summaryrefslogtreecommitdiff
path: root/python/function.py
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2018-04-04 14:11:55 -0400
committerPeter LaFosse <peter@vector35.com>2018-04-04 14:11:55 -0400
commitd990d5ebf56eb0f1a7d96e98577cb9ace9dac19d (patch)
tree752649d87db23f95a59384f5325b94b734e1c27b /python/function.py
parent1eb3683b3a1ee0d263267b1e84957fadea7fadaa (diff)
parentfa716fe2da53a4f136380b1f60197bd197b2793a (diff)
Merging with dev
Diffstat (limited to 'python/function.py')
-rw-r--r--python/function.py391
1 files changed, 359 insertions, 32 deletions
diff --git a/python/function.py b/python/function.py
index 58bee8f4..6db44e6d 100644
--- a/python/function.py
+++ b/python/function.py
@@ -26,7 +26,8 @@ import ctypes
import _binaryninjacore as core
from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType,
HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend,
- DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType)
+ DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType,
+ FunctionAnalysisSkipOverride)
import architecture
import platform
import highlight
@@ -51,11 +52,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 +104,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):
@@ -177,9 +226,9 @@ class PossibleValueSet(object):
if self.type == RegisterValueType.LookupTableValue:
return "<table: %s>" % ', '.join([repr(i) for i in self.table])
if self.type == RegisterValueType.InSetOfValues:
- return "<in %s>" % repr(self.values)
+ return "<in set(%s)>" % '[{}]'.format(', '.join(hex(i) for i in self.values))
if self.type == RegisterValueType.NotInSetOfValues:
- return "<not in %s>" % repr(self.values)
+ return "<not in set(%s)>" % '[{}]'.format(', '.join(hex(i) for i in self.values))
if self.type == RegisterValueType.ReturnAddressValue:
return "<return address>"
return "<undetermined>"
@@ -219,14 +268,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
@@ -370,7 +420,7 @@ class Function(object):
arch = core.BNGetFunctionArchitecture(self.handle)
if arch is None:
return None
- self._arch = architecture.Architecture(arch)
+ self._arch = architecture.CoreArchitecture._from_cache(arch)
return self._arch
@property
@@ -378,7 +428,7 @@ class Function(object):
"""Function platform (read-only)"""
if self._platform:
return self._platform
- else:
+ else:
plat = core.BNGetFunctionPlatform(self.handle)
if plat is None:
return None
@@ -485,7 +535,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 +548,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
@@ -508,7 +558,7 @@ class Function(object):
branches = core.BNGetIndirectBranches(self.handle, count)
result = []
for i in xrange(0, count.value):
- result.append(IndirectBranchInfo(architecture.Architecture(branches[i].sourceArch), branches[i].sourceAddr, architecture.Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined))
+ result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined))
core.BNFreeIndirectBranchList(branches)
return result
@@ -558,6 +608,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 +715,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 +751,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
@@ -715,6 +818,32 @@ class Function(object):
for i in block:
yield i
+ @property
+ def too_large(self):
+ """Whether the function is too large to automatically perform analysis (read-only)"""
+ return core.BNIsFunctionTooLarge(self.handle)
+
+ @property
+ def analysis_skipped(self):
+ """Whether automatic analysis was skipped for this function"""
+ return core.BNIsFunctionAnalysisSkipped(self.handle)
+
+ @analysis_skipped.setter
+ def analysis_skipped(self, skip):
+ if skip:
+ core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.AlwaysSkipFunctionAnalysis)
+ else:
+ core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.NeverSkipFunctionAnalysis)
+
+ @property
+ def analysis_skip_override(self):
+ """Override for skipping of automatic analysis"""
+ return FunctionAnalysisSkipOverride(core.BNGetFunctionAnalysisSkipOverride(self.handle))
+
+ @analysis_skip_override.setter
+ def analysis_skip_override(self, override):
+ core.BNSetFunctionAnalysisSkipOverride(self.handle, override)
+
def __iter__(self):
count = ctypes.c_ulonglong()
blocks = core.BNGetFunctionBasicBlockList(self.handle, count)
@@ -1013,7 +1142,7 @@ class Function(object):
branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count)
result = []
for i in xrange(0, count.value):
- result.append(IndirectBranchInfo(architecture.Architecture(branches[i].sourceArch), branches[i].sourceAddr, architecture.Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined))
+ result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined))
core.BNFreeIndirectBranchList(branches)
return result
@@ -1055,6 +1184,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 +1253,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))()
@@ -1325,6 +1480,94 @@ class Function(object):
result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg))
return RegisterValue(self.arch, result.value, confidence = result.confidence)
+ def set_auto_call_stack_adjustment(self, addr, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ if not isinstance(adjust, types.SizeWithConfidence):
+ adjust = types.SizeWithConfidence(adjust)
+ core.BNSetAutoCallStackAdjustment(self.handle, arch.handle, addr, adjust.value, adjust.confidence)
+
+ def set_auto_call_reg_stack_adjustment(self, addr, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))()
+ i = 0
+ for reg_stack in adjust.keys():
+ adjust_buf[i].regStack = arch.get_reg_stack_index(reg_stack)
+ value = adjust[reg_stack]
+ if not isinstance(value, types.RegisterStackAdjustmentWithConfidence):
+ value = types.RegisterStackAdjustmentWithConfidence(value)
+ adjust_buf[i].adjustment = value.value
+ adjust_buf[i].confidence = value.confidence
+ i += 1
+ core.BNSetAutoCallRegisterStackAdjustment(self.handle, arch.handle, addr, adjust_buf, len(adjust))
+
+ def set_auto_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ reg_stack = arch.get_reg_stack_index(reg_stack)
+ if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence):
+ adjust = types.RegisterStackAdjustmentWithConfidence(adjust)
+ core.BNSetAutoCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack,
+ adjust.value, adjust.confidence)
+
+ def set_call_stack_adjustment(self, addr, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ if not isinstance(adjust, types.SizeWithConfidence):
+ adjust = types.SizeWithConfidence(adjust)
+ core.BNSetUserCallStackAdjustment(self.handle, arch.handle, addr, adjust.value, adjust.confidence)
+
+ def set_call_reg_stack_adjustment(self, addr, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ adjust_buf = (core.BNRegisterStackAdjustment * len(adjust))()
+ i = 0
+ for reg_stack in adjust.keys():
+ adjust_buf[i].regStack = arch.get_reg_stack_index(reg_stack)
+ value = adjust[reg_stack]
+ if not isinstance(value, types.RegisterStackAdjustmentWithConfidence):
+ value = types.RegisterStackAdjustmentWithConfidence(value)
+ adjust_buf[i].adjustment = value.value
+ adjust_buf[i].confidence = value.confidence
+ i += 1
+ core.BNSetUserCallRegisterStackAdjustment(self.handle, arch.handle, addr, adjust_buf, len(adjust))
+
+ def set_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, adjust, arch=None):
+ if arch is None:
+ arch = self.arch
+ reg_stack = arch.get_reg_stack_index(reg_stack)
+ if not isinstance(adjust, types.RegisterStackAdjustmentWithConfidence):
+ adjust = types.RegisterStackAdjustmentWithConfidence(adjust)
+ core.BNSetUserCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack,
+ adjust.value, adjust.confidence)
+
+ def get_call_stack_adjustment(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
+ result = core.BNGetCallStackAdjustment(self.handle, arch.handle, addr)
+ return types.SizeWithConfidence(result.value, confidence = result.confidence)
+
+ def get_call_reg_stack_adjustment(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
+ count = ctypes.c_ulonglong()
+ adjust = core.BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, count)
+ result = {}
+ for i in xrange(0, count.value):
+ result[arch.get_reg_stack_name(adjust[i].regStack)] = types.RegisterStackAdjustmentWithConfidence(
+ adjust[i].adjustment, confidence = adjust[i].confidence)
+ core.BNFreeRegisterStackAdjustments(adjust)
+ return result
+
+ def get_call_reg_stack_adjustment_for_reg_stack(self, addr, reg_stack, arch=None):
+ if arch is None:
+ arch = self.arch
+ reg_stack = arch.get_reg_stack_index(reg_stack)
+ adjust = core.BNGetCallRegisterStackAdjustmentForRegisterStack(self.handle, arch.handle, addr, reg_stack)
+ result = types.RegisterStackAdjustmentWithConfidence(adjust.adjustment, confidence = adjust.confidence)
+ return result
+
class AdvancedFunctionAnalysisDataRequestor(object):
def __init__(self, func = None):
@@ -1355,9 +1598,10 @@ class AdvancedFunctionAnalysisDataRequestor(object):
class DisassemblyTextLine(object):
- def __init__(self, addr, tokens):
+ def __init__(self, addr, tokens, il_instr = None):
self.address = addr
self.tokens = tokens
+ self.il_instruction = il_instr
def __str__(self):
result = ""
@@ -1382,8 +1626,9 @@ class FunctionGraphEdge(object):
class FunctionGraphBlock(object):
- def __init__(self, handle):
+ def __init__(self, handle, graph):
self.handle = handle
+ self.graph = graph
def __del__(self):
core.BNFreeFunctionGraphBlock(self.handle)
@@ -1402,13 +1647,22 @@ class FunctionGraphBlock(object):
def basic_block(self):
"""Basic block associated with this part of the function graph (read-only)"""
block = core.BNGetFunctionGraphBasicBlock(self.handle)
- func = core.BNGetBasicBlockFunction(block)
- if func is None:
+ func_handle = core.BNGetBasicBlockFunction(block)
+ if func_handle is None:
core.BNFreeBasicBlock(block)
- block = None
+ return None
+
+ view = binaryview.BinaryView(handle = core.BNGetFunctionData(func_handle))
+ func = Function(view, func_handle)
+
+ if core.BNIsLowLevelILBasicBlock(block):
+ block = lowlevelil.LowLevelILBasicBlock(view, block,
+ lowlevelil.LowLevelILFunction(func.arch, core.BNGetBasicBlockLowLevelILFunction(block), func))
+ elif core.BNIsMediumLevelILBasicBlock(block):
+ block = mediumlevelil.MediumLevelILBasicBlock(view, block,
+ mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func))
else:
- block = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), block)
- core.BNFreeFunction(func)
+ block = basicblock.BasicBlock(view, block)
return block
@property
@@ -1417,7 +1671,7 @@ class FunctionGraphBlock(object):
arch = core.BNGetFunctionGraphBlockArchitecture(self.handle)
if arch is None:
return None
- return architecture.Architecture(arch)
+ return architecture.CoreArchitecture._from_cache(arch)
@property
def start(self):
@@ -1454,9 +1708,14 @@ class FunctionGraphBlock(object):
"""Function graph block list of lines (read-only)"""
count = ctypes.c_ulonglong()
lines = core.BNGetFunctionGraphBlockLines(self.handle, count)
+ block = self.basic_block
result = []
for i in xrange(0, count.value):
addr = lines[i].addr
+ if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'):
+ il_instr = block.il_function[lines[i].instrIndex]
+ else:
+ il_instr = None
tokens = []
for j in xrange(0, lines[i].count):
token_type = InstructionTextTokenType(lines[i].tokens[j].type)
@@ -1468,7 +1727,7 @@ class FunctionGraphBlock(object):
confidence = lines[i].tokens[j].confidence
address = lines[i].tokens[j].address
tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
- result.append(DisassemblyTextLine(addr, tokens))
+ result.append(DisassemblyTextLine(addr, tokens, il_instr))
core.BNFreeDisassemblyTextLines(lines, count.value)
return result
@@ -1513,9 +1772,14 @@ class FunctionGraphBlock(object):
def __iter__(self):
count = ctypes.c_ulonglong()
lines = core.BNGetFunctionGraphBlockLines(self.handle, count)
+ block = self.basic_block
try:
for i in xrange(0, count.value):
addr = lines[i].addr
+ if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'):
+ il_instr = block.il_function[lines[i].instrIndex]
+ else:
+ il_instr = None
tokens = []
for j in xrange(0, lines[i].count):
token_type = InstructionTextTokenType(lines[i].tokens[j].type)
@@ -1527,7 +1791,7 @@ class FunctionGraphBlock(object):
confidence = lines[i].tokens[j].confidence
address = lines[i].tokens[j].address
tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
- yield DisassemblyTextLine(addr, tokens)
+ yield DisassemblyTextLine(addr, tokens, il_instr)
finally:
core.BNFreeDisassemblyTextLines(lines, count.value)
@@ -1615,11 +1879,16 @@ class FunctionGraph(object):
blocks = core.BNGetFunctionGraphBlocks(self.handle, count)
result = []
for i in xrange(0, count.value):
- result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i])))
+ result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self))
core.BNFreeFunctionGraphBlockList(blocks, count.value)
return result
@property
+ def has_blocks(self):
+ """Whether the function graph has at least one block (read-only)"""
+ return core.BNFunctionGraphHasBlocks(self.handle)
+
+ @property
def width(self):
"""Function graph width (read-only)"""
return core.BNGetFunctionGraphWidth(self.handle)
@@ -1649,6 +1918,32 @@ class FunctionGraph(object):
def settings(self):
return DisassemblySettings(core.BNGetFunctionGraphSettings(self.handle))
+ @property
+ def is_il(self):
+ return core.BNIsILFunctionGraph(self.handle)
+
+ @property
+ def is_low_level_il(self):
+ return core.BNIsLowLevelILFunctionGraph(self.handle)
+
+ @property
+ def is_medium_level_il(self):
+ return core.BNIsMediumLevelILFunctionGraph(self.handle)
+
+ @property
+ def il_function(self):
+ if self.is_low_level_il:
+ il_func = core.BNGetFunctionGraphLowLevelILFunction(self.handle)
+ if not il_func:
+ return None
+ return lowlevelil.LowLevelILFunction(self.function.arch, il_func, self.function)
+ if self.is_medium_level_il:
+ il_func = core.BNGetFunctionGraphMediumLevelILFunction(self.handle)
+ if not il_func:
+ return None
+ return mediumlevelil.MediumLevelILFunction(self.function.arch, il_func, self.function)
+ return None
+
def __setattr__(self, name, value):
try:
object.__setattr__(self, name, value)
@@ -1663,7 +1958,7 @@ class FunctionGraph(object):
blocks = core.BNGetFunctionGraphBlocks(self.handle, count)
try:
for i in xrange(0, count.value):
- yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))
+ yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)
finally:
core.BNFreeFunctionGraphBlockList(blocks, count.value)
@@ -1706,7 +2001,7 @@ class FunctionGraph(object):
blocks = core.BNGetFunctionGraphBlocksInRegion(self.handle, left, top, right, bottom, count)
result = []
for i in xrange(0, count.value):
- result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i])))
+ result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self))
core.BNFreeFunctionGraphBlockList(blocks, count.value)
return result
@@ -1739,6 +2034,38 @@ 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 IntrinsicInput(object):
+ def __init__(self, type_obj, name=""):
+ self.name = name
+ self.type = type_obj
+
+ def __repr__(self):
+ if len(self.name) == 0:
+ return "<input: %s>" % str(self.type)
+ return "<input: %s %s>" % (str(self.type), self.name)
+
+
+class IntrinsicInfo(object):
+ def __init__(self, inputs, outputs, index=None):
+ self.inputs = inputs
+ self.outputs = outputs
+ self.index = index
+
+ def __repr__(self):
+ return "<intrinsic: %s -> %s>" % (repr(self.inputs), repr(self.outputs))
+
+
class InstructionBranch(object):
def __init__(self, branch_type, target = 0, arch = None):
self.type = branch_type