summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/__init__.py2
-rw-r--r--python/architecture.py58
-rw-r--r--python/associateddatastore.py2
-rw-r--r--python/basicblock.py2
-rw-r--r--python/binaryview.py18
-rw-r--r--python/callingconvention.py2
-rw-r--r--python/databuffer.py2
-rw-r--r--python/demangle.py6
-rw-r--r--python/examples/angr_plugin.py2
-rw-r--r--python/examples/bin_info.py3
-rw-r--r--python/examples/breakpoint.py2
-rwxr-xr-xpython/examples/export_svg.py18
-rw-r--r--python/examples/instruction_iterator.py2
-rw-r--r--python/examples/jump_table.py2
-rw-r--r--python/examples/nds.py2
-rw-r--r--python/examples/nes.py51
-rw-r--r--python/examples/nsf.py2
-rw-r--r--python/examples/print_syscalls.py2
-rw-r--r--python/examples/version_switcher.py2
-rw-r--r--python/fileaccessor.py2
-rw-r--r--python/filemetadata.py2
-rw-r--r--python/function.py34
-rw-r--r--python/functionrecognizer.py2
-rw-r--r--python/generator.cpp2
-rw-r--r--python/highlight.py2
-rw-r--r--python/interaction.py18
-rw-r--r--python/lineardisassembly.py2
-rw-r--r--python/log.py10
-rw-r--r--python/lowlevelil.py295
-rw-r--r--python/mainthread.py2
-rw-r--r--python/mediumlevelil.py222
-rw-r--r--python/platform.py2
-rw-r--r--python/plugin.py2
-rw-r--r--python/pluginmanager.py2
-rw-r--r--python/scriptingprovider.py8
-rw-r--r--python/startup.py2
-rw-r--r--python/transform.py2
-rw-r--r--python/types.py14
-rw-r--r--python/undoaction.py2
-rw-r--r--python/update.py2
40 files changed, 549 insertions, 260 deletions
diff --git a/python/__init__.py b/python/__init__.py
index c7c5f768..4f58a6db 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/architecture.py b/python/architecture.py
index d3778613..34f2ca35 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -651,11 +651,11 @@ class Architecture(object):
operand_list = []
for i in xrange(operand_count):
if operands[i].constant:
- operand_list.append(("const", operands[i].value))
+ operand_list.append(operands[i].value)
elif lowlevelil.LLIL_REG_IS_TEMP(operands[i].reg):
- operand_list.append(("reg", operands[i].reg))
+ operand_list.append(lowlevelil.ILRegister(self, operands[i].reg))
else:
- operand_list.append(("reg", self._regs_by_index[operands[i].reg]))
+ operand_list.append(lowlevelil.ILRegister(self, operands[i].reg))
return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list,
lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index
except (KeyError, OSError):
@@ -915,7 +915,10 @@ class Architecture(object):
:param LowLevelILFunction il:
:rtype: LowLevelILExpr
"""
- return il.unimplemented()
+ flag = self.get_flag_index(flag)
+ if flag not in self._flag_roles:
+ return il.unimplemented()
+ return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il)
@abc.abstractmethod
def perform_get_flag_condition_low_level_il(self, cond, il):
@@ -927,7 +930,7 @@ class Architecture(object):
:param LowLevelILFunction il:
:rtype: LowLevelILExpr
"""
- return il.unimplemented()
+ return self.get_default_flag_condition_low_level_il(cond, il)
@abc.abstractmethod
def perform_assemble(self, code, addr):
@@ -1232,6 +1235,20 @@ class Architecture(object):
"""
return core.BNGetArchitectureFlagName(self.handle, flag)
+ def get_reg_index(self, reg):
+ if isinstance(reg, str):
+ return self.regs[reg].index
+ elif isinstance(reg, lowlevelil.ILRegister):
+ return reg.index
+ return reg
+
+ def get_flag_index(self, flag):
+ if isinstance(flag, str):
+ return self._flags[flag]
+ elif isinstance(flag, lowlevelil.ILFlag):
+ return flag.index
+ return flag
+
def get_flag_write_type_name(self, write_type):
"""
``get_flag_write_type_name`` gets the flag write type name for the given flag.
@@ -1262,7 +1279,7 @@ class Architecture(object):
"""
return self._flag_write_types[write_type]
- def get_flag_write_low_level_il(self, op, size, write_type, operands, il):
+ def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
"""
:param LowLevelILOperation op:
:param int size:
@@ -1272,22 +1289,26 @@ class Architecture(object):
:param LowLevelILFunction il:
:rtype: LowLevelILExpr
"""
+ flag = self.get_flag_index(flag)
operand_list = (core.BNRegisterOrConstant * len(operands))()
for i in xrange(len(operands)):
if isinstance(operands[i], str):
operand_list[i].constant = False
- operand_list[i].reg = self._flags[operands[i]]
+ operand_list[i].reg = self.regs[operands[i]]
+ elif isinstance(operands[i], lowlevelil.ILRegister):
+ operand_list[i].constant = False
+ operand_list[i].reg = operands[i].index
else:
operand_list[i].constant = True
operand_list[i].value = operands[i]
return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size,
- self._flag_write_types[write_type], operand_list, len(operand_list), il.handle))
+ self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle))
- def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il):
+ def get_default_flag_write_low_level_il(self, op, size, role, operands, il):
"""
:param LowLevelILOperation op:
:param int size:
- :param str write_type:
+ :param FlagRole role:
:param list(str or int) operands: a list of either items that are either string register names or constant \
integer values
:param LowLevelILFunction il:
@@ -1297,12 +1318,15 @@ class Architecture(object):
for i in xrange(len(operands)):
if isinstance(operands[i], str):
operand_list[i].constant = False
- operand_list[i].reg = self._flags[operands[i]]
+ operand_list[i].reg = self.regs[operands[i]]
+ elif isinstance(operands[i], lowlevelil.ILRegister):
+ operand_list[i].constant = False
+ operand_list[i].reg = operands[i].index
else:
operand_list[i].constant = True
operand_list[i].value = operands[i]
return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size,
- self._flag_write_types[write_type], operand_list, len(operand_list), il.handle))
+ role, operand_list, len(operand_list), il.handle))
def get_flag_condition_low_level_il(self, cond, il):
"""
@@ -1312,6 +1336,14 @@ class Architecture(object):
"""
return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle))
+ def get_default_flag_condition_low_level_il(self, cond, il):
+ """
+ :param LowLevelILFlagCondition cond:
+ :param LowLevelILFunction il:
+ :rtype: LowLevelILExpr
+ """
+ return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle))
+
def get_modified_regs_on_write(self, reg):
"""
``get_modified_regs_on_write`` returns a list of register names that are modified when ``reg`` is written.
diff --git a/python/associateddatastore.py b/python/associateddatastore.py
index 6b5e688e..c9b35ee0 100644
--- a/python/associateddatastore.py
+++ b/python/associateddatastore.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/basicblock.py b/python/basicblock.py
index 5bec391b..3dc5b050 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/binaryview.py b/python/binaryview.py
index 042c08f5..8165c592 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -641,7 +641,7 @@ class BinaryView(object):
@classmethod
def set_default_session_data(cls, name, value):
"""
- ```set_default_session_data``` saves a variable to the BinaryView.
+ ``set_default_session_data`` saves a variable to the BinaryView.
:param name: name of the variable to be saved
:param value: value of the variable to be saved
@@ -1329,7 +1329,7 @@ class BinaryView(object):
def perform_is_offset_executable(self, addr):
"""
- ``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is executable.
+ ``perform_is_offset_executable`` implements a check if a virtual address ``addr`` is executable.
.. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
data without overriding this method.
@@ -1410,7 +1410,7 @@ class BinaryView(object):
def create_database(self, filename, progress_func=None):
"""
- ``perform_get_database`` writes the current database (.bndb) file out to the specified file.
+ ``create_database`` writes the current database (.bndb) file out to the specified file.
:param str filename: path and filename to write the bndb to, this string `should` have ".bndb" appended to it.
:param callable() progress_func: optional function to be called with the current progress and total count.
@@ -1851,7 +1851,7 @@ class BinaryView(object):
def define_user_data_var(self, addr, var_type):
"""
- ``define_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``.
+ ``define_user_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``.
:param int addr: virtual address to define the given data variable
:param binaryninja.Type var_type: type to be defined at the given virtual address
@@ -1881,7 +1881,7 @@ class BinaryView(object):
def undefine_user_data_var(self, addr):
"""
- ``undefine_data_var`` removes the user data variable at the virtual address ``addr``.
+ ``undefine_user_data_var`` removes the user data variable at the virtual address ``addr``.
:param int addr: virtual address to define the data variable to be removed
:rtype: None
@@ -2145,6 +2145,8 @@ class BinaryView(object):
"""
``define_auto_symbol`` adds a symbol to the internal list of automatically discovered Symbol objects.
+ .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used.
+
:param Symbol sym: the symbol to define
:rtype: None
"""
@@ -2154,6 +2156,8 @@ class BinaryView(object):
"""
``define_auto_symbol_and_var_or_function``
+ .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used.
+
:param Symbol sym: the symbol to define
:param SymbolType sym_type: Type of symbol being defined
:param Platform plat: (optional) platform
@@ -2180,6 +2184,8 @@ class BinaryView(object):
"""
``define_user_symbol`` adds a symbol to the internal list of user added Symbol objects.
+ .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used.
+
:param Symbol sym: the symbol to define
:rtype: None
"""
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 04ba711f..4c87eef6 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/databuffer.py b/python/databuffer.py
index 6b3423da..3f9e4ce5 100644
--- a/python/databuffer.py
+++ b/python/databuffer.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/demangle.py b/python/demangle.py
index ed38674a..11673263 100644
--- a/python/demangle.py
+++ b/python/demangle.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -48,8 +48,8 @@ def demangle_ms(arch, mangled_name):
:param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes.
:param str mangled_name: a mangled Microsoft Visual Studio C++ name
- :return: returns a Type object for the mangled name
- :rtype: Type
+ :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error
+ :rtype: Tuple
:Example:
>>> demangle_ms(Architecture["x86_64"], "?testf@Foobar@@SA?AW4foo@1@W421@@Z")
diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py
index 90217d65..c84373be 100644
--- a/python/examples/angr_plugin.py
+++ b/python/examples/angr_plugin.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py
index 4c4ab8fd..17a96685 100644
--- a/python/examples/bin_info.py
+++ b/python/examples/bin_info.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -38,7 +38,6 @@ def get_bininfo(bv):
sys.exit(1)
bv = BinaryViewType.get_view_of_file(filename)
- log.redirect_output_to_log()
log.log_to_stdout(True)
contents = "## %s ##\n" % bv.file.filename
diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py
index b1297e26..a2801511 100644
--- a/python/examples/breakpoint.py
+++ b/python/examples/breakpoint.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py
index 95e2d62d..7814c9fd 100755
--- a/python/examples/export_svg.py
+++ b/python/examples/export_svg.py
@@ -1,6 +1,7 @@
# from binaryninja import *
import os
import webbrowser
+import time
try:
from urllib import pathname2url # Python 2.x
except:
@@ -34,7 +35,7 @@ def save_svg(bv, function):
outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename)
if outputfile is None:
return
- content = render_svg(function)
+ content = render_svg(function, origname)
output = open(outputfile, 'w')
output.write(content)
output.close()
@@ -54,7 +55,7 @@ def instruction_data_flow(function, address):
return 'Opcode: {bytes}'.format(bytes=padded)
-def render_svg(function):
+def render_svg(function, origname):
graph = function.create_graph()
graph.layout_and_wait()
heightconst = 15
@@ -67,7 +68,13 @@ def render_svg(function):
@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro);
body {
background-color: rgb(42, 42, 42);
+ color: rgb(220, 220, 220);
+ font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace;
}
+ a, a:visited {
+ color: rgb(200, 200, 200);
+ font-weight: bold;
+ }
svg {
background-color: rgb(42, 42, 42);
display: block;
@@ -101,7 +108,7 @@ def render_svg(function):
fill: currentColor;
}
text {
- font-family: 'Source Code Pro';
+ font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace;
font-size: 9pt;
fill: rgb(224, 224, 224);
}
@@ -207,7 +214,10 @@ def render_svg(function):
edges += ' <polyline class="edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(type=BranchType(edge.type).name, points=points)
output += ' ' + edges + '\n'
output += ' </g>\n'
- output += '</svg></html>'
+ output += '</svg>'
+
+ output += '<p>This CFG generated by <a href="https://binary.ninja/">Binary Ninja</a> from {filename} on {timestring}.</p>'.format(filename = origname, timestring = time.strftime("%c"))
+ output += '</html>'
return output
diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py
index 7ff2d692..f55e1c1b 100644
--- a/python/examples/instruction_iterator.py
+++ b/python/examples/instruction_iterator.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py
index 439e2ab6..419cc188 100644
--- a/python/examples/jump_table.py
+++ b/python/examples/jump_table.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/nds.py b/python/examples/nds.py
index ff137b4b..34d8a292 100644
--- a/python/examples/nds.py
+++ b/python/examples/nds.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/nes.py b/python/examples/nes.py
index 4122cde0..e55a90b7 100644
--- a/python/examples/nes.py
+++ b/python/examples/nes.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -191,21 +191,21 @@ OperandTokens = [
def indirect_load(il, value):
if (value & 0xff) == 0xff:
- lo_addr = il.const(2, value)
- hi_addr = il.const(2, (value & 0xff00) | ((value + 1) & 0xff))
+ lo_addr = il.const_pointer(2, value)
+ hi_addr = il.const_pointer(2, (value & 0xff00) | ((value + 1) & 0xff))
lo = il.zero_extend(2, il.load(1, lo_addr))
hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8))
return il.or_expr(2, lo, hi)
- return il.load(2, il.const(2, value))
+ return il.load(2, il.const_pointer(2, value))
def load_zero_page_16(il, value):
if il[value].operation == LowLevelILOperation.LLIL_CONST:
- if il[value].value == 0xff:
- lo = il.zero_extend(2, il.load(1, il.const(2, 0xff)))
- hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const(2, 0)), il.const(2, 8)))
+ if il[value].constant == 0xff:
+ lo = il.zero_extend(2, il.load(1, il.const_pointer(2, 0xff)))
+ hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const_pointer(2, 0)), il.const(2, 8)))
return il.or_expr(2, lo, hi)
- return il.load(2, il.const(2, il[value].value))
+ return il.load(2, il.const_pointer(2, il[value].constant))
il.append(il.set_reg(1, LLIL_TEMP(0), value))
value = il.reg(1, LLIL_TEMP(0))
lo_addr = value
@@ -217,23 +217,23 @@ def load_zero_page_16(il, value):
OperandIL = [
lambda il, value: None, # NONE
- lambda il, value: il.load(1, il.const(2, value)), # ABS
+ lambda il, value: il.load(1, il.const_pointer(2, value)), # ABS
lambda il, value: il.const(2, value), # ABS_DEST
lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x")))), # ABS_X
lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x"))), # ABS_X_DEST
lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y")))), # ABS_Y
lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y"))), # ABS_Y_DEST
lambda il, value: il.reg(1, "a"), # ACCUM
- lambda il, value: il.const(2, value), # ADDR
+ lambda il, value: il.const_pointer(2, value), # ADDR
lambda il, value: il.const(1, value), # IMMED
lambda il, value: indirect_load(il, value), # IND
lambda il, value: il.load(1, load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x")))), # IND_X
lambda il, value: load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x"))), # IND_X_DEST
lambda il, value: il.load(1, il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y"))), # IND_Y
lambda il, value: il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y")), # IND_Y_DEST
- lambda il, value: il.const(2, value), # REL
- lambda il, value: il.load(1, il.const(2, value)), # ZERO
- lambda il, value: il.const(2, value), # ZERO_DEST
+ lambda il, value: il.const_pointer(2, value), # REL
+ lambda il, value: il.load(1, il.const_pointer(2, value)), # ZERO
+ lambda il, value: il.const_pointer(2, value), # ZERO_DEST
lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x")))), # ZERO_X
lambda il, value: il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x"))), # ZERO_X_DEST
lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "y")))), # ZERO_Y
@@ -244,7 +244,7 @@ OperandIL = [
def cond_branch(il, cond, dest):
t = None
if il[dest].operation == LowLevelILOperation.LLIL_CONST:
- t = il.get_label_for_address(Architecture['6502'], il[dest].value)
+ t = il.get_label_for_address(Architecture['6502'], il[dest].constant)
if t is None:
t = LowLevelILLabel()
indirect = True
@@ -262,7 +262,7 @@ def cond_branch(il, cond, dest):
def jump(il, dest):
label = None
if il[dest].operation == LowLevelILOperation.LLIL_CONST:
- label = il.get_label_for_address(Architecture['6502'], il[dest].value)
+ label = il.get_label_for_address(Architecture['6502'], il[dest].constant)
if label is None:
il.append(il.jump(dest))
else:
@@ -300,7 +300,7 @@ def rti(il):
InstructionIL = {
- "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, flags = "*")),
+ "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")),
"asl": lambda il, operand: il.store(1, operand, il.shift_left(1, il.load(1, operand), il.const(1, 1), flags = "czs")),
"asl@": lambda il, operand: il.set_reg(1, "a", il.shift_left(1, operand, il.const(1, 1), flags = "czs")),
"and": lambda il, operand: il.set_reg(1, "a", il.and_expr(1, il.reg(1, "a"), operand, flags = "zs")),
@@ -341,13 +341,13 @@ InstructionIL = {
"php": lambda il, operand: il.push(1, get_p_value(il)),
"pla": lambda il, operand: il.set_reg(1, "a", il.pop(1), flags = "zs"),
"plp": lambda il, operand: set_p_value(il, il.pop(1)),
- "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")),
- "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")),
- "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")),
- "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")),
+ "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")),
+ "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")),
+ "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")),
+ "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")),
"rti": lambda il, operand: rti(il),
"rts": lambda il, operand: il.ret(il.add(2, il.pop(2), il.const(2, 1))),
- "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, flags = "*")),
+ "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")),
"sec": lambda il, operand: il.set_flag("c", il.const(0, 1)),
"sed": lambda il, operand: il.set_flag("d", il.const(0, 1)),
"sei": lambda il, operand: il.set_flag("i", il.const(0, 1)),
@@ -469,6 +469,15 @@ class M6502(Architecture):
return length
+ def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
+ if flag == 'c':
+ if (op == LowLevelILOperation.LLIL_SUB) or (op == LowLevelILOperation.LLIL_SBB):
+ # Subtraction carry flag is inverted from the commom implementation
+ return il.not_expr(0, self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il))
+ # Other operations use a normal carry flag
+ return self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il)
+ return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il)
+
def perform_is_never_branch_patch_available(self, data, addr):
if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"):
return True
diff --git a/python/examples/nsf.py b/python/examples/nsf.py
index b1bac3a8..b0164065 100644
--- a/python/examples/nsf.py
+++ b/python/examples/nsf.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py
index 2af4d38d..d995ad1e 100644
--- a/python/examples/print_syscalls.py
+++ b/python/examples/print_syscalls.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py
index 9d5bbf05..3e1cab40 100644
--- a/python/examples/version_switcher.py
+++ b/python/examples/version_switcher.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/fileaccessor.py b/python/fileaccessor.py
index 8fec43a1..2c1f1d19 100644
--- a/python/fileaccessor.py
+++ b/python/fileaccessor.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/filemetadata.py b/python/filemetadata.py
index b489d5bb..4bfc0214 100644
--- a/python/filemetadata.py
+++ b/python/filemetadata.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/function.py b/python/function.py
index d54cf25a..34511cfa 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -205,11 +205,15 @@ class Variable(object):
class ConstantReference(object):
- def __init__(self, val, size):
+ def __init__(self, val, size, ptr, intermediate):
self.value = val
self.size = size
+ self.pointer = ptr
+ self.intermediate = intermediate
def __repr__(self):
+ if self.pointer:
+ return "<constant pointer %#x>" % self.value
if self.size == 0:
return "<constant %#x>" % self.value
return "<constant %#x size %d>" % (self.value, self.size)
@@ -426,6 +430,16 @@ class Function(object):
else:
return Function._associated_data[handle.value]
+ @property
+ def analysis_performance_info(self):
+ count = ctypes.c_ulonglong()
+ info = core.BNGetFunctionAnalysisPerformanceInfo(self.handle, count)
+ result = {}
+ for i in xrange(0, count.value):
+ result[info[i].name] = info[i].seconds
+ core.BNFreeAnalysisPerformanceInfo(info, count.value)
+ return result
+
def __iter__(self):
count = ctypes.c_ulonglong()
blocks = core.BNGetFunctionBasicBlockList(self.handle, count)
@@ -500,8 +514,7 @@ class Function(object):
"""
if arch is None:
arch = self.arch
- if isinstance(reg, str):
- reg = arch.regs[reg].index
+ reg = arch.get_reg_index(reg)
value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg)
result = RegisterValue(arch, value)
return result
@@ -521,8 +534,7 @@ class Function(object):
"""
if arch is None:
arch = self.arch
- if isinstance(reg, str):
- reg = arch.regs[reg].index
+ reg = arch.get_reg_index(reg)
value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg)
result = RegisterValue(arch, value)
return result
@@ -618,7 +630,7 @@ class Function(object):
refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count)
result = []
for i in xrange(0, count.value):
- result.append(ConstantReference(refs[i].value, refs[i].size))
+ result.append(ConstantReference(refs[i].value, refs[i].size, refs[i].pointer, refs[i].intermediate))
core.BNFreeConstantReferenceList(refs)
return result
@@ -628,8 +640,7 @@ class Function(object):
return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)]
def get_lifted_il_flag_uses_for_definition(self, i, flag):
- if isinstance(flag, str):
- flag = self.arch._flags[flag]
+ flag = self.arch.get_flag_index(flag)
count = ctypes.c_ulonglong()
instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count)
result = []
@@ -639,8 +650,7 @@ class Function(object):
return result
def get_lifted_il_flag_definitions_for_use(self, i, flag):
- if isinstance(flag, str):
- flag = self.arch._flags[flag]
+ flag = self.arch.get_flag_index(flag)
count = ctypes.c_ulonglong()
instrs = core.BNGetLiftedILFlagDefinitionsForUse(self.handle, i, flag, count)
result = []
@@ -743,7 +753,7 @@ class Function(object):
:param int instr_addr:
:param int value:
:param int operand:
- :param IntegerDisplayTypeEnum display_type:
+ :param enums.IntegerDisplayType display_type:
:param Architecture arch: (optional)
"""
if arch is None:
diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py
index 960aee2f..8514a2ee 100644
--- a/python/functionrecognizer.py
+++ b/python/functionrecognizer.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/generator.cpp b/python/generator.cpp
index 1c0e7b16..6f19db66 100644
--- a/python/generator.cpp
+++ b/python/generator.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2016 Vector 35 LLC
+// Copyright (c) 2015-2017 Vector 35 LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
diff --git a/python/highlight.py b/python/highlight.py
index 6af1cf95..96bc543d 100644
--- a/python/highlight.py
+++ b/python/highlight.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/interaction.py b/python/interaction.py
index 6d640d17..60607692 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -23,7 +23,7 @@ import traceback
# Binary Ninja components
import _binaryninjacore as core
-from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonResult
+from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult
import binaryview
import log
@@ -517,5 +517,17 @@ def get_form_input(fields, title):
return True
-def show_message_box(title, text, buttons = MessageBoxButtonResult.OKButton, icon = MessageBoxIcon.InformationIcon):
+def show_message_box(title, text, buttons = MessageBoxButtonSet.OKButtonSet, icon = MessageBoxIcon.InformationIcon):
+ """
+ ``show_message_box`` Displays a configurable message box in the UI, or prompts on the console as appropriate
+ retrieves a list of all Symbol objects of the provided symbol type in the optionally
+ provided range.
+
+ :param str title: Text title for the message box.
+ :param str text: Text for the main body of the message box.
+ :param MessageBoxButtonSet buttons: One of :py:class:`MessageBoxButtonSet`
+ :param MessageBoxIcon icon: One of :py:class:`MessageBoxIcon`
+ :return: Which button was selected
+ :rtype: MessageBoxButtonResult
+ """
return core.BNShowMessageBox(title, text, buttons, icon)
diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py
index 9b88b78a..5ef8d623 100644
--- a/python/lineardisassembly.py
+++ b/python/lineardisassembly.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/log.py b/python/log.py
index 45adb4aa..f7144183 100644
--- a/python/log.py
+++ b/python/log.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -23,11 +23,19 @@
import _binaryninjacore as core
+_output_to_log = False
+
+
def redirect_output_to_log():
global _output_to_log
_output_to_log = True
+def is_output_redirected_to_log():
+ global _output_to_log
+ return _output_to_log
+
+
def log(level, text):
"""
``log`` writes messages to the log console for the given log level.
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 3634cca2..d1a76a2a 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -37,6 +37,73 @@ class LowLevelILLabel(object):
self.handle = handle
+class ILRegister(object):
+ def __init__(self, arch, reg):
+ self.arch = arch
+ self.index = reg
+ self.temp = (self.index & 0x80000000) != 0
+ if self.temp:
+ self.name = "temp%d" % (self.index & 0x7fffffff)
+ else:
+ self.name = self.arch.get_reg_name(self.index)
+
+ @property
+ def info(self):
+ return self.arch.regs[self.name]
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+
+class ILFlag(object):
+ def __init__(self, arch, flag):
+ self.arch = arch
+ self.index = flag
+ self.temp = (self.index & 0x80000000) != 0
+ if self.temp:
+ self.name = "cond:%d" % (self.index & 0x7fffffff)
+ else:
+ self.name = self.arch.get_flag_name(self.index)
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+
+class SSARegister(object):
+ def __init__(self, reg, version):
+ self.reg = reg
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.reg), self.version)
+
+
+class SSAFlag(object):
+ def __init__(self, flag, version):
+ self.flag = flag
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.flag), self.version)
+
+
+class LowLevelILOperationAndSize(object):
+ def __init__(self, operation, size):
+ self.operation = operation
+ self.size = size
+
+ def __repr__(self):
+ if self.size == 0:
+ return "<%s>" % self.operation.name
+ return "<%s %d>" % (self.operation.name, self.size)
+
+
class LowLevelILInstruction(object):
"""
``class LowLevelILInstruction`` Low Level Intermediate Language Instructions are infinite length tree-based
@@ -55,12 +122,13 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_POP: [],
LowLevelILOperation.LLIL_REG: [("src", "reg")],
LowLevelILOperation.LLIL_CONST: [("constant", "int")],
+ LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")],
LowLevelILOperation.LLIL_FLAG: [("src", "flag")],
LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")],
LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
LowLevelILOperation.LLIL_SUB: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
LowLevelILOperation.LLIL_AND: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_OR: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_XOR: [("left", "expr"), ("right", "expr")],
@@ -68,9 +136,9 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_LSR: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_ASR: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_ROL: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
LowLevelILOperation.LLIL_ROR: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
LowLevelILOperation.LLIL_MUL: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
@@ -86,6 +154,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_NOT: [("src", "expr")],
LowLevelILOperation.LLIL_SX: [("src", "expr")],
LowLevelILOperation.LLIL_ZX: [("src", "expr")],
+ LowLevelILOperation.LLIL_LOW_PART: [("src", "expr")],
LowLevelILOperation.LLIL_JUMP: [("dest", "expr")],
LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")],
LowLevelILOperation.LLIL_CALL: [("dest", "expr")],
@@ -112,24 +181,24 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_UNDEF: [],
LowLevelILOperation.LLIL_UNIMPL: [],
LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")],
- LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")],
- LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg_ssa"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")],
- LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")],
- LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")],
- LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")],
- LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")],
- LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")],
- LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")],
+ LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "reg")],
+ LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag_ssa"), ("src", "expr")],
+ LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag_ssa")],
+ LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag_ssa"), ("bit", "int")],
LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")],
LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")],
LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")],
- LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")],
+ LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")],
LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")],
LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
- LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg"), ("index", "int"), ("src", "reg_ssa_list")],
- LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")],
+ LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")],
LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
}
@@ -150,27 +219,31 @@ class LowLevelILInstruction(object):
self.source_operand = None
operands = LowLevelILInstruction.ILOperations[instr.operation]
self.operands = []
- for i in xrange(0, len(operands)):
- name, operand_type = operands[i]
+ i = 0
+ for operand in operands:
+ name, operand_type = operand
if operand_type == "int":
value = instr.operands[i]
elif operand_type == "expr":
value = LowLevelILInstruction(func, instr.operands[i])
elif operand_type == "reg":
- if (instr.operands[i] & 0x80000000) != 0:
- value = instr.operands[i]
- else:
- value = func.arch.get_reg_name(instr.operands[i])
+ value = ILRegister(func.arch, instr.operands[i])
+ elif operand_type == "reg_ssa":
+ reg = ILRegister(func.arch, instr.operands[i])
+ i += 1
+ value = SSARegister(reg, instr.operands[i])
elif operand_type == "flag":
- if (instr.operands[i] & 0x80000000) != 0:
- value = instr.operands[i]
- else:
- value = func.arch.get_flag_name(instr.operands[i])
+ value = ILFlag(func.arch, instr.operands[i])
+ elif operand_type == "flag_ssa":
+ flag = ILFlag(func.arch, instr.operands[i])
+ i += 1
+ value = SSAFlag(flag, instr.operands[i])
elif operand_type == "cond":
value = LowLevelILFlagCondition(instr.operands[i])
elif operand_type == "int_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
value = []
for i in xrange(count.value):
value.append(operand_list[i])
@@ -178,27 +251,26 @@ class LowLevelILInstruction(object):
elif operand_type == "reg_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
value = []
for i in xrange(count.value / 2):
reg = operand_list[i * 2]
- reg_index = operand_list[(i * 2) + 1]
- if (reg & 0x80000000) == 0:
- reg = func.arch.get_reg_name(reg)
- value.append((reg, reg_index))
+ reg_version = operand_list[(i * 2) + 1]
+ value.append(SSARegister(ILRegister(func.arch, reg), reg_version))
core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "flag_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
value = []
for i in xrange(count.value / 2):
flag = operand_list[i * 2]
- flag_index = operand_list[(i * 2) + 1]
- if (flag & 0x80000000) == 0:
- flag = func.arch.get_flag_name(flag)
- value.append((flag, flag_index))
+ flag_version = operand_list[(i * 2) + 1]
+ value.append(SSAFlag(ILFlag(func.arch, flag), flag_version))
core.BNLowLevelILFreeOperandList(operand_list)
self.operands.append(value)
self.__dict__[name] = value
+ i += 1
def __str__(self):
tokens = self.tokens
@@ -273,61 +345,76 @@ class LowLevelILInstruction(object):
core.BNFreePossibleValueSet(value)
return result
+ @property
+ def prefix_operands(self):
+ """All operands in the expression tree in prefix order"""
+ result = [LowLevelILOperationAndSize(self.operation, self.size)]
+ for operand in self.operands:
+ if isinstance(operand, LowLevelILInstruction):
+ result += operand.prefix_operands
+ else:
+ result.append(operand)
+ return result
+
+ @property
+ def postfix_operands(self):
+ """All operands in the expression tree in postfix order"""
+ result = []
+ for operand in self.operands:
+ if isinstance(operand, LowLevelILInstruction):
+ result += operand.postfix_operands
+ else:
+ result.append(operand)
+ result.append(LowLevelILOperationAndSize(self.operation, self.size))
+ return result
+
def get_reg_value(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_reg_value_after(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_possible_reg_values(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_possible_reg_values_after(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_flag_value(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_flag_value_after(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_possible_flag_values(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_possible_flag_values_after(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
@@ -589,8 +676,7 @@ class LowLevelILFunction(object):
:return: The expression ``reg = value``
:rtype: LowLevelILExpr
"""
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
+ reg = self.arch.get_reg_index(reg)
return self.expr(LowLevelILOperation.LLIL_SET_REG, reg, value.index, size = size, flags = flags)
def set_reg_split(self, size, hi, lo, value, flags = 0):
@@ -606,10 +692,8 @@ class LowLevelILFunction(object):
:return: The expression ``hi:lo = value``
:rtype: LowLevelILExpr
"""
- if isinstance(hi, str):
- hi = self.arch.regs[hi].index
- if isinstance(lo, str):
- lo = self.arch.regs[lo].index
+ hi = self.arch.get_reg_index(hi)
+ lo = self.arch.get_reg_index(lo)
return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags)
def set_flag(self, flag, value):
@@ -676,8 +760,7 @@ class LowLevelILFunction(object):
:return: A register expression for the given string
:rtype: LowLevelILExpr
"""
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
+ reg = self.arch.get_reg_index(reg)
return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size)
def const(self, size, value):
@@ -691,6 +774,17 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_CONST, value, size=size)
+ def const_pointer(self, size, value):
+ """
+ ``const_pointer`` returns an expression for the constant pointer ``value`` with size ``size``
+
+ :param int size: the size of the pointer in bytes
+ :param int value: address referenced by pointer
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size)
+
def flag(self, reg):
"""
``flag`` returns a flag expression for the given flag name.
@@ -727,7 +821,7 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_ADD, a.index, b.index, size=size, flags=flags)
- def add_carry(self, size, a, b, flags=None):
+ def add_carry(self, size, a, b, carry, flags=None):
"""
``add_carry`` adds with carry expression ``a`` to expression ``b`` potentially setting flags ``flags`` and
returning an expression of ``size`` bytes.
@@ -735,11 +829,12 @@ class LowLevelILFunction(object):
:param int size: the size of the result in bytes
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
+ :param LowLevelILExpr carry: Carry flag expression
:param str flags: flags to set
- :return: The expression ``adc.<size>{<flags>}(a, b)``
+ :return: The expression ``adc.<size>{<flags>}(a, b, carry)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, carry.index, size=size, flags=flags)
def sub(self, size, a, b, flags=None):
"""
@@ -755,7 +850,7 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_SUB, a.index, b.index, size=size, flags=flags)
- def sub_borrow(self, size, a, b, flags=None):
+ def sub_borrow(self, size, a, b, carry, flags=None):
"""
``sub_borrow`` subtracts with borrow expression ``b`` from expression ``a`` potentially setting flags ``flags``
and returning an expression of ``size`` bytes.
@@ -763,11 +858,12 @@ class LowLevelILFunction(object):
:param int size: the size of the result in bytes
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
+ :param LowLevelILExpr carry: Carry flag expression
:param str flags: flags to set
- :return: The expression ``sbc.<size>{<flags>}(a, b)``
+ :return: The expression ``sbb.<size>{<flags>}(a, b, carry)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, carry.index, size=size, flags=flags)
def and_expr(self, size, a, b, flags=None):
"""
@@ -867,7 +963,7 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_ROL, a.index, b.index, size=size, flags=flags)
- def rotate_left_carry(self, size, a, b, flags=None):
+ def rotate_left_carry(self, size, a, b, carry, flags=None):
"""
``rotate_left_carry`` bitwise rotates left with carry expression ``a`` by expression ``b`` potentially setting
flags ``flags`` and returning an expression of ``size`` bytes.
@@ -875,11 +971,12 @@ class LowLevelILFunction(object):
:param int size: the size of the result in bytes
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
+ :param LowLevelILExpr carry: Carry flag expression
:param str flags: optional, flags to set
- :return: The expression ``rcl.<size>{<flags>}(a, b)``
+ :return: The expression ``rlc.<size>{<flags>}(a, b, carry)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, carry.index, size=size, flags=flags)
def rotate_right(self, size, a, b, flags=None):
"""
@@ -895,7 +992,7 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_ROR, a.index, b.index, size=size, flags=flags)
- def rotate_right_carry(self, size, a, b, flags=None):
+ def rotate_right_carry(self, size, a, b, carry, flags=None):
"""
``rotate_right_carry`` bitwise rotates right with carry expression ``a`` by expression ``b`` potentially setting
flags ``flags`` and returning an expression of ``size`` bytes.
@@ -903,11 +1000,12 @@ class LowLevelILFunction(object):
:param int size: the size of the result in bytes
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
+ :param LowLevelILExpr carry: Carry flag expression
:param str flags: optional, flags to set
- :return: The expression ``rcr.<size>{<flags>}(a, b)``
+ :return: The expression ``rrc.<size>{<flags>}(a, b, carry)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, carry.index, size=size, flags=flags)
def mult(self, size, a, b, flags=None):
"""
@@ -1107,7 +1205,7 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_SX, value.index, size=size, flags=flags)
- def zero_extend(self, size, value):
+ def zero_extend(self, size, value, flags=None):
"""
``zero_extend`` zero-extends the expression in ``value`` to ``size`` bytes
@@ -1116,7 +1214,18 @@ class LowLevelILFunction(object):
:return: The expression ``sx.<size>(value)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size)
+ return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags)
+
+ def low_part(self, size, value, flags=None):
+ """
+ ``low_part`` truncates ``value`` to ``size`` bytes
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to zero extend
+ :return: The expression ``(value).<size>``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_LOW_PART, value.index, size=size, flags=flags)
def jump(self, dest):
"""
@@ -1477,18 +1586,16 @@ class LowLevelILFunction(object):
def get_non_ssa_instruction_index(self, instr):
return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr)
- def get_ssa_reg_definition(self, reg, index):
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
- result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index)
+ def get_ssa_reg_definition(self, reg_ssa):
+ reg = self.arch.get_reg_index(reg_ssa.reg)
+ result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, reg_ssa.version)
if result >= core.BNGetLowLevelILInstructionCount(self.handle):
return None
return result
- def get_ssa_flag_definition(self, flag, index):
- if isinstance(flag, str):
- flag = self.arch.get_flag_by_name(flag)
- result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index)
+ def get_ssa_flag_definition(self, flag_ssa):
+ flag = self.arch.get_flag_index(flag_ssa.flag)
+ result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, flag_ssa.version)
if result >= core.BNGetLowLevelILInstructionCount(self.handle):
return None
return result
@@ -1499,22 +1606,20 @@ class LowLevelILFunction(object):
return None
return result
- def get_ssa_reg_uses(self, reg, index):
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
+ def get_ssa_reg_uses(self, reg_ssa):
+ reg = self.arch.get_reg_index(reg_ssa.reg)
count = ctypes.c_ulonglong()
- instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count)
+ instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, reg_ssa.version, count)
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
core.BNFreeILInstructionList(instrs)
return result
- def get_ssa_flag_uses(self, flag, index):
- if isinstance(flag, str):
- flag = self.arch.get_flag_by_name(flag)
+ def get_ssa_flag_uses(self, flag_ssa):
+ flag = self.arch.get_flag_index(flag_ssa.flag)
count = ctypes.c_ulonglong()
- instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count)
+ instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, flag_ssa.version, count)
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
@@ -1530,17 +1635,15 @@ class LowLevelILFunction(object):
core.BNFreeILInstructionList(instrs)
return result
- def get_ssa_reg_value(self, reg, index):
- if isinstance(reg, str):
- reg = self.arch.regs[reg].index
- value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index)
+ def get_ssa_reg_value(self, reg_ssa):
+ reg = self.arch.get_reg_index(reg_ssa.reg)
+ value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, reg_ssa.version)
result = function.RegisterValue(self.arch, value)
return result
- def get_ssa_flag_value(self, flag, index):
- if isinstance(flag, str):
- flag = self.arch.get_flag_by_name(flag)
- value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index)
+ def get_ssa_flag_value(self, flag_ssa):
+ flag = self.arch.get_flag_index(flag_ssa.flag)
+ value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, flag_ssa.version)
result = function.RegisterValue(self.arch, value)
return result
diff --git a/python/mainthread.py b/python/mainthread.py
index 220f0b64..3e12bd65 100644
--- a/python/mainthread.py
+++ b/python/mainthread.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index f205714e..4aacad00 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -28,6 +28,15 @@ import basicblock
import lowlevelil
+class SSAVariable(object):
+ def __init__(self, var, version):
+ self.var = var
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.var), self.version)
+
+
class MediumLevelILLabel(object):
def __init__(self, handle = None):
if handle is None:
@@ -37,6 +46,17 @@ class MediumLevelILLabel(object):
self.handle = handle
+class MediumLevelILOperationAndSize(object):
+ def __init__(self, operation, size):
+ self.operation = operation
+ self.size = size
+
+ def __repr__(self):
+ if self.size == 0:
+ return "<%s>" % self.operation.name
+ return "<%s %d>" % (self.operation.name, self.size)
+
+
class MediumLevelILInstruction(object):
"""
``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based
@@ -56,6 +76,7 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")],
MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")],
MediumLevelILOperation.MLIL_CONST: [("constant", "int")],
+ MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")],
MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")],
@@ -85,6 +106,7 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_NOT: [("src", "expr")],
MediumLevelILOperation.MLIL_SX: [("src", "expr")],
MediumLevelILOperation.MLIL_ZX: [("src", "expr")],
+ MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")],
MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")],
MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")],
MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")],
@@ -114,15 +136,15 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_UNDEF: [],
MediumLevelILOperation.MLIL_UNIMPL: [],
MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")],
- MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")],
- MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")],
MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")],
- MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")],
- MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")],
- MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")],
- MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")],
- MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")],
- MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")],
+ MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")],
+ MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var_ssa"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var_ssa")],
+ MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var_ssa"), ("offset", "int")],
MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")],
MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")],
MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")],
@@ -131,7 +153,7 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")],
MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")],
MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")],
- MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")],
MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
}
@@ -157,6 +179,19 @@ class MediumLevelILInstruction(object):
value = MediumLevelILInstruction(func, instr.operands[i])
elif operand_type == "var":
value = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
+ elif operand_type == "var_ssa":
+ var = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
+ version = instr.operands[i + 1]
+ i += 1
+ value = SSAVariable(var, version)
+ elif operand_type == "var_ssa_dest_and_src":
+ var = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
+ dest_version = instr.operands[i + 1]
+ src_version = instr.operands[i + 2]
+ i += 2
+ self.operands.append(SSAVariable(var, dest_version))
+ self.dest = SSAVariable(var, dest_version)
+ value = SSAVariable(var, src_version)
elif operand_type == "int_list":
count = ctypes.c_ulonglong()
operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count)
@@ -179,9 +214,9 @@ class MediumLevelILInstruction(object):
value = []
for j in xrange(count.value / 2):
var_id = operand_list[j * 2]
- var_index = operand_list[(j * 2) + 1]
- value.append((function.Variable.from_identifier(self.function.source_function,
- var_id), var_index))
+ var_version = operand_list[(j * 2) + 1]
+ value.append(SSAVariable(function.Variable.from_identifier(self.function.source_function,
+ var_id), var_version))
core.BNMediumLevelILFreeOperandList(operand_list)
elif operand_type == "expr_list":
count = ctypes.c_ulonglong()
@@ -281,35 +316,108 @@ class MediumLevelILInstruction(object):
return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr)
@property
- def ssa_memory_index(self):
- """Index of active memory contents in SSA form for this instruction"""
- return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index)
+ def ssa_memory_version(self):
+ """Version of active memory contents in SSA form for this instruction"""
+ return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index)
+
+ @property
+ def prefix_operands(self):
+ """All operands in the expression tree in prefix order"""
+ result = [MediumLevelILOperationAndSize(self.operation, self.size)]
+ for operand in self.operands:
+ if isinstance(operand, MediumLevelILInstruction):
+ result += operand.prefix_operands
+ else:
+ result.append(operand)
+ return result
+
+ @property
+ def postfix_operands(self):
+ """All operands in the expression tree in postfix order"""
+ result = []
+ for operand in self.operands:
+ if isinstance(operand, MediumLevelILInstruction):
+ result += operand.postfix_operands
+ else:
+ result.append(operand)
+ result.append(MediumLevelILOperationAndSize(self.operation, self.size))
+ return result
+
+ @property
+ def vars_written(self):
+ """List of variables written by instruction"""
+ if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD,
+ MediumLevelILOperation.MLIL_SET_VAR_SSA, MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD,
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED, MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD,
+ MediumLevelILOperation.MLIL_VAR_PHI]:
+ return [self.dest]
+ elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]:
+ return [self.high, self.low]
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL]:
+ return self.output
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED,
+ MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA,
+ MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]:
+ return self.output.vars_written
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]:
+ return self.dest
+ return []
+
+ @property
+ def vars_read(self):
+ """List of variables read by instruction"""
+ if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD,
+ MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SSA,
+ MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA, MediumLevelILOperation.MLIL_SET_VAR_ALIASED]:
+ return self.src.vars_read
+ elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD,
+ MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]:
+ return [self.prev] + self.src.vars_read
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL,
+ MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA]:
+ result = []
+ for param in self.params:
+ result += param.vars_read
+ return result
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED,
+ MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]:
+ return self.params.vars_read
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL_PARAM, MediumLevelILOperation.MLIL_CALL_PARAM_SSA,
+ MediumLevelILOperation.MLIL_VAR_PHI]:
+ return self.src
+ elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]:
+ return []
+ result = []
+ for operand in self.operands:
+ if (isinstance(operand, function.Variable)) or (isinstance(operand, SSAVariable)):
+ result.append(operand)
+ elif isinstance(operand, MediumLevelILInstruction):
+ result += operand.vars_read
+ return result
- def get_ssa_var_possible_values(self, var, index):
+ def get_ssa_var_possible_values(self, ssa_var):
var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index)
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
- def get_ssa_var_index(self, var):
+ def get_ssa_var_version(self, var):
var_data = core.BNVariable()
var_data.type = var.source_type
var_data.index = var.index
var_data.storage = var.storage
- return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index)
+ return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index)
def get_var_for_reg(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index)
return function.Variable(self.function.source_function, result.type, result.index, result.storage)
def get_var_for_flag(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.regs[flag].index
+ flag = self.function.arch.get_flag_index(flag)
result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index)
return function.Variable(self.function.source_function, result.type, result.index, result.storage)
@@ -318,60 +426,52 @@ class MediumLevelILInstruction(object):
return function.Variable(self.function.source_function, result.type, result.index, result.storage)
def get_reg_value(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_reg_value_after(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_possible_reg_values(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_possible_reg_values_after(self, reg):
- if isinstance(reg, str):
- reg = self.function.arch.regs[reg].index
+ reg = self.function.arch.get_reg_index(reg)
value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_flag_value(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_flag_value_after(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index)
result = function.RegisterValue(self.function.arch, value)
return result
def get_possible_flag_values(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
return result
def get_possible_flag_values_after(self, flag):
- if isinstance(flag, str):
- flag = self.function.arch.flags[flag].index
+ flag = self.function.arch.get_flag_index(flag)
value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index)
result = function.PossibleValueSet(self.function.arch, value)
core.BNFreePossibleValueSet(value)
@@ -644,50 +744,50 @@ class MediumLevelILFunction(object):
def get_non_ssa_instruction_index(self, instr):
return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr)
- def get_ssa_var_definition(self, var, index):
+ def get_ssa_var_definition(self, ssa_var):
var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index)
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version)
if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
return None
return result
- def get_ssa_memory_definition(self, index):
- result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index)
+ def get_ssa_memory_definition(self, version):
+ result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, version)
if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
return None
return result
- def get_ssa_var_uses(self, var, index):
+ def get_ssa_var_uses(self, ssa_var):
count = ctypes.c_ulonglong()
var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count)
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count)
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
core.BNFreeILInstructionList(instrs)
return result
- def get_ssa_memory_uses(self, index):
+ def get_ssa_memory_uses(self, version):
count = ctypes.c_ulonglong()
- instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count)
+ instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, version, count)
result = []
for i in xrange(0, count.value):
result.append(instrs[i])
core.BNFreeILInstructionList(instrs)
return result
- def get_ssa_var_value(self, var, index):
+ def get_ssa_var_value(self, ssa_var):
var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index)
+ var_data.type = ssa_var.var.source_type
+ var_data.index = ssa_var.var.index
+ var_data.storage = ssa_var.var.storage
+ value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, ssa_var.version)
result = function.RegisterValue(self.arch, value)
return result
diff --git a/python/platform.py b/python/platform.py
index 139b7d5e..9ba7625f 100644
--- a/python/platform.py
+++ b/python/platform.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/plugin.py b/python/plugin.py
index 2632b5a9..f038d122 100644
--- a/python/plugin.py
+++ b/python/plugin.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/pluginmanager.py b/python/pluginmanager.py
index 37962114..c0f70260 100644
--- a/python/pluginmanager.py
+++ b/python/pluginmanager.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 71402b1b..94616d59 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -35,8 +35,6 @@ import basicblock
import startup
import log
-_output_to_log = False
-
class _ThreadActionContext(object):
_actions = []
@@ -379,14 +377,12 @@ class _PythonScriptingInstanceOutput(object):
return self.write('\n'.join(lines))
def write(self, data):
- global _output_to_log
-
interpreter = None
if "value" in dir(PythonScriptingInstance._interpreter):
interpreter = PythonScriptingInstance._interpreter.value
if interpreter is None:
- if _output_to_log:
+ if log.is_output_redirected_to_log():
self.buffer += data
while True:
i = self.buffer.find('\n')
diff --git a/python/startup.py b/python/startup.py
index 324cc690..0abc47cb 100644
--- a/python/startup.py
+++ b/python/startup.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/transform.py b/python/transform.py
index 40382c69..59d719e7 100644
--- a/python/transform.py
+++ b/python/transform.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/types.py b/python/types.py
index ebaa36fc..f8e416f4 100644
--- a/python/types.py
+++ b/python/types.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
@@ -22,7 +22,7 @@ import ctypes
# Binary Ninja components
import _binaryninjacore as core
-from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType
+from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType
import callingconvention
import function
@@ -646,9 +646,13 @@ class Structure(object):
def union(self):
return core.BNIsStructureUnion(self.handle)
- @union.setter
- def union(self, value):
- core.BNSetStructureUnion(self.handle, value)
+ @property
+ def type(self):
+ return StructureType(core.BNGetStructureType(self.handle))
+
+ @type.setter
+ def type(self, value):
+ core.BNSetStructureType(self.handle, value)
def __setattr__(self, name, value):
try:
diff --git a/python/undoaction.py b/python/undoaction.py
index 9f742e00..7e3c76a0 100644
--- a/python/undoaction.py
+++ b/python/undoaction.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
diff --git a/python/update.py b/python/update.py
index 6417e4a0..be6962d7 100644
--- a/python/update.py
+++ b/python/update.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015-2016 Vector 35 LLC
+# Copyright (c) 2015-2017 Vector 35 LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to