summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py2
-rw-r--r--python/callingconvention.py85
-rw-r--r--python/function.py67
-rw-r--r--python/lowlevelil.py24
-rw-r--r--python/types.py15
5 files changed, 179 insertions, 14 deletions
diff --git a/python/architecture.py b/python/architecture.py
index 04179e7f..c4179b00 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -231,7 +231,7 @@ class Architecture(object):
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)
+ self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i])
core.BNFreeRegisterList(regs)
else:
startup._init_plugins()
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 18662fc5..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)
@@ -317,6 +356,25 @@ class CallingConvention(object):
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)
@@ -334,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 ba00147e..eabf86b3 100644
--- a/python/function.py
+++ b/python/function.py
@@ -263,14 +263,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
@@ -519,7 +520,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
@@ -532,7 +533,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
@@ -675,6 +676,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)
@@ -1099,6 +1129,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))()
@@ -1727,10 +1771,11 @@ class RegisterInfo(object):
class RegisterStackInfo(object):
- def __init__(self, storage_regs, top_relative_regs, stack_top_reg):
+ 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)
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index f5a39b7e..3810e742 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -197,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")],
@@ -258,7 +258,7 @@ 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")],
@@ -334,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)
@@ -364,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
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