summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py119
-rw-r--r--python/callingconvention.py89
-rw-r--r--python/function.py163
-rw-r--r--python/lowlevelil.py500
-rw-r--r--python/mediumlevelil.py36
-rw-r--r--python/types.py15
6 files changed, 875 insertions, 47 deletions
diff --git a/python/architecture.py b/python/architecture.py
index a893c1d4..08049d46 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -123,6 +123,7 @@ class Architecture(object):
flag_roles = {}
flags_required_for_flag_condition = {}
flags_written_by_flag_write_type = {}
+ reg_stacks = {}
__metaclass__ = _ArchitectureMetaClass
next_address = 0
@@ -218,6 +219,22 @@ class Architecture(object):
for i in xrange(0, count.value):
self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i]))
core.BNFreeRegisterList(regs)
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetAllArchitectureRegisterStacks(self.handle, count)
+ self.__dict__["reg_stacks"] = {}
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureRegisterStackName(self.handle, regs[i])
+ info = core.BNGetArchitectureRegisterStackInfo(self.handle, regs[i])
+ storage = []
+ for j in xrange(0, info.storageCount):
+ storage.append(core.BNGetArchitectureRegisterName(self.handle, info.firstStorageReg + j))
+ top_rel = []
+ for j in xrange(0, info.topRelativeCount):
+ top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j))
+ top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg)
+ self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i])
+ core.BNFreeRegisterList(regs)
else:
startup._init_plugins()
@@ -262,6 +279,9 @@ class Architecture(object):
self._get_stack_pointer_register)
self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register)
self._cb.getGlobalRegisters = self._cb.getGlobalRegisters.__class__(self._get_global_registers)
+ self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__(self._get_register_stack_name)
+ self._cb.getAllRegisterStacks = self._cb.getAllRegisterStacks.__class__(self._get_all_register_stacks)
+ self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__(self._get_register_stack_info)
self._cb.assemble = self._cb.assemble.__class__(self._assemble)
self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
self._is_never_branch_patch_available)
@@ -283,6 +303,30 @@ class Architecture(object):
self._regs_by_index = {}
self.__dict__["regs"] = self.__class__.regs
reg_index = 0
+
+ # Registers used for storage in register stacks must be sequential, so allocate these in order first
+ self._all_reg_stacks = {}
+ self._reg_stacks_by_index = {}
+ self.__dict__["reg_stacks"] = self.__class__.reg_stacks
+ reg_stack_index = 0
+ for reg_stack in self.reg_stacks:
+ info = self.reg_stacks[reg_stack]
+ for reg in info.storage_regs:
+ self._all_regs[reg] = reg_index
+ self._regs_by_index[reg_index] = reg
+ self.regs[reg].index = reg_index
+ reg_index += 1
+ for reg in info.top_relative_regs:
+ self._all_regs[reg] = reg_index
+ self._regs_by_index[reg_index] = reg
+ self.regs[reg].index = reg_index
+ reg_index += 1
+ if reg_stack not in self._all_reg_stacks:
+ self._all_reg_stacks[reg_stack] = reg_stack_index
+ self._reg_stacks_by_index[reg_stack_index] = reg_stack
+ self.reg_stacks[reg_stack].index = reg_stack_index
+ reg_stack_index += 1
+
for reg in self.regs:
info = self.regs[reg]
if reg not in self._all_regs:
@@ -756,6 +800,57 @@ class Architecture(object):
count[0] = 0
return None
+ def _get_register_stack_name(self, ctxt, reg_stack):
+ try:
+ if reg_stack in self._reg_stacks_by_index:
+ return core.BNAllocString(self._reg_stacks_by_index[reg_stack])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
+ def _get_all_register_stacks(self, ctxt, count):
+ try:
+ regs = self._reg_stacks_by_index.keys()
+ count[0] = len(regs)
+ reg_buf = (ctypes.c_uint * len(regs))()
+ for i in xrange(0, len(regs)):
+ reg_buf[i] = regs[i]
+ result = ctypes.cast(reg_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, reg_buf)
+ return result.value
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_register_stack_info(self, ctxt, reg_stack, result):
+ try:
+ if reg_stack not in self._reg_stacks_by_index:
+ result[0].firstStorageReg = 0
+ result[0].firstTopRelativeReg = 0
+ result[0].storageCount = 0
+ result[0].topRelativeCount = 0
+ result[0].stackTopReg = 0
+ return
+ info = self.__class__.regs[self._reg_stacks_by_index[reg_stack]]
+ result[0].firstStorageReg = self._all_regs[info.storage_regs[0]]
+ result[0].storageCount = len(info.storage_regs)
+ if len(info.top_relative_regs) > 0:
+ result[0].firstTopRelativeReg = self._all_regs[info.top_relative_regs[0]]
+ result[0].topRelativeCount = len(info.top_relative_regs)
+ else:
+ result[0].firstTopRelativeReg = 0
+ result[0].topRelativeCount = 0
+ result[0].stackTopReg = self._all_regs[info.stack_top_reg]
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ result[0].firstStorageReg = 0
+ result[0].firstTopRelativeReg = 0
+ result[0].storageCount = 0
+ result[0].topRelativeCount = 0
+ result[0].stackTopReg = 0
+
def _assemble(self, ctxt, code, addr, result, errors):
try:
data, error_str = self.perform_assemble(code, addr)
@@ -1264,6 +1359,23 @@ class Architecture(object):
"""
return core.BNGetArchitectureRegisterName(self.handle, reg)
+ def get_reg_stack_name(self, reg_stack):
+ """
+ ``get_reg_stack_name`` gets a register stack name from a register stack number.
+
+ :param int reg_stack: register stack number
+ :return: the corresponding register string
+ :rtype: str
+ """
+ return core.BNGetArchitectureRegisterStackName(self.handle, reg_stack)
+
+ def get_reg_stack_for_reg(self, reg):
+ reg = self.get_reg_index(reg)
+ result = core.BNGetArchitectureRegisterStackForRegister(self.handle, reg)
+ if result == 0xffffffff:
+ return None
+ return self.get_reg_stack_name(result)
+
def get_flag_name(self, flag):
"""
``get_flag_name`` gets a flag name from a flag number.
@@ -1281,6 +1393,13 @@ class Architecture(object):
return reg.index
return reg
+ def get_reg_stack_index(self, reg_stack):
+ if isinstance(reg_stack, str):
+ return self.reg_stacks[reg_stack].index
+ elif isinstance(reg_stack, lowlevelil.ILRegisterStack):
+ return reg_stack.index
+ return reg_stack
+
def get_flag_index(self, flag):
if isinstance(flag, str):
return self._flags[flag]
diff --git a/python/callingconvention.py b/python/callingconvention.py
index e72475c9..5aad3317 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -28,6 +28,7 @@ import log
import types
import function
import binaryview
+from enums import VariableSourceType
class CallingConvention(object):
@@ -68,6 +69,8 @@ class CallingConvention(object):
self._cb.getImplicitlyDefinedRegisters = self._cb.getImplicitlyDefinedRegisters.__class__(self._get_implicitly_defined_regs)
self._cb.getIncomingRegisterValue = self._cb.getIncomingRegisterValue.__class__(self._get_incoming_reg_value)
self._cb.getIncomingFlagValue = self._cb.getIncomingFlagValue.__class__(self._get_incoming_flag_value)
+ self._cb.getIncomingVariableForParameterVariable = self._cb.getIncomingVariableForParameterVariable.__class__(self._get_incoming_var_for_parameter_var)
+ self._cb.getParameterVariableForIncomingVariable = self._cb.getParameterVariableForIncomingVariable.__class__(self._get_parameter_var_for_incoming_var)
self.handle = core.BNCreateCallingConvention(arch.handle, name, self._cb)
self.__class__._registered_calling_conventions.append(self)
else:
@@ -301,6 +304,42 @@ class CallingConvention(object):
result[0].state = api_obj.state
result[0].value = api_obj.value
+ def _get_incoming_var_for_parameter_var(self, ctxt, in_var, func, result):
+ try:
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ out_var = self.perform_get_incoming_var_for_parameter_var(in_var_obj, func_obj)
+ result[0].type = out_var.source_type
+ result[0].index = out_var.index
+ result[0].storage = out_var.storage
+ except:
+ log.log_error(traceback.format_exc())
+ result[0].type = in_var[0].type
+ result[0].index = in_var[0].index
+ result[0].storage = in_var[0].storage
+
+ def _get_parameter_var_for_incoming_var(self, ctxt, in_var, func, result):
+ try:
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)),
+ core.BNNewFunctionReference(func))
+ in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ out_var = self.perform_get_parameter_var_for_incoming_var(in_var_obj, func_obj)
+ result[0].type = out_var.source_type
+ result[0].index = out_var.index
+ result[0].storage = out_var.storage
+ except:
+ log.log_error(traceback.format_exc())
+ result[0].type = in_var[0].type
+ result[0].index = in_var[0].index
+ result[0].storage = in_var[0].storage
+
def __repr__(self):
return "<calling convention: %s %s>" % (self.arch.name, self.name)
@@ -308,11 +347,34 @@ class CallingConvention(object):
return self.name
def perform_get_incoming_reg_value(self, reg, func):
+ reg_stack = self.arch.get_reg_stack_for_reg(reg)
+ if reg_stack is not None:
+ if reg == self.arch.reg_stacks[reg_stack].stack_top_reg:
+ return function.RegisterValue.constant(0)
return function.RegisterValue()
def perform_get_incoming_flag_value(self, reg, func):
return function.RegisterValue()
+ def perform_get_incoming_var_for_parameter_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ out_var = core.BNGetDefaultIncomingVariableForParameterVariable(self.handle, in_buf)
+ name = None
+ if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
+ name = func.arch.get_reg_name(out_var.storage)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+
+ def perform_get_parameter_var_for_incoming_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_buf)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage)
+
def with_confidence(self, confidence):
return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle),
confidence = confidence)
@@ -330,3 +392,30 @@ class CallingConvention(object):
if func is not None:
func_handle = func.handle
return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle))
+
+ def get_incoming_var_for_parameter_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = func.handle
+ out_var = core.BNGetIncomingVariableForParameterVariable(self.handle, in_buf, func_obj)
+ name = None
+ if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
+ name = func.arch.get_reg_name(out_var.storage)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+
+ def get_parameter_var_for_incoming_var(self, in_var, func):
+ in_buf = core.BNVariable()
+ in_buf.type = in_var.source_type
+ in_buf.index = in_var.index
+ in_buf.storage = in_var.storage
+ if func is None:
+ func_obj = None
+ else:
+ func_obj = func.handle
+ out_var = core.BNGetParameterVariableForIncomingVariable(self.handle, in_buf, func_obj)
+ return function.Variable(func, out_var.type, out_var.index, out_var.storage)
diff --git a/python/function.py b/python/function.py
index 58bee8f4..10583b58 100644
--- a/python/function.py
+++ b/python/function.py
@@ -51,11 +51,11 @@ class LookupTableEntry(object):
class RegisterValue(object):
def __init__(self, arch = None, value = None, confidence = types.max_confidence):
+ self.is_constant = False
if value is None:
self.type = RegisterValueType.UndeterminedValue
else:
self.type = RegisterValueType(value.state)
- self.is_constant = False
if value.state == RegisterValueType.EntryValue:
self.arch = arch
if arch is not None:
@@ -103,6 +103,54 @@ class RegisterValue(object):
result.value = self.value
return result
+ @classmethod
+ def undetermined(self):
+ return RegisterValue()
+
+ @classmethod
+ def entry_value(self, arch, reg):
+ result = RegisterValue()
+ result.type = RegisterValueType.EntryValue
+ result.arch = arch
+ result.reg = reg
+ return result
+
+ @classmethod
+ def constant(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ConstantValue
+ result.value = value
+ result.is_constant = True
+ return result
+
+ @classmethod
+ def constant_ptr(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ConstantPointerValue
+ result.value = value
+ result.is_constant = True
+ return result
+
+ @classmethod
+ def stack_frame_offset(self, offset):
+ result = RegisterValue()
+ result.type = RegisterValueType.StackFrameOffset
+ result.offset = offset
+ return result
+
+ @classmethod
+ def imported_address(self, value):
+ result = RegisterValue()
+ result.type = RegisterValueType.ImportedAddressValue
+ result.value = value
+ return result
+
+ @classmethod
+ def return_address(self):
+ result = RegisterValue()
+ result.type = RegisterValueType.ReturnAddressValue
+ return result
+
class ValueRange(object):
def __init__(self, start, end, step):
@@ -219,14 +267,15 @@ class Variable(object):
var.storage = storage
self.identifier = core.BNToVariableIdentifier(var)
- if name is None:
- name = core.BNGetVariableName(func.handle, var)
- if var_type is None:
- var_type_conf = core.BNGetVariableType(func.handle, var)
- if var_type_conf.type:
- var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence)
- else:
- var_type = None
+ if func is not None:
+ if name is None:
+ name = core.BNGetVariableName(func.handle, var)
+ if var_type is None:
+ var_type_conf = core.BNGetVariableType(func.handle, var)
+ if var_type_conf.type:
+ var_type = types.Type(var_type_conf.type, platform = func.platform, confidence = var_type_conf.confidence)
+ else:
+ var_type = None
self.name = name
self.type = var_type
@@ -485,7 +534,7 @@ class Function(object):
result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence)))
result.sort(key = lambda x: x.identifier)
- core.BNFreeVariableList(v, count.value)
+ core.BNFreeVariableNameAndTypeList(v, count.value)
return result
@property
@@ -498,7 +547,7 @@ class Function(object):
result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence)))
result.sort(key = lambda x: x.identifier)
- core.BNFreeVariableList(v, count.value)
+ core.BNFreeVariableNameAndTypeList(v, count.value)
return result
@property
@@ -558,6 +607,30 @@ class Function(object):
core.BNSetUserFunctionReturnType(self.handle, type_conf)
@property
+ def return_regs(self):
+ """Registers that are used for the return value"""
+ result = core.BNGetFunctionReturnRegisters(self.handle)
+ reg_set = []
+ for i in xrange(0, result.count):
+ reg_set.append(self.arch.get_reg_name(result.regs[i]))
+ regs = types.RegisterSet(reg_set, confidence = result.confidence)
+ core.BNFreeRegisterSet(result)
+ return regs
+
+ @return_regs.setter
+ def return_regs(self, value):
+ regs = core.BNRegisterSetWithConfidence()
+ regs.regs = (ctypes.c_uint * len(value))()
+ regs.count = len(value)
+ for i in xrange(0, len(value)):
+ regs.regs[i] = self.arch.get_reg_index(value[i])
+ if hasattr(value, 'confidence'):
+ regs.confidence = value.confidence
+ else:
+ regs.confidence = types.max_confidence
+ core.BNSetUserFunctionReturnRegisters(self.handle, regs)
+
+ @property
def calling_convention(self):
"""Calling convention used by the function"""
result = core.BNGetFunctionCallingConvention(self.handle)
@@ -641,6 +714,35 @@ class Function(object):
core.BNSetUserFunctionStackAdjustment(self.handle, sc)
@property
+ def reg_stack_adjustments(self):
+ """Number of entries removed from each register stack after return"""
+ count = ctypes.c_ulonglong()
+ adjust = core.BNGetFunctionRegisterStackAdjustments(self.handle, count)
+ result = {}
+ for i in xrange(0, count.value):
+ name = self.arch.get_reg_stack_name(adjust[i].regStack)
+ value = types.RegisterStackAdjustmentWithConfidence(adjust[i].adjustment,
+ confidence = adjust[i].confidence)
+ result[name] = value
+ core.BNFreeRegisterStackAdjustments(adjust)
+ return result
+
+ @reg_stack_adjustments.setter
+ def reg_stack_adjustments(self, value):
+ adjust = (core.BNRegisterStackAdjustment * len(value))()
+ i = 0
+ for reg_stack in value.keys():
+ adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack)
+ if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence):
+ adjust[i].adjustment = value[reg_stack].value
+ adjust[i].confidence = value[reg_stack].confidence
+ else:
+ adjust[i].adjustment = value[reg_stack]
+ adjust[i].confidence = types.max_confidence
+ i += 1
+ core.BNSetUserFunctionRegisterStackAdjustments(self.handle, adjust, len(value))
+
+ @property
def clobbered_regs(self):
"""Registers that are modified by this function"""
result = core.BNGetFunctionClobberedRegisters(self.handle)
@@ -648,7 +750,7 @@ class Function(object):
for i in xrange(0, result.count):
reg_set.append(self.arch.get_reg_name(result.regs[i]))
regs = types.RegisterSet(reg_set, confidence = result.confidence)
- core.BNFreeClobberedRegisters(result)
+ core.BNFreeRegisterSet(result)
return regs
@clobbered_regs.setter
@@ -1055,6 +1157,18 @@ class Function(object):
type_conf.confidence = value.confidence
core.BNSetAutoFunctionReturnType(self.handle, type_conf)
+ def set_auto_return_regs(self, value):
+ regs = core.BNRegisterSetWithConfidence()
+ regs.regs = (ctypes.c_uint * len(value))()
+ regs.count = len(value)
+ for i in xrange(0, len(value)):
+ regs.regs[i] = self.arch.get_reg_index(value[i])
+ if hasattr(value, 'confidence'):
+ regs.confidence = value.confidence
+ else:
+ regs.confidence = types.max_confidence
+ core.BNSetAutoFunctionReturnRegisters(self.handle, regs)
+
def set_auto_calling_convention(self, value):
conv_conf = core.BNCallingConventionWithConfidence()
if value is None:
@@ -1112,6 +1226,20 @@ class Function(object):
sc.confidence = types.max_confidence
core.BNSetAutoFunctionStackAdjustment(self.handle, sc)
+ def set_auto_reg_stack_adjustments(self, value):
+ adjust = (core.BNRegisterStackAdjustment * len(value))()
+ i = 0
+ for reg_stack in value.keys():
+ adjust[i].regStack = self.arch.get_reg_stack_index(reg_stack)
+ if isinstance(value[reg_stack], types.RegisterStackAdjustmentWithConfidence):
+ adjust[i].adjustment = value[reg_stack].value
+ adjust[i].confidence = value[reg_stack].confidence
+ else:
+ adjust[i].adjustment = value[reg_stack]
+ adjust[i].confidence = types.max_confidence
+ i += 1
+ core.BNSetAutoFunctionRegisterStackAdjustments(self.handle, adjust, len(value))
+
def set_auto_clobbered_regs(self, value):
regs = core.BNRegisterSetWithConfidence()
regs.regs = (ctypes.c_uint * len(value))()
@@ -1739,6 +1867,17 @@ class RegisterInfo(object):
return "<reg: size %d, offset %d in %s%s>" % (self.size, self.offset, self.full_width_reg, extend)
+class RegisterStackInfo(object):
+ def __init__(self, storage_regs, top_relative_regs, stack_top_reg, index=None):
+ self.storage_regs = storage_regs
+ self.top_relative_regs = top_relative_regs
+ self.stack_top_reg = stack_top_reg
+ self.index = index
+
+ def __repr__(self):
+ return "<reg stack: %d regs, stack top in %s>" % (len(self.storage_regs), self.stack_top_reg)
+
+
class InstructionBranch(object):
def __init__(self, branch_type, target = 0, arch = None):
self.type = branch_type
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index dfc5af5f..42c34ee0 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -26,6 +26,7 @@ from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionText
import function
import basicblock
import mediumlevelil
+import struct
class LowLevelILLabel(object):
@@ -61,6 +62,26 @@ class ILRegister(object):
return self.info == other.info
+class ILRegisterStack(object):
+ def __init__(self, arch, reg_stack):
+ self.arch = arch
+ self.index = reg_stack
+ self.name = self.arch.get_reg_stack_name(self.index)
+
+ @property
+ def info(self):
+ return self.arch.reg_stacks[self.name]
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.info == other.info
+
+
class ILFlag(object):
def __init__(self, arch, flag):
self.arch = arch
@@ -87,6 +108,15 @@ class SSARegister(object):
return "<ssa %s version %d>" % (repr(self.reg), self.version)
+class SSARegisterStack(object):
+ def __init__(self, reg_stack, version):
+ self.reg_stack = reg_stack
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.reg_stack), self.version)
+
+
class SSAFlag(object):
def __init__(self, flag, version):
self.flag = flag
@@ -118,14 +148,20 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_NOP: [],
LowLevelILOperation.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_STACK_REL: [("stack", "reg_stack"), ("dest", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_PUSH: [("stack", "reg_stack"), ("src", "expr")],
LowLevelILOperation.LLIL_SET_FLAG: [("dest", "flag"), ("src", "expr")],
LowLevelILOperation.LLIL_LOAD: [("src", "expr")],
LowLevelILOperation.LLIL_STORE: [("dest", "expr"), ("src", "expr")],
LowLevelILOperation.LLIL_PUSH: [("src", "expr")],
LowLevelILOperation.LLIL_POP: [],
LowLevelILOperation.LLIL_REG: [("src", "reg")],
+ LowLevelILOperation.LLIL_REG_SPLIT: [("hi", "reg"), ("lo", "reg")],
+ LowLevelILOperation.LLIL_REG_STACK_REL: [("stack", "reg_stack"), ("src", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_POP: [("stack", "reg_stack")],
LowLevelILOperation.LLIL_CONST: [("constant", "int")],
LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")],
+ LowLevelILOperation.LLIL_FLOAT_CONST: [("constant", "float")],
LowLevelILOperation.LLIL_FLAG: [("src", "flag")],
LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")],
LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")],
@@ -146,13 +182,13 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_DIVU: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_DIVU_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_DIVS: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_DIVS_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_MODU: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_MODU_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_MODS: [("left", "expr"), ("right", "expr")],
- LowLevelILOperation.LLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_MODS_DP: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_NEG: [("src", "expr")],
LowLevelILOperation.LLIL_NOT: [("src", "expr")],
LowLevelILOperation.LLIL_SX: [("src", "expr")],
@@ -161,7 +197,7 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_JUMP: [("dest", "expr")],
LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")],
LowLevelILOperation.LLIL_CALL: [("dest", "expr")],
- LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int")],
+ LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")],
LowLevelILOperation.LLIL_RET: [("dest", "expr")],
LowLevelILOperation.LLIL_NORET: [],
LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")],
@@ -186,12 +222,35 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_UNDEF: [],
LowLevelILOperation.LLIL_UNIMPL: [],
LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")],
+ LowLevelILOperation.LLIL_FADD: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FSUB: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FMUL: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FDIV: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FSQRT: [("src", "expr")],
+ LowLevelILOperation.LLIL_FNEG: [("src", "expr")],
+ LowLevelILOperation.LLIL_FABS: [("src", "expr")],
+ LowLevelILOperation.LLIL_FLOAT_TO_INT: [("src", "expr")],
+ LowLevelILOperation.LLIL_INT_TO_FLOAT: [("src", "expr")],
+ LowLevelILOperation.LLIL_FLOAT_CONV: [("src", "expr")],
+ LowLevelILOperation.LLIL_FCMP_E: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_NE: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_LT: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_LE: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_GE: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_GT: [("left", "expr"), ("right", "expr")],
+ LowLevelILOperation.LLIL_FCMP_UO: [("left", "expr"), ("right", "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_SET_REG_STACK_REL_SSA: [("stack", "expr"), ("dest", "expr"), ("top", "expr"), ("src", "expr")],
+ LowLevelILOperation.LLIL_SET_REG_STACK_ABS_SSA: [("stack", "expr"), ("dest", "reg"), ("src", "expr")],
LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_STACK_DEST_SSA: [("src", "reg_stack_ssa_dest_and_src")],
LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")],
LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "reg")],
+ LowLevelILOperation.LLIL_REG_SPLIT_SSA: [("hi", "reg_ssa"), ("lo", "reg_ssa")],
+ LowLevelILOperation.LLIL_REG_STACK_REL_SSA: [("stack", "reg_stack_ssa"), ("src", "expr"), ("top", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_ABS_SSA: [("stack", "reg_stack_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")],
@@ -199,10 +258,11 @@ class LowLevelILInstruction(object):
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_ssa"), ("src_memory", "int")],
- LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "expr_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_ssa"), ("src", "reg_ssa_list")],
+ LowLevelILOperation.LLIL_REG_STACK_PHI: [("dest", "reg_stack_ssa"), ("src", "reg_stack_ssa_list")],
LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")],
LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")]
}
@@ -229,14 +289,35 @@ class LowLevelILInstruction(object):
name, operand_type = operand
if operand_type == "int":
value = instr.operands[i]
+ elif operand_type == "float":
+ if instr.size == 4:
+ value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0]
+ elif instr.size == 8:
+ value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0]
+ else:
+ value = instr.operands[i]
elif operand_type == "expr":
value = LowLevelILInstruction(func, instr.operands[i])
elif operand_type == "reg":
value = ILRegister(func.arch, instr.operands[i])
+ elif operand_type == "reg_stack":
+ value = ILRegisterStack(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 == "reg_stack_ssa":
+ reg_stack = ILRegisterStack(func.arch, instr.operands[i])
+ i += 1
+ value = SSARegisterStack(reg_stack, instr.operands[i])
+ elif operand_type == "reg_stack_ssa_dest_and_src":
+ reg_stack = ILRegisterStack(func.arch, instr.operands[i])
+ i += 1
+ value = SSARegisterStack(reg_stack, instr.operands[i])
+ i += 1
+ self.operands.append(value)
+ self.dest = value
+ value = SSARegisterStack(reg_stack, instr.operands[i])
elif operand_type == "flag":
value = ILFlag(func.arch, instr.operands[i])
elif operand_type == "flag_ssa":
@@ -253,6 +334,14 @@ class LowLevelILInstruction(object):
for i in xrange(count.value):
value.append(operand_list[i])
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "expr_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(LowLevelILInstruction(func, operand_list[i]))
+ core.BNLowLevelILFreeOperandList(operand_list)
elif operand_type == "reg_ssa_list":
count = ctypes.c_ulonglong()
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
@@ -263,6 +352,16 @@ class LowLevelILInstruction(object):
reg_version = operand_list[(i * 2) + 1]
value.append(SSARegister(ILRegister(func.arch, reg), reg_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_stack_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_stack = operand_list[i * 2]
+ reg_version = operand_list[(i * 2) + 1]
+ value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), 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)
@@ -273,6 +372,18 @@ class LowLevelILInstruction(object):
flag_version = operand_list[(i * 2) + 1]
value.append(SSAFlag(ILFlag(func.arch, flag), flag_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_stack_adjust":
+ 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_stack = operand_list[i * 2]
+ adjust = operand_list[(i * 2) + 1]
+ if adjust & 0x80000000:
+ adjust |= ~0x80000000
+ value[func.arch.get_reg_stack_name(reg_stack)] = adjust
+ core.BNLowLevelILFreeOperandList(operand_list)
self.operands.append(value)
self.__dict__[name] = value
i += 1
@@ -710,6 +821,38 @@ class LowLevelILFunction(object):
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_reg_stack_top_relative(self, size, reg_stack, entry, value, flags = 0):
+ """
+ ``set_reg_stack_top_relative`` sets the top-relative entry ``entry`` of size ``size`` in register
+ stack ``reg_stack`` to the expression ``value``
+
+ :param int size: size of the register parameter in bytes
+ :param str reg_stack: the register stack name
+ :param LowLevelILExpr entry: an expression for which stack entry to set
+ :param LowLevelILExpr value: an expression to set the entry to
+ :param str flags: which flags are set by this operation
+ :return: The expression ``reg_stack[entry] = value``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_SET_REG_STACK_REL, reg_stack, entry.index, value.index,
+ size = size, flags = flags)
+
+ def reg_stack_push(self, size, reg_stack, value, flags = 0):
+ """
+ ``reg_stack_push`` pushes the expression ``value`` of size ``size`` onto the top of the register
+ stack ``reg_stack``
+
+ :param int size: size of the register parameter in bytes
+ :param str reg_stack: the register stack name
+ :param LowLevelILExpr value: an expression to push
+ :param str flags: which flags are set by this operation
+ :return: The expression ``reg_stack.push(value)``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_PUSH, reg_stack, value.index, size = size, flags = flags)
+
def set_flag(self, flag, value):
"""
``set_flag`` sets the flag ``flag`` to the LowLevelILExpr ``value``
@@ -768,7 +911,7 @@ class LowLevelILFunction(object):
def reg(self, size, reg):
"""
- ``reg`` returns a register of size ``size`` with name ``name``
+ ``reg`` returns a register of size ``size`` with name ``reg``
:param int size: the size of the register in bytes
:param str reg: the name of the register
@@ -778,6 +921,47 @@ class LowLevelILFunction(object):
reg = self.arch.get_reg_index(reg)
return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size)
+ def reg_split(self, size, hi, lo):
+ """
+ ``reg_split`` combines registers of size ``size`` with names ``hi`` and ``lo``
+
+ :param int size: the size of the register in bytes
+ :param str hi: register holding high part of value
+ :param str lo: register holding low part of value
+ :return: The expression ``hi:lo``
+ :rtype: LowLevelILExpr
+ """
+ hi = self.arch.get_reg_index(hi)
+ lo = self.arch.get_reg_index(lo)
+ return self.expr(LowLevelILOperation.LLIL_REG_SPLIT, hi, lo, size=size)
+
+ def reg_stack_top_relative(self, size, reg_stack, entry):
+ """
+ ``reg_stack_top_relative`` returns a register stack entry of size ``size`` at top-relative
+ location ``entry`` in register stack with name ``reg_stack``
+
+ :param int size: the size of the register in bytes
+ :param str reg_stack: the name of the register stack
+ :param LowLevelILExpr entry: an expression for which stack entry to fetch
+ :return: The expression ``reg_stack[entry]``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_REL, reg_stack, entry.index, size=size)
+
+ def reg_stack_pop(self, size, reg_stack):
+ """
+ ``reg_stack_pop`` returns the top entry of size ``size`` in register stack with name ``reg_stack``, and
+ removes the entry from the stack
+
+ :param int size: the size of the register in bytes
+ :param str reg_stack: the name of the register stack
+ :return: The expression ``reg_stack.pop``
+ :rtype: LowLevelILExpr
+ """
+ reg_stack = self.arch.get_reg_stack_index(reg_stack)
+ return self.expr(LowLevelILOperation.LLIL_REG_STACK_POP, reg_stack, size=size)
+
def const(self, size, value):
"""
``const`` returns an expression for the constant integer ``value`` with size ``size``
@@ -800,6 +984,38 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size)
+ def float_const_raw(self, size, value):
+ """
+ ``float_const_raw`` returns an expression for the constant raw binary floating point
+ value ``value`` with size ``size``
+
+ :param int size: the size of the constant in bytes
+ :param int value: integer value for the raw binary representation of the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, value, size=size)
+
+ def float_const_single(self, value):
+ """
+ ``float_const_single`` returns an expression for the single precision floating point value ``value``
+
+ :param float value: float value for the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("I", struct.pack("f", value))[0], size=4)
+
+ def float_const_double(self, value):
+ """
+ ``float_const_double`` returns an expression for the double precision floating point value ``value``
+
+ :param float value: float value for the constant
+ :return: A constant expression of given value and size
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("Q", struct.pack("d", value))[0], size=8)
+
def flag(self, reg):
"""
``flag`` returns a flag expression for the given flag name.
@@ -1078,21 +1294,20 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags)
- def div_double_prec_signed(self, size, hi, lo, b, flags=None):
+ def div_double_prec_signed(self, size, a, b, flags=None):
"""
- ``div_double_prec_signed`` signed double precision divide using expression ``hi`` and expression ``lo`` as a
+ ``div_double_prec_signed`` signed double precision divide using expression ``a`` as a
single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an
expression of ``size`` bytes.
:param int size: the size of the result in bytes
- :param LowLevelILExpr hi: high LHS expression
- :param LowLevelILExpr lo: low LHS expression
+ :param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``divs.dp.<size>{<flags>}(hi:lo, b)``
+ :return: The expression ``divs.dp.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_DIVS_DP, a.index, b.index, size=size, flags=flags)
def div_unsigned(self, size, a, b, flags=None):
"""
@@ -1108,21 +1323,20 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags)
- def div_double_prec_unsigned(self, size, hi, lo, b, flags=None):
+ def div_double_prec_unsigned(self, size, a, b, flags=None):
"""
- ``div_double_prec_unsigned`` unsigned double precision divide using expression ``hi`` and expression ``lo`` as
+ ``div_double_prec_unsigned`` unsigned double precision divide using expression ``a`` as
a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an
expression of ``size`` bytes.
:param int size: the size of the result in bytes
- :param LowLevelILExpr hi: high LHS expression
- :param LowLevelILExpr lo: low LHS expression
+ :param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``divs.dp.<size>{<flags>}(hi:lo, b)``
+ :return: The expression ``divs.dp.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_DIVS_DP, hi.index, lo.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_DIVS_DP, a.index, b.index, size=size, flags=flags)
def mod_signed(self, size, a, b, flags=None):
"""
@@ -1138,21 +1352,20 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags)
- def mod_double_prec_signed(self, size, hi, lo, b, flags=None):
+ def mod_double_prec_signed(self, size, a, b, flags=None):
"""
- ``mod_double_prec_signed`` signed double precision modulus using expression ``hi`` and expression ``lo`` as a single
+ ``mod_double_prec_signed`` signed double precision modulus using expression ``a`` as a single
double precision register by expression ``b`` potentially setting flags ``flags`` and returning an expression
of ``size`` bytes.
:param int size: the size of the result in bytes
- :param LowLevelILExpr hi: high LHS expression
- :param LowLevelILExpr lo: low LHS expression
+ :param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``mods.dp.<size>{<flags>}(hi:lo, b)``
+ :return: The expression ``mods.dp.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_MODS_DP, a.index, b.index, size=size, flags=flags)
def mod_unsigned(self, size, a, b, flags=None):
"""
@@ -1168,21 +1381,20 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags)
- def mod_double_prec_unsigned(self, size, hi, lo, b, flags=None):
+ def mod_double_prec_unsigned(self, size, a, b, flags=None):
"""
- ``mod_double_prec_unsigned`` unsigned double precision modulus using expression ``hi`` and expression ``lo`` as
+ ``mod_double_prec_unsigned`` unsigned double precision modulus using expression ``a`` as
a single double precision register by expression ``b`` potentially setting flags ``flags`` and returning an
expression of ``size`` bytes.
:param int size: the size of the result in bytes
- :param LowLevelILExpr hi: high LHS expression
- :param LowLevelILExpr lo: low LHS expression
+ :param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``modu.dp.<size>{<flags>}(hi:lo, b)``
+ :return: The expression ``modu.dp.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_MODS_DP, hi.index, lo.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_MODS_DP, a.index, b.index, size=size, flags=flags)
def neg_expr(self, size, value, flags=None):
"""
@@ -1501,6 +1713,232 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_UNIMPL_MEM, addr.index, size = size)
+ def float_add(self, size, a, b, flags=None):
+ """
+ ``float_add`` adds floating point expression ``a`` to expression ``b`` potentially setting flags ``flags``
+ and returning an expression of ``size`` bytes.
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``fadd.<size>{<flags>}(a, b)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FADD, a.index, b.index, size=size, flags=flags)
+
+ def float_sub(self, size, a, b, flags=None):
+ """
+ ``float_sub`` subtracts floating point expression ``b`` from expression ``a`` potentially setting flags ``flags``
+ and returning an expression of ``size`` bytes.
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``fsub.<size>{<flags>}(a, b)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FSUB, a.index, b.index, size=size, flags=flags)
+
+ def float_mult(self, size, a, b, flags=None):
+ """
+ ``float_mult`` multiplies floating point expression ``a`` by expression ``b`` potentially setting flags ``flags``
+ and returning an expression of ``size`` bytes.
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``fmul.<size>{<flags>}(a, b)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FMUL, a.index, b.index, size=size, flags=flags)
+
+ def float_div(self, size, a, b, flags=None):
+ """
+ ``float_div`` divides floating point expression ``a`` by expression ``b`` potentially setting flags ``flags``
+ and returning an expression of ``size`` bytes.
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``fdiv.<size>{<flags>}(a, b)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FDIV, a.index, b.index, size=size, flags=flags)
+
+ def float_sqrt(self, size, value, flags=None):
+ """
+ ``float_sqrt`` returns square root of floating point expression ``value`` of size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``sqrt.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FSQRT, value.index, size=size, flags=flags)
+
+ def float_neg(self, size, value, flags=None):
+ """
+ ``float_neg`` returns sign negation of floating point expression ``value`` of size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``fneg.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FNEG, value.index, size=size, flags=flags)
+
+ def float_abs(self, size, value, flags=None):
+ """
+ ``float_abs`` returns absolute value of floating point expression ``value`` of size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``fabs.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FABS, value.index, size=size, flags=flags)
+
+ def float_to_int(self, size, value, flags=None):
+ """
+ ``float_to_int`` returns integer value of floating point expression ``value`` of size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``int.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_TO_INT, value.index, size=size, flags=flags)
+
+ def int_to_float(self, size, value, flags=None):
+ """
+ ``int_to_float`` returns floating point value of integer expression ``value`` of size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``float.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_INT_TO_FLOAT, value.index, size=size, flags=flags)
+
+ def float_convert(self, size, value, flags=None):
+ """
+ ``int_to_float`` converts floating point value of expression ``value`` to size ``size`` potentially setting flags
+
+ :param int size: the size of the result in bytes
+ :param LowLevelILExpr value: the expression to negate
+ :param str flags: optional, flags to set
+ :return: The expression ``fconvert.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONV, value.index, size=size, flags=flags)
+
+ def float_compare_equal(self, size, a, b):
+ """
+ ``float_compare_equal`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is equal to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f== b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_E, a.index, b.index)
+
+ def float_compare_not_equal(self, size, a, b):
+ """
+ ``float_compare_not_equal`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is not equal to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f!= b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_NE, a.index, b.index)
+
+ def float_compare_less_than(self, size, a, b):
+ """
+ ``float_compare_less_than`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is less than to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f< b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_LT, a.index, b.index)
+
+ def float_compare_less_equal(self, size, a, b):
+ """
+ ``float_compare_less_equal`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is less than or equal to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f<= b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_LE, a.index, b.index)
+
+ def float_compare_greater_equal(self, size, a, b):
+ """
+ ``float_compare_greater_equal`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is greater than or equal to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f>= b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_GE, a.index, b.index)
+
+ def float_compare_greater_than(self, size, a, b):
+ """
+ ``float_compare_greater_than`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is greater than or equal to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``a f> b``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_GT, a.index, b.index)
+
+ def float_compare_unordered(self, size, a, b):
+ """
+ ``float_compare_unordered`` returns floating point comparison expression of size ``size`` checking if
+ expression ``a`` is unordered relative to expression ``b``
+
+ :param int size: the size of the operands in bytes
+ :param LowLevelILExpr a: LHS expression
+ :param LowLevelILExpr b: RHS expression
+ :param str flags: flags to set
+ :return: The expression ``is_unordered(a, b)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FCMP_UO, a.index, b.index)
+
def goto(self, label):
"""
``goto`` returns a goto expression which jumps to the provided LowLevelILLabel.
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 6f5515bb..85feba0a 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -27,6 +27,7 @@ import function
import basicblock
import lowlevelil
import types
+import struct
class SSAVariable(object):
@@ -85,10 +86,12 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_STORE_STRUCT: [("dest", "expr"), ("offset", "int"), ("src", "expr")],
MediumLevelILOperation.MLIL_VAR: [("src", "var")],
MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")],
+ MediumLevelILOperation.MLIL_VAR_SPLIT: [("high", "var"), ("low", "var")],
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_FLOAT_CONST: [("constant", "float")],
MediumLevelILOperation.MLIL_IMPORT: [("constant", "int")],
MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")],
@@ -108,13 +111,13 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_DIVU: [("left", "expr"), ("right", "expr")],
- MediumLevelILOperation.MLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVU_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")],
- MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_DIVS_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")],
- MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODU_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")],
- MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_MODS_DP: [("left", "expr"), ("right", "expr")],
MediumLevelILOperation.MLIL_NEG: [("src", "expr")],
MediumLevelILOperation.MLIL_NOT: [("src", "expr")],
MediumLevelILOperation.MLIL_SX: [("src", "expr")],
@@ -150,6 +153,23 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_UNDEF: [],
MediumLevelILOperation.MLIL_UNIMPL: [],
MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FADD: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FSUB: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FMUL: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FDIV: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FSQRT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FNEG: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FABS: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FLOAT_TO_INT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_INT_TO_FLOAT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FLOAT_CONV: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_E: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_NE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_LT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_LE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_GE: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_GT: [("left", "expr"), ("right", "expr")],
+ MediumLevelILOperation.MLIL_FCMP_UO: [("left", "expr"), ("right", "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", "var_ssa"), ("low", "var_ssa"), ("src", "expr")],
@@ -159,6 +179,7 @@ class MediumLevelILInstruction(object):
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_VAR_SPLIT_SSA: [("high", "var_ssa"), ("low", "var_ssa")],
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")],
@@ -192,6 +213,13 @@ class MediumLevelILInstruction(object):
name, operand_type = operand
if operand_type == "int":
value = instr.operands[i]
+ elif operand_type == "float":
+ if instr.size == 4:
+ value = struct.unpack("f", struct.pack("I", instr.operands[i] & 0xffffffff))[0]
+ elif instr.size == 8:
+ value = struct.unpack("d", struct.pack("Q", instr.operands[i]))[0]
+ else:
+ value = instr.operands[i]
elif operand_type == "expr":
value = MediumLevelILInstruction(func, instr.operands[i])
elif operand_type == "var":
diff --git a/python/types.py b/python/types.py
index 2557db2c..d44cc736 100644
--- a/python/types.py
+++ b/python/types.py
@@ -680,6 +680,21 @@ class SizeWithConfidence(object):
return self.value
+class RegisterStackAdjustmentWithConfidence(object):
+ def __init__(self, value, confidence = max_confidence):
+ self.value = value
+ self.confidence = confidence
+
+ def __str__(self):
+ return str(self.value)
+
+ def __repr__(self):
+ return repr(self.value)
+
+ def __int__(self):
+ return self.value
+
+
class RegisterSet(object):
def __init__(self, reg_list, confidence = max_confidence):
self.regs = reg_list