summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py1916
-rw-r--r--python/basicblock.py23
-rw-r--r--python/binaryview.py30
-rw-r--r--python/callingconvention.py91
-rw-r--r--python/examples/arch_hook.py16
-rw-r--r--python/examples/nes.py28
-rw-r--r--python/function.py391
-rw-r--r--python/interaction.py2
-rw-r--r--python/lowlevelil.py720
-rw-r--r--python/mediumlevelil.py47
-rw-r--r--python/platform.py2
-rw-r--r--python/plugin.py219
-rw-r--r--python/scriptingprovider.py4
-rw-r--r--python/types.py17
14 files changed, 2938 insertions, 568 deletions
diff --git a/python/architecture.py b/python/architecture.py
index a893c1d4..c5f87ec6 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -44,7 +44,7 @@ class _ArchitectureMetaClass(type):
archs = core.BNGetArchitectureList(count)
result = []
for i in xrange(0, count.value):
- result.append(Architecture(archs[i]))
+ result.append(CoreArchitecture._from_cache(archs[i]))
core.BNFreeArchitectureList(archs)
return result
@@ -54,7 +54,7 @@ class _ArchitectureMetaClass(type):
archs = core.BNGetArchitectureList(count)
try:
for i in xrange(0, count.value):
- yield Architecture(archs[i])
+ yield CoreArchitecture._from_cache(archs[i])
finally:
core.BNFreeArchitectureList(archs)
@@ -63,7 +63,7 @@ class _ArchitectureMetaClass(type):
arch = core.BNGetArchitectureByName(name)
if arch is None:
raise KeyError("'%s' is not a valid architecture" % str(name))
- return Architecture(arch)
+ return CoreArchitecture._from_cache(arch)
def register(cls):
startup._init_plugins()
@@ -120,232 +120,266 @@ class Architecture(object):
global_regs = []
flags = []
flag_write_types = []
+ semantic_flag_classes = []
+ semantic_flag_groups = []
flag_roles = {}
flags_required_for_flag_condition = {}
+ flags_required_for_semantic_flag_group = {}
+ flag_conditions_for_semantic_flag_group = {}
flags_written_by_flag_write_type = {}
+ semantic_class_for_flag_write_type = {}
+ reg_stacks = {}
+ intrinsics = {}
__metaclass__ = _ArchitectureMetaClass
next_address = 0
- def __init__(self, handle=None):
- if handle is not None:
- self.handle = core.handle_of_type(handle, core.BNArchitecture)
- self.__dict__["name"] = core.BNGetArchitectureName(self.handle)
- self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle))
- self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle)
- self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle)
- self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle)
- self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle)
- self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle)
- self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle,
- core.BNGetArchitectureStackPointerRegister(self.handle))
- self.__dict__["link_reg"] = core.BNGetArchitectureRegisterName(self.handle,
- core.BNGetArchitectureLinkRegister(self.handle))
+ def __init__(self):
+ startup._init_plugins()
- count = ctypes.c_ulonglong()
- regs = core.BNGetAllArchitectureRegisters(self.handle, count)
- self.__dict__["regs"] = {}
- for i in xrange(0, count.value):
- name = core.BNGetArchitectureRegisterName(self.handle, regs[i])
- info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i])
- full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister)
- self.regs[name] = function.RegisterInfo(full_width_reg, info.size, info.offset,
- ImplicitRegisterExtend(info.extend), regs[i])
- core.BNFreeRegisterList(regs)
+ if self.__class__.opcode_display_length > self.__class__.max_instr_length:
+ self.__class__.opcode_display_length = self.__class__.max_instr_length
- count = ctypes.c_ulonglong()
- flags = core.BNGetAllArchitectureFlags(self.handle, count)
- self._flags = {}
- self._flags_by_index = {}
- self.__dict__["flags"] = []
- for i in xrange(0, count.value):
- name = core.BNGetArchitectureFlagName(self.handle, flags[i])
- self._flags[name] = flags[i]
- self._flags_by_index[flags[i]] = name
- self.flags.append(name)
- core.BNFreeRegisterList(flags)
+ self._cb = core.BNCustomArchitecture()
+ self._cb.context = 0
+ self._cb.init = self._cb.init.__class__(self._init)
+ self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness)
+ self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size)
+ self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size)
+ self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment)
+ self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length)
+ self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length)
+ self._cb.getAssociatedArchitectureByAddress = \
+ self._cb.getAssociatedArchitectureByAddress.__class__(self._get_associated_arch_by_address)
+ self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info)
+ self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text)
+ self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text)
+ self._cb.getInstructionLowLevelIL = self._cb.getInstructionLowLevelIL.__class__(
+ self._get_instruction_low_level_il)
+ self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name)
+ self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name)
+ self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name)
+ self._cb.getSemanticFlagClassName = self._cb.getSemanticFlagClassName.__class__(self._get_semantic_flag_class_name)
+ self._cb.getSemanticFlagGroupName = self._cb.getSemanticFlagGroupName.__class__(self._get_semantic_flag_group_name)
+ self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers)
+ self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers)
+ self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags)
+ self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types)
+ self._cb.getAllSemanticFlagClasses = self._cb.getAllSemanticFlagClasses.__class__(self._get_all_semantic_flag_classes)
+ self._cb.getAllSemanticFlagGroups = self._cb.getAllSemanticFlagGroups.__class__(self._get_all_semantic_flag_groups)
+ self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role)
+ self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__(
+ self._get_flags_required_for_flag_condition)
+ self._cb.getFlagsRequiredForSemanticFlagGroup = self._cb.getFlagsRequiredForSemanticFlagGroup.__class__(
+ self._get_flags_required_for_semantic_flag_group)
+ self._cb.getFlagConditionsForSemanticFlagGroup = self._cb.getFlagConditionsForSemanticFlagGroup.__class__(
+ self._get_flag_conditions_for_semantic_flag_group)
+ self._cb.freeFlagConditionsForSemanticFlagGroup = self._cb.freeFlagConditionsForSemanticFlagGroup.__class__(
+ self._free_flag_conditions_for_semantic_flag_group)
+ self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__(
+ self._get_flags_written_by_flag_write_type)
+ self._cb.getSemanticClassForFlagWriteType = self._cb.getSemanticClassForFlagWriteType.__class__(
+ self._get_semantic_class_for_flag_write_type)
+ self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__(
+ self._get_flag_write_low_level_il)
+ self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__(
+ self._get_flag_condition_low_level_il)
+ self._cb.getSemanticFlagGroupLowLevelIL = self._cb.getSemanticFlagGroupLowLevelIL.__class__(
+ self._get_semantic_flag_group_low_level_il)
+ self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list)
+ self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info)
+ self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__(
+ 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.getIntrinsicName = self._cb.getIntrinsicName.__class__(self._get_intrinsic_name)
+ self._cb.getAllIntrinsics = self._cb.getAllIntrinsics.__class__(self._get_all_intrinsics)
+ self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__(self._get_intrinsic_inputs)
+ self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__(self._free_name_and_type_list)
+ self._cb.getIntrinsicOutputs = self._cb.getIntrinsicOutputs.__class__(self._get_intrinsic_outputs)
+ self._cb.freeTypeList = self._cb.freeTypeList.__class__(self._free_type_list)
+ self._cb.assemble = self._cb.assemble.__class__(self._assemble)
+ self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
+ self._is_never_branch_patch_available)
+ self._cb.isAlwaysBranchPatchAvailable = self._cb.isAlwaysBranchPatchAvailable.__class__(
+ self._is_always_branch_patch_available)
+ self._cb.isInvertBranchPatchAvailable = self._cb.isInvertBranchPatchAvailable.__class__(
+ self._is_invert_branch_patch_available)
+ self._cb.isSkipAndReturnZeroPatchAvailable = self._cb.isSkipAndReturnZeroPatchAvailable.__class__(
+ self._is_skip_and_return_zero_patch_available)
+ self._cb.isSkipAndReturnValuePatchAvailable = self._cb.isSkipAndReturnValuePatchAvailable.__class__(
+ self._is_skip_and_return_value_patch_available)
+ self._cb.convertToNop = self._cb.convertToNop.__class__(self._convert_to_nop)
+ self._cb.alwaysBranch = self._cb.alwaysBranch.__class__(self._always_branch)
+ self._cb.invertBranch = self._cb.invertBranch.__class__(self._invert_branch)
+ self._cb.skipAndReturnValue = self._cb.skipAndReturnValue.__class__(self._skip_and_return_value)
- count = ctypes.c_ulonglong()
- types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count)
- self._flag_write_types = {}
- self._flag_write_types_by_index = {}
- self.__dict__["flag_write_types"] = []
- for i in xrange(0, count.value):
- name = core.BNGetArchitectureFlagWriteTypeName(self.handle, types[i])
- self._flag_write_types[name] = types[i]
- self._flag_write_types_by_index[types[i]] = name
- self.flag_write_types.append(name)
- core.BNFreeRegisterList(types)
+ self.__dict__["endianness"] = self.__class__.endianness
+ self.__dict__["address_size"] = self.__class__.address_size
+ self.__dict__["default_int_size"] = self.__class__.default_int_size
+ self.__dict__["instr_alignment"] = self.__class__.instr_alignment
+ self.__dict__["max_instr_length"] = self.__class__.max_instr_length
+ self.__dict__["opcode_display_length"] = self.__class__.opcode_display_length
+ self.__dict__["stack_pointer"] = self.__class__.stack_pointer
+ self.__dict__["link_reg"] = self.__class__.link_reg
- self._flag_roles = {}
- self.__dict__["flag_roles"] = {}
- for flag in self.__dict__["flags"]:
- role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag]))
- self.__dict__["flag_roles"][flag] = role
- self._flag_roles[self._flags[flag]] = role
+ self._all_regs = {}
+ self._full_width_regs = {}
+ self._regs_by_index = {}
+ self.__dict__["regs"] = self.__class__.regs
+ reg_index = 0
- self._flags_required_for_flag_condition = {}
- self.__dict__["flags_required_for_flag_condition"] = {}
- for cond in LowLevelILFlagCondition:
- count = ctypes.c_ulonglong()
- flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, count)
- flag_indexes = []
- flag_names = []
- for i in xrange(0, count.value):
- flag_indexes.append(flags[i])
- flag_names.append(self._flags_by_index[flags[i]])
- core.BNFreeRegisterList(flags)
- self._flags_required_for_flag_condition[cond] = flag_indexes
- self.__dict__["flags_required_for_flag_condition"][cond] = flag_names
+ # 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
- self._flags_written_by_flag_write_type = {}
- self.__dict__["flags_written_by_flag_write_type"] = {}
- for write_type in self.flag_write_types:
- count = ctypes.c_ulonglong()
- flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle,
- self._flag_write_types[write_type], count)
- flag_indexes = []
- flag_names = []
- for i in xrange(0, count.value):
- flag_indexes.append(flags[i])
- flag_names.append(self._flags_by_index[flags[i]])
- core.BNFreeRegisterList(flags)
- self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes
- self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names
+ for reg in self.regs:
+ info = self.regs[reg]
+ if reg not in self._all_regs:
+ self._all_regs[reg] = reg_index
+ self._regs_by_index[reg_index] = reg
+ self.regs[reg].index = reg_index
+ reg_index += 1
+ if info.full_width_reg not in self._all_regs:
+ self._all_regs[info.full_width_reg] = reg_index
+ self._regs_by_index[reg_index] = info.full_width_reg
+ self.regs[info.full_width_reg].index = reg_index
+ reg_index += 1
+ if info.full_width_reg not in self._full_width_regs:
+ self._full_width_regs[info.full_width_reg] = self._all_regs[info.full_width_reg]
- count = ctypes.c_ulonglong()
- regs = core.BNGetArchitectureGlobalRegisters(self.handle, count)
- self.__dict__["global_regs"] = []
- for i in xrange(0, count.value):
- self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i]))
- core.BNFreeRegisterList(regs)
- else:
- startup._init_plugins()
+ self._flags = {}
+ self._flags_by_index = {}
+ self.__dict__["flags"] = self.__class__.flags
+ flag_index = 0
+ for flag in self.__class__.flags:
+ if flag not in self._flags:
+ self._flags[flag] = flag_index
+ self._flags_by_index[flag_index] = flag
+ flag_index += 1
- if self.__class__.opcode_display_length > self.__class__.max_instr_length:
- self.__class__.opcode_display_length = self.__class__.max_instr_length
+ self._flag_write_types = {}
+ self._flag_write_types_by_index = {}
+ self.__dict__["flag_write_types"] = self.__class__.flag_write_types
+ write_type_index = 0
+ for write_type in self.__class__.flag_write_types:
+ if write_type not in self._flag_write_types:
+ self._flag_write_types[write_type] = write_type_index
+ self._flag_write_types_by_index[write_type_index] = write_type
+ write_type_index += 1
- self._cb = core.BNCustomArchitecture()
- self._cb.context = 0
- self._cb.init = self._cb.init.__class__(self._init)
- self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness)
- self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size)
- self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size)
- self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment)
- self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length)
- self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length)
- self._cb.getAssociatedArchitectureByAddress = \
- self._cb.getAssociatedArchitectureByAddress.__class__(self._get_associated_arch_by_address)
- self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info)
- self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text)
- self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text)
- self._cb.getInstructionLowLevelIL = self._cb.getInstructionLowLevelIL.__class__(
- self._get_instruction_low_level_il)
- self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name)
- self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name)
- self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name)
- self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers)
- self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers)
- self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags)
- self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types)
- self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role)
- self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__(
- self._get_flags_required_for_flag_condition)
- self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__(
- self._get_flags_written_by_flag_write_type)
- self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__(
- self._get_flag_write_low_level_il)
- self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__(
- self._get_flag_condition_low_level_il)
- self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list)
- self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info)
- self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__(
- 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.assemble = self._cb.assemble.__class__(self._assemble)
- self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__(
- self._is_never_branch_patch_available)
- self._cb.isAlwaysBranchPatchAvailable = self._cb.isAlwaysBranchPatchAvailable.__class__(
- self._is_always_branch_patch_available)
- self._cb.isInvertBranchPatchAvailable = self._cb.isInvertBranchPatchAvailable.__class__(
- self._is_invert_branch_patch_available)
- self._cb.isSkipAndReturnZeroPatchAvailable = self._cb.isSkipAndReturnZeroPatchAvailable.__class__(
- self._is_skip_and_return_zero_patch_available)
- self._cb.isSkipAndReturnValuePatchAvailable = self._cb.isSkipAndReturnValuePatchAvailable.__class__(
- self._is_skip_and_return_value_patch_available)
- self._cb.convertToNop = self._cb.convertToNop.__class__(self._convert_to_nop)
- self._cb.alwaysBranch = self._cb.alwaysBranch.__class__(self._always_branch)
- self._cb.invertBranch = self._cb.invertBranch.__class__(self._invert_branch)
- self._cb.skipAndReturnValue = self._cb.skipAndReturnValue.__class__(self._skip_and_return_value)
+ self._semantic_flag_classes = {}
+ self._semantic_flag_classes_by_index = {}
+ self.__dict__["semantic_flag_classes"] = self.__class__.semantic_flag_classes
+ semantic_class_index = 1
+ for sem_class in self.__class__.semantic_flag_classes:
+ if sem_class not in self._semantic_flag_classes:
+ self._semantic_flag_classes[sem_class] = semantic_class_index
+ self._semantic_flag_classes_by_index[semantic_class_index] = sem_class
+ semantic_class_index += 1
- self._all_regs = {}
- self._full_width_regs = {}
- self._regs_by_index = {}
- self.__dict__["regs"] = self.__class__.regs
- reg_index = 0
- for reg in self.regs:
- info = self.regs[reg]
- if reg not in self._all_regs:
- self._all_regs[reg] = reg_index
- self._regs_by_index[reg_index] = reg
- self.regs[reg].index = reg_index
- reg_index += 1
- if info.full_width_reg not in self._all_regs:
- self._all_regs[info.full_width_reg] = reg_index
- self._regs_by_index[reg_index] = info.full_width_reg
- self.regs[info.full_width_reg].index = reg_index
- reg_index += 1
- if info.full_width_reg not in self._full_width_regs:
- self._full_width_regs[info.full_width_reg] = self._all_regs[info.full_width_reg]
+ self._semantic_flag_groups = {}
+ self._semantic_flag_groups_by_index = {}
+ self.__dict__["semantic_flag_groups"] = self.__class__.semantic_flag_groups
+ semantic_group_index = 0
+ for sem_group in self.__class__.semantic_flag_groups:
+ if sem_group not in self._semantic_flag_groups:
+ self._semantic_flag_groups[sem_group] = semantic_group_index
+ self._semantic_flag_groups_by_index[semantic_group_index] = sem_group
+ semantic_group_index += 1
- self._flags = {}
- self._flags_by_index = {}
- self.__dict__["flags"] = self.__class__.flags
- flag_index = 0
- for flag in self.__class__.flags:
- if flag not in self._flags:
- self._flags[flag] = flag_index
- self._flags_by_index[flag_index] = flag
- flag_index += 1
+ self._flag_roles = {}
+ self.__dict__["flag_roles"] = self.__class__.flag_roles
+ for flag in self.__class__.flag_roles:
+ role = self.__class__.flag_roles[flag]
+ if isinstance(role, str):
+ role = FlagRole[role]
+ self._flag_roles[self._flags[flag]] = role
- self._flag_write_types = {}
- self._flag_write_types_by_index = {}
- self.__dict__["flag_write_types"] = self.__class__.flag_write_types
- write_type_index = 0
- for write_type in self.__class__.flag_write_types:
- if write_type not in self._flag_write_types:
- self._flag_write_types[write_type] = write_type_index
- self._flag_write_types_by_index[write_type_index] = write_type
- write_type_index += 1
+ self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition
- self._flag_roles = {}
- self.__dict__["flag_roles"] = self.__class__.flag_roles
- for flag in self.__class__.flag_roles:
- role = self.__class__.flag_roles[flag]
- if isinstance(role, str):
- role = FlagRole[role]
- self._flag_roles[self._flags[flag]] = role
+ self._flags_required_by_semantic_flag_group = {}
+ self.__dict__["flags_required_for_semantic_flag_group"] = self.__class__.flags_required_for_semantic_flag_group
+ for group in self.__class__.flags_required_for_semantic_flag_group:
+ flags = []
+ for flag in self.__class__.flags_required_for_semantic_flag_group[group]:
+ flags.append(self._flags[flag])
+ self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flags
- self._flags_required_for_flag_condition = {}
- self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition
- for cond in self.__class__.flags_required_for_flag_condition:
- flags = []
- for flag in self.__class__.flags_required_for_flag_condition[cond]:
- flags.append(self._flags[flag])
- self._flags_required_for_flag_condition[cond] = flags
+ self._flag_conditions_for_semantic_flag_group = {}
+ self.__dict__["flag_conditions_for_semantic_flag_group"] = self.__class__.flag_conditions_for_semantic_flag_group
+ for group in self.__class__.flag_conditions_for_semantic_flag_group:
+ class_cond = {}
+ for sem_class in self.__class__.flag_conditions_for_semantic_flag_group[group]:
+ if sem_class is None:
+ class_cond[0] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class]
+ else:
+ class_cond[self._semantic_flag_classes[sem_class]] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class]
+ self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_cond
- self._flags_written_by_flag_write_type = {}
- self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type
- for write_type in self.__class__.flags_written_by_flag_write_type:
- flags = []
- for flag in self.__class__.flags_written_by_flag_write_type[write_type]:
- flags.append(self._flags[flag])
- self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags
+ self._flags_written_by_flag_write_type = {}
+ self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type
+ for write_type in self.__class__.flags_written_by_flag_write_type:
+ flags = []
+ for flag in self.__class__.flags_written_by_flag_write_type[write_type]:
+ flags.append(self._flags[flag])
+ self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags
- self.__dict__["global_regs"] = self.__class__.global_regs
+ self._semantic_class_for_flag_write_type = {}
+ self.__dict__["semantic_class_for_flag_write_type"] = self.__class__.semantic_class_for_flag_write_type
+ for write_type in self.__class__.semantic_class_for_flag_write_type:
+ sem_class = self.__class__.semantic_class_for_flag_write_type[write_type]
+ if sem_class in self._semantic_flag_classes:
+ sem_class_index = self._semantic_flag_classes[sem_class]
+ else:
+ sem_class_index = 0
+ self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class_index
+
+ self.__dict__["global_regs"] = self.__class__.global_regs
- self._pending_reg_lists = {}
- self._pending_token_lists = {}
+ self._intrinsics = {}
+ self._intrinsics_by_index = {}
+ self.__dict__["intrinsics"] = self.__class__.intrinsics
+ intrinsic_index = 0
+ for intrinsic in self.__class__.intrinsics.keys():
+ if intrinsic not in self._intrinsics:
+ info = self.__class__.intrinsics[intrinsic]
+ for i in xrange(0, len(info.inputs)):
+ if isinstance(info.inputs[i], types.Type):
+ info.inputs[i] = function.IntrinsicInput(info.inputs[i])
+ elif isinstance(info.inputs[i], tuple):
+ info.inputs[i] = function.IntrinsicInput(info.inputs[i][0], info.inputs[i][1])
+ info.index = intrinsic_index
+ self._intrinsics[intrinsic] = intrinsic_index
+ self._intrinsics_by_index[intrinsic_index] = (intrinsic, info)
+ intrinsic_index += 1
+
+ self._pending_reg_lists = {}
+ self._pending_token_lists = {}
+ self._pending_condition_lists = {}
+ self._pending_name_and_type_lists = {}
+ self._pending_type_lists = {}
def __eq__(self, value):
if not isinstance(value, Architecture):
@@ -405,49 +439,49 @@ class Architecture(object):
def _get_endianness(self, ctxt):
try:
- return self.__class__.endianness
+ return self.endianness
except:
log.log_error(traceback.format_exc())
return Endianness.LittleEndian
def _get_address_size(self, ctxt):
try:
- return self.__class__.address_size
+ return self.address_size
except:
log.log_error(traceback.format_exc())
return 8
def _get_default_integer_size(self, ctxt):
try:
- return self.__class__.default_int_size
+ return self.default_int_size
except:
log.log_error(traceback.format_exc())
return 4
def _get_instruction_alignment(self, ctxt):
try:
- return self.__class__.instr_alignment
+ return self.instr_alignment
except:
log.log_error(traceback.format_exc())
return 1
def _get_max_instruction_length(self, ctxt):
try:
- return self.__class__.max_instr_length
+ return self.max_instr_length
except:
log.log_error(traceback.format_exc())
return 16
def _get_opcode_display_length(self, ctxt):
try:
- return self.__class__.opcode_display_length
+ return self.opcode_display_length
except:
log.log_error(traceback.format_exc())
return 8
def _get_associated_arch_by_address(self, ctxt, addr):
try:
- result, new_addr = self.perform_get_associated_arch_by_address(addr[0])
+ result, new_addr = self.get_associated_arch_by_address(addr[0])
addr[0] = new_addr
return ctypes.cast(result.handle, ctypes.c_void_p).value
except:
@@ -458,7 +492,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(max_len)
ctypes.memmove(buf, data, max_len)
- info = self.perform_get_instruction_info(buf.raw, addr)
+ info = self.get_instruction_info(buf.raw, addr)
if info is None:
return False
result[0].length = info.length
@@ -484,7 +518,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length[0])
ctypes.memmove(buf, data, length[0])
- info = self.perform_get_instruction_text(buf.raw, addr)
+ info = self.get_instruction_text(buf.raw, addr)
if info is None:
return False
tokens = info[0]
@@ -524,7 +558,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length[0])
ctypes.memmove(buf, data, length[0])
- result = self.perform_get_instruction_low_level_il(buf.raw, addr,
+ result = self.get_instruction_low_level_il(buf.raw, addr,
lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il)))
if result is None:
return False
@@ -561,6 +595,24 @@ class Architecture(object):
log.log_error(traceback.format_exc())
return core.BNAllocString("")
+ def _get_semantic_flag_class_name(self, ctxt, sem_class):
+ try:
+ if sem_class in self._semantic_flag_classes_by_index:
+ return core.BNAllocString(self._semantic_flag_classes_by_index[sem_class])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
+ def _get_semantic_flag_group_name(self, ctxt, sem_group):
+ try:
+ if sem_group in self._semantic_flag_groups_by_index:
+ return core.BNAllocString(self._semantic_flag_groups_by_index[sem_group])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
def _get_full_width_registers(self, ctxt, count):
try:
regs = self._full_width_regs.values()
@@ -608,11 +660,11 @@ class Architecture(object):
def _get_all_flag_write_types(self, ctxt, count):
try:
- types = self._flag_write_types_by_index.keys()
- count[0] = len(types)
- type_buf = (ctypes.c_uint * len(types))()
- for i in xrange(0, len(types)):
- type_buf[i] = types[i]
+ write_types = self._flag_write_types_by_index.keys()
+ count[0] = len(write_types)
+ type_buf = (ctypes.c_uint * len(write_types))()
+ for i in xrange(0, len(write_types)):
+ type_buf[i] = write_types[i]
result = ctypes.cast(type_buf, ctypes.c_void_p)
self._pending_reg_lists[result.value] = (result, type_buf)
return result.value
@@ -621,19 +673,73 @@ class Architecture(object):
count[0] = 0
return None
- def _get_flag_role(self, ctxt, flag):
+ def _get_all_semantic_flag_classes(self, ctxt, count):
+ try:
+ sem_classes = self._semantic_flag_classes_by_index.keys()
+ count[0] = len(sem_classes)
+ class_buf = (ctypes.c_uint * len(sem_classes))()
+ for i in xrange(0, len(sem_classes)):
+ class_buf[i] = sem_classes[i]
+ result = ctypes.cast(class_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, class_buf)
+ return result.value
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_all_semantic_flag_groups(self, ctxt, count):
try:
- if flag in self._flag_roles:
- return self._flag_roles[flag]
+ sem_groups = self._semantic_flag_groups_by_index.keys()
+ count[0] = len(sem_groups)
+ group_buf = (ctypes.c_uint * len(sem_groups))()
+ for i in xrange(0, len(sem_groups)):
+ group_buf[i] = sem_groups[i]
+ result = ctypes.cast(group_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, group_buf)
+ return result.value
+ except KeyError:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_flag_role(self, ctxt, flag, sem_class):
+ try:
+ if sem_class in self._semantic_flag_classes_by_index:
+ sem_class = self._semantic_flag_classes_by_index[sem_class]
+ else:
+ sem_class = None
+ return self.get_flag_role(flag, sem_class)
+ except KeyError:
+ log.log_error(traceback.format_exc())
return FlagRole.SpecialFlagRole
+
+ def _get_flags_required_for_flag_condition(self, ctxt, cond, sem_class, count):
+ try:
+ if sem_class in self._semantic_flag_classes_by_index:
+ sem_class = self._semantic_flag_classes_by_index[sem_class]
+ else:
+ sem_class = None
+ flag_names = self.get_flags_required_for_flag_condition(cond, sem_class)
+ flags = []
+ for name in flag_names:
+ flags.append(self._flags[name])
+ count[0] = len(flags)
+ flag_buf = (ctypes.c_uint * len(flags))()
+ for i in xrange(0, len(flags)):
+ flag_buf[i] = flags[i]
+ result = ctypes.cast(flag_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, flag_buf)
+ return result.value
except KeyError:
log.log_error(traceback.format_exc())
+ count[0] = 0
return None
- def _get_flags_required_for_flag_condition(self, ctxt, cond, count):
+ def _get_flags_required_for_semantic_flag_group(self, ctxt, sem_group, count):
try:
- if cond in self._flags_required_for_flag_condition:
- flags = self._flags_required_for_flag_condition[cond]
+ if sem_group in self._flags_required_by_semantic_flag_group:
+ flags = self._flags_required_by_semantic_flag_group[sem_group]
else:
flags = []
count[0] = len(flags)
@@ -643,11 +749,41 @@ class Architecture(object):
result = ctypes.cast(flag_buf, ctypes.c_void_p)
self._pending_reg_lists[result.value] = (result, flag_buf)
return result.value
- except KeyError:
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_flag_conditions_for_semantic_flag_group(self, ctxt, sem_group, count):
+ try:
+ if sem_group in self._flag_conditions_for_semantic_flag_group:
+ class_cond = self._flag_conditions_for_semantic_flag_group[sem_group]
+ else:
+ class_cond = {}
+ count[0] = len(class_cond)
+ cond_buf = (core.BNFlagConditionForSemanticClass * len(class_cond))()
+ i = 0
+ for class_index in class_cond.keys():
+ cond_buf[i].semanticClass = class_index
+ cond_buf[i].condition = class_cond[class_index]
+ i += 1
+ result = ctypes.cast(cond_buf, ctypes.c_void_p)
+ self._pending_condition_lists[result.value] = (result, cond_buf)
+ return result.value
+ except (KeyError, OSError):
log.log_error(traceback.format_exc())
count[0] = 0
return None
+ def _free_flag_conditions_for_semantic_flag_group(self, ctxt, conditions):
+ try:
+ buf = ctypes.cast(conditions, ctypes.c_void_p)
+ if buf.value not in self._pending_condition_lists:
+ raise ValueError("freeing condition list that wasn't allocated")
+ del self._pending_condition_lists[buf.value]
+ except (ValueError, KeyError):
+ log.log_error(traceback.format_exc())
+
def _get_flags_written_by_flag_write_type(self, ctxt, write_type, count):
try:
if write_type in self._flags_written_by_flag_write_type:
@@ -666,6 +802,16 @@ class Architecture(object):
count[0] = 0
return None
+ def _get_semantic_class_for_flag_write_type(self, ctxt, write_type):
+ try:
+ if write_type in self._semantic_class_for_flag_write_type:
+ return self._semantic_class_for_flag_write_type[write_type]
+ else:
+ return 0
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return 0
+
def _get_flag_write_low_level_il(self, ctxt, op, size, write_type, flag, operands, operand_count, il):
try:
write_type_name = None
@@ -680,15 +826,31 @@ class Architecture(object):
operand_list.append(lowlevelil.ILRegister(self, operands[i].reg))
else:
operand_list.append(lowlevelil.ILRegister(self, operands[i].reg))
- return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list,
+ return self.get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list,
lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index
except (KeyError, OSError):
log.log_error(traceback.format_exc())
return False
- def _get_flag_condition_low_level_il(self, ctxt, cond, il):
+ def _get_flag_condition_low_level_il(self, ctxt, cond, sem_class, il):
try:
- return self.perform_get_flag_condition_low_level_il(cond,
+ if sem_class in self._semantic_flag_classes_by_index:
+ sem_class_name = self._semantic_flag_classes_by_index[sem_class]
+ else:
+ sem_class_name = None
+ return self.get_flag_condition_low_level_il(cond, sem_class_name,
+ lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index
+ except OSError:
+ log.log_error(traceback.format_exc())
+ return 0
+
+ def _get_semantic_flag_group_low_level_il(self, ctxt, sem_group, il):
+ try:
+ if sem_group in self._semantic_flag_groups_by_index:
+ sem_group_name = self._semantic_flag_groups_by_index[sem_group]
+ else:
+ sem_group_name = None
+ return self.get_semantic_flag_group_low_level_il(sem_group_name,
lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index
except OSError:
log.log_error(traceback.format_exc())
@@ -711,7 +873,7 @@ class Architecture(object):
result[0].size = 0
result[0].extend = ImplicitRegisterExtend.NoExtend
return
- info = self.__class__.regs[self._regs_by_index[reg]]
+ info = self.regs[self._regs_by_index[reg]]
result[0].fullWidthRegister = self._all_regs[info.full_width_reg]
result[0].offset = info.offset
result[0].size = info.size
@@ -728,26 +890,50 @@ class Architecture(object):
def _get_stack_pointer_register(self, ctxt):
try:
- return self._all_regs[self.__class__.stack_pointer]
+ return self._all_regs[self.stack_pointer]
except KeyError:
log.log_error(traceback.format_exc())
return 0
def _get_link_register(self, ctxt):
try:
- if self.__class__.link_reg is None:
+ if self.link_reg is None:
return 0xffffffff
- return self._all_regs[self.__class__.link_reg]
+ return self._all_regs[self.link_reg]
except KeyError:
log.log_error(traceback.format_exc())
return 0
def _get_global_registers(self, ctxt, count):
try:
- count[0] = len(self.__class__.global_regs)
- reg_buf = (ctypes.c_uint * len(self.__class__.global_regs))()
- for i in xrange(0, len(self.__class__.global_regs)):
- reg_buf[i] = self._all_regs[self.__class__.global_regs[i]]
+ count[0] = len(self.global_regs)
+ reg_buf = (ctypes.c_uint * len(self.global_regs))()
+ for i in xrange(0, len(self.global_regs)):
+ reg_buf[i] = self._all_regs[self.global_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_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
@@ -756,9 +942,125 @@ class Architecture(object):
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.reg_stacks[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 _get_intrinsic_name(self, ctxt, intrinsic):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ return core.BNAllocString(self._intrinsics_by_index[intrinsic][0])
+ return core.BNAllocString("")
+ except (KeyError, OSError):
+ log.log_error(traceback.format_exc())
+ return core.BNAllocString("")
+
+ def _get_all_intrinsics(self, ctxt, count):
+ try:
+ regs = self._intrinsics_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_intrinsic_inputs(self, ctxt, intrinsic, count):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ inputs = self._intrinsics_by_index[intrinsic][1].inputs
+ count[0] = len(inputs)
+ input_buf = (core.BNNameAndType * len(inputs))()
+ for i in xrange(0, len(inputs)):
+ input_buf[i].name = inputs[i].name
+ input_buf[i].type = core.BNNewTypeReference(inputs[i].type.handle)
+ input_buf[i].typeConfidence = inputs[i].type.confidence
+ result = ctypes.cast(input_buf, ctypes.c_void_p)
+ self._pending_name_and_type_lists[result.value] = (result, input_buf, len(inputs))
+ return result.value
+ count[0] = 0
+ return None
+ except:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _free_name_and_type_list(self, ctxt, buf_raw, length):
+ try:
+ buf = ctypes.cast(buf_raw, ctypes.c_void_p)
+ if buf.value not in self._pending_name_and_type_lists:
+ raise ValueError("freeing name and type list that wasn't allocated")
+ name_and_types = self._pending_name_and_type_lists[buf.value][1]
+ count = self._pending_name_and_type_lists[buf.value][2]
+ for i in xrange(0, count):
+ core.BNFreeType(name_and_types[i].type)
+ del self._pending_name_and_type_lists[buf.value]
+ except (ValueError, KeyError):
+ log.log_error(traceback.format_exc())
+
+ def _get_intrinsic_outputs(self, ctxt, intrinsic, count):
+ try:
+ if intrinsic in self._intrinsics_by_index:
+ outputs = self._intrinsics_by_index[intrinsic][1].outputs
+ count[0] = len(outputs)
+ output_buf = (core.BNTypeWithConfidence * len(outputs))()
+ for i in xrange(0, len(outputs)):
+ output_buf[i].type = core.BNNewTypeReference(outputs[i].handle)
+ output_buf[i].confidence = outputs[i].confidence
+ result = ctypes.cast(output_buf, ctypes.c_void_p)
+ self._pending_type_lists[result.value] = (result, output_buf, len(outputs))
+ return result.value
+ count[0] = 0
+ return None
+ except:
+ log.log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _free_type_list(self, ctxt, buf_raw, length):
+ try:
+ buf = ctypes.cast(buf_raw, ctypes.c_void_p)
+ if buf.value not in self._pending_type_lists:
+ raise ValueError("freeing type list that wasn't allocated")
+ types = self._pending_type_lists[buf.value][1]
+ count = self._pending_type_lists[buf.value][2]
+ for i in xrange(0, count):
+ core.BNFreeType(types[i].type)
+ del self._pending_type_lists[buf.value]
+ except (ValueError, KeyError):
+ log.log_error(traceback.format_exc())
+
def _assemble(self, ctxt, code, addr, result, errors):
try:
- data, error_str = self.perform_assemble(code, addr)
+ data, error_str = self.assemble(code, addr)
errors[0] = core.BNAllocString(str(error_str))
if data is None:
return False
@@ -776,7 +1078,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- return self.perform_is_never_branch_patch_available(buf.raw, addr)
+ return self.is_never_branch_patch_available(buf.raw, addr)
except:
log.log_error(traceback.format_exc())
return False
@@ -785,7 +1087,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- return self.perform_is_always_branch_patch_available(buf.raw, addr)
+ return self.is_always_branch_patch_available(buf.raw, addr)
except:
log.log_error(traceback.format_exc())
return False
@@ -794,7 +1096,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- return self.perform_is_invert_branch_patch_available(buf.raw, addr)
+ return self.is_invert_branch_patch_available(buf.raw, addr)
except:
log.log_error(traceback.format_exc())
return False
@@ -803,7 +1105,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- return self.perform_is_skip_and_return_zero_patch_available(buf.raw, addr)
+ return self.is_skip_and_return_zero_patch_available(buf.raw, addr)
except:
log.log_error(traceback.format_exc())
return False
@@ -812,7 +1114,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- return self.perform_is_skip_and_return_value_patch_available(buf.raw, addr)
+ return self.is_skip_and_return_value_patch_available(buf.raw, addr)
except:
log.log_error(traceback.format_exc())
return False
@@ -821,7 +1123,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- result = self.perform_convert_to_nop(buf.raw, addr)
+ result = self.convert_to_nop(buf.raw, addr)
if result is None:
return False
result = str(result)
@@ -837,7 +1139,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- result = self.perform_always_branch(buf.raw, addr)
+ result = self.always_branch(buf.raw, addr)
if result is None:
return False
result = str(result)
@@ -853,7 +1155,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- result = self.perform_invert_branch(buf.raw, addr)
+ result = self.invert_branch(buf.raw, addr)
if result is None:
return False
result = str(result)
@@ -869,7 +1171,7 @@ class Architecture(object):
try:
buf = ctypes.create_string_buffer(length)
ctypes.memmove(buf, data, length)
- result = self.perform_skip_and_return_value(buf.raw, addr, value)
+ result = self.skip_and_return_value(buf.raw, addr, value)
if result is None:
return False
result = str(result)
@@ -882,27 +1184,15 @@ class Architecture(object):
return False
def perform_get_associated_arch_by_address(self, addr):
+ """
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_associated_arch_by_address``.
+ """
return self, addr
@abc.abstractmethod
def perform_get_instruction_info(self, data, addr):
"""
- ``perform_get_instruction_info`` implements a method which interpretes the bytes passed in ``data`` as an
- :py:Class:`InstructionInfo` object. The InstructionInfo object should have the length of the current instruction.
- If the instruction is a branch instruction the method should add a branch of the proper type:
-
- ===================== ===================================================
- BranchType Description
- ===================== ===================================================
- UnconditionalBranch Branch will always be taken
- FalseBranch False branch condition
- TrueBranch True branch condition
- CallDestination Branch is a call instruction (Branch with Link)
- FunctionReturn Branch returns from a function
- SystemCall System call instruction
- IndirectBranch Branch destination is a memory address or register
- UnresolvedBranch Call instruction that isn't
- ===================== ===================================================
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_info``.
:param str data: bytes to decode
:param int addr: virtual address of the byte to be decoded
@@ -914,8 +1204,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_get_instruction_text(self, data, addr):
"""
- ``perform_get_instruction_text`` implements a method which interpretes the bytes passed in ``data`` as a
- list of :py:class:`InstructionTextToken` objects.
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_text``.
:param str data: bytes to decode
:param int addr: virtual address of the byte to be decoded
@@ -927,10 +1216,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_get_instruction_low_level_il(self, data, addr, il):
"""
- ``perform_get_instruction_low_level_il`` implements a method to interpret the bytes passed in ``data`` to
- low-level IL instructions. The il instructions must be appended to the :py:class:`LowLevelILFunction`.
-
- .. note:: Architecture subclasses should implement this method.
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_instruction_low_level_il``.
:param str data: bytes to be interpreted as low-level IL instructions
:param int addr: virtual address of start of ``data``
@@ -942,8 +1228,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
"""
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_write_low_level_il``.
:param LowLevelILOperation op:
:param int size:
@@ -959,28 +1244,32 @@ class Architecture(object):
return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il)
@abc.abstractmethod
- def perform_get_flag_condition_low_level_il(self, cond, il):
+ def perform_get_flag_condition_low_level_il(self, cond, sem_class, il):
"""
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_condition_low_level_il``.
- :param LowLevelILFlagCondition cond:
- :param LowLevelILFunction il:
+ :param LowLevelILFlagCondition cond: Flag condition to be computed
+ :param str sem_class: Semantic class to be used (None for default semantics)
+ :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to
:rtype: LowLevelILExpr
"""
- return self.get_default_flag_condition_low_level_il(cond, il)
+ return self.get_default_flag_condition_low_level_il(cond, sem_class, il)
@abc.abstractmethod
- def perform_assemble(self, code, addr):
+ def perform_get_semantic_flag_group_low_level_il(self, sem_group, il):
"""
- ``perform_assemble`` implements a method to convert the string of assembly instructions ``code`` loaded at
- virtual address ``addr`` to the byte representation of those instructions. This can be done by simply shelling
- out to an assembler like yasm or llvm-mc, since this method isn't performance sensitive.
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_semantic_flag_group_low_level_il``.
- .. note:: Architecture subclasses should implement this method.
- .. note :: It is important that the assembler used accepts a syntax identical to the one emitted by the \
- disassembler. This will prevent confusing the user.
- .. warning:: This method should never be called directly.
+ :param str sem_group: Semantic group to be computed
+ :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to
+ :rtype: LowLevelILExpr
+ """
+ return il.unimplemented()
+
+ @abc.abstractmethod
+ def perform_assemble(self, code, addr):
+ """
+ Deprecated method provided for compatibility. Architecture plugins should override ``assemble``.
:param str code: string representation of the instructions to be assembled
:param int addr: virtual address that the instructions will be loaded at
@@ -992,8 +1281,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_is_never_branch_patch_available(self, data, addr):
"""
- ``perform_is_never_branch_patch_available`` implements a check to determine if the instruction represented by
- the bytes contained in ``data`` at address addr is a branch instruction that can be made to never branch.
+ Deprecated method provided for compatibility. Architecture plugins should override ``is_never_branch_patch_available``.
.. note:: Architecture subclasses should implement this method.
.. warning:: This method should never be called directly.
@@ -1008,11 +1296,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_is_always_branch_patch_available(self, data, addr):
"""
- ``perform_is_always_branch_patch_available`` implements a check to determine if the instruction represented by
- the bytes contained in ``data`` at address addr is a conditional branch that can be made unconditional.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``is_always_branch_patch_available``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1024,11 +1308,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_is_invert_branch_patch_available(self, data, addr):
"""
- ``perform_is_invert_branch_patch_available`` implements a check to determine if the instruction represented by
- the bytes contained in ``data`` at address addr is a conditional branch which can be inverted.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``is_invert_branch_patch_available``.
:param int addr: the virtual address of the instruction to be patched
:return: True if the instruction can be patched, False otherwise
@@ -1039,13 +1319,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_is_skip_and_return_zero_patch_available(self, data, addr):
"""
- ``perform_is_skip_and_return_zero_patch_available`` implements a check to determine if the instruction represented by
- the bytes contained in ``data`` at address addr is a *call-like* instruction which can made into instructions
- that are equivilent to "return 0". For example if ``data`` was the x86 instruction ``call eax`` which could be
- converted into ``xor eax,eax`` thus this function would return True.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``is_skip_and_return_zero_patch_available``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1057,13 +1331,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_is_skip_and_return_value_patch_available(self, data, addr):
"""
- ``perform_is_skip_and_return_value_patch_available`` implements a check to determine if the instruction represented by
- the bytes contained in ``data`` at address addr is a *call-like* instruction which can made into instructions
- that are equivilent to "return 0". For example if ``data`` was the x86 instruction ``call 0xdeadbeef`` which could be
- converted into ``mov eax, 42`` thus this function would return True.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``is_skip_and_return_value_patch_available``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1075,10 +1343,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_convert_to_nop(self, data, addr):
"""
- ``perform_convert_to_nop`` implements a method which returns a nop sequence of len(data) bytes long.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``convert_to_nop``.
:param str data: bytes at virtual address ``addr``
:param int addr: the virtual address of the instruction to be patched
@@ -1090,11 +1355,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_always_branch(self, data, addr):
"""
- ``perform_always_branch`` implements a method which converts the branch represented by the bytes in ``data`` to
- at ``addr`` to an unconditional branch.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``always_branch``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1106,11 +1367,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_invert_branch(self, data, addr):
"""
- ``perform_invert_branch`` implements a method which inverts the branch represented by the bytes in ``data`` to
- at ``addr``.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``invert_branch``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1122,12 +1379,7 @@ class Architecture(object):
@abc.abstractmethod
def perform_skip_and_return_value(self, data, addr, value):
"""
- ``perform_skip_and_return_value`` implements a method which converts a *call-like* instruction represented by
- the bytes in ``data`` at ``addr`` to one or more instructions that are equivilent to a function returning a
- value.
-
- .. note:: Architecture subclasses should implement this method.
- .. warning:: This method should never be called directly.
+ Deprecated method provided for compatibility. Architecture plugins should override ``skip_and_return_value``.
:param str data: bytes to be checked
:param int addr: the virtual address of the instruction to be patched
@@ -1137,76 +1389,70 @@ class Architecture(object):
"""
return None
+ def perform_get_flag_role(self, flag, sem_class):
+ """
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_flag_role``.
+ """
+ if flag in self._flag_roles:
+ return self._flag_roles[flag]
+ return FlagRole.SpecialFlagRole
+
+ def perform_get_flags_required_for_flag_condition(self, cond, sem_class):
+ """
+ Deprecated method provided for compatibility. Architecture plugins should override ``get_flags_required_for_flag_condition``.
+ """
+ if cond in self.flags_required_for_flag_condition:
+ return self.flags_required_for_flag_condition[cond]
+ return []
+
def get_associated_arch_by_address(self, addr):
- new_addr = ctypes.c_ulonglong()
- new_addr.value = addr
- result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr)
- return Architecture(handle = result), new_addr.value
+ return self.perform_get_associated_arch_by_address(addr)
def get_instruction_info(self, data, addr):
"""
``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address
``addr`` with data ``data``.
+ .. note:: Architecture subclasses should implement this method.
+
.. note :: The instruction info object should always set the InstructionInfo.length to the instruction length, \
and the branches of the proper types shoulde be added if the instruction is a branch.
+ If the instruction is a branch instruction architecture plugins should add a branch of the proper type:
+
+ ===================== ===================================================
+ BranchType Description
+ ===================== ===================================================
+ UnconditionalBranch Branch will always be taken
+ FalseBranch False branch condition
+ TrueBranch True branch condition
+ CallDestination Branch is a call instruction (Branch with Link)
+ FunctionReturn Branch returns from a function
+ SystemCall System call instruction
+ IndirectBranch Branch destination is a memory address or register
+ UnresolvedBranch Branch destination is an unknown address
+ ===================== ===================================================
+
:param str data: max_instruction_length bytes from the binary at virtual address ``addr``
:param int addr: virtual address of bytes in ``data``
:return: the InstructionInfo for the current instruction
:rtype: InstructionInfo
"""
- info = core.BNInstructionInfo()
- data = str(data)
- buf = (ctypes.c_ubyte * len(data))()
- ctypes.memmove(buf, data, len(data))
- if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info):
- return None
- result = function.InstructionInfo()
- result.length = info.length
- result.arch_transition_by_target_addr = info.archTransitionByTargetAddr
- result.branch_delay = info.branchDelay
- for i in xrange(0, info.branchCount):
- target = info.branchTarget[i]
- if info.branchArch[i]:
- arch = Architecture(info.branchArch[i])
- else:
- arch = None
- result.add_branch(BranchType(info.branchType[i]), target, arch)
- return result
+ return self.perform_get_instruction_info(data, addr)
def get_instruction_text(self, data, addr):
"""
``get_instruction_text`` returns a list of InstructionTextToken objects for the instruction at the given virtual
address ``addr`` with data ``data``.
+ .. note:: Architecture subclasses should implement this method.
+
:param str data: max_instruction_length bytes from the binary at virtual address ``addr``
:param int addr: virtual address of bytes in ``data``
:return: an InstructionTextToken list for the current instruction
:rtype: list(InstructionTextToken)
"""
- data = str(data)
- count = ctypes.c_ulonglong()
- length = ctypes.c_ulonglong()
- length.value = len(data)
- buf = (ctypes.c_ubyte * len(data))()
- ctypes.memmove(buf, data, len(data))
- tokens = ctypes.POINTER(core.BNInstructionTextToken)()
- if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count):
- return None, 0
- result = []
- for i in xrange(0, count.value):
- token_type = InstructionTextTokenType(tokens[i].type)
- text = tokens[i].text
- value = tokens[i].value
- size = tokens[i].size
- operand = tokens[i].operand
- context = tokens[i].context
- confidence = tokens[i].confidence
- address = tokens[i].address
- result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
- core.BNFreeInstructionText(tokens, count.value)
- return result, length.value
+ return self.perform_get_instruction_text(data, addr)
def get_instruction_low_level_il_instruction(self, bv, addr):
il = lowlevelil.LowLevelILFunction(self)
@@ -1222,19 +1468,15 @@ class Architecture(object):
This is used to analyze arbitrary data at an address, if you are working with an existing binary, you likely
want to be using ``Function.get_low_level_il_at``.
+ .. note:: Architecture subclasses should implement this method.
+
:param str data: max_instruction_length bytes from the binary at virtual address ``addr``
:param int addr: virtual address of bytes in ``data``
:param LowLevelILFunction il: The function the current instruction belongs to
:return: the length of the current instruction
:rtype: int
"""
- data = str(data)
- length = ctypes.c_ulonglong()
- length.value = len(data)
- buf = (ctypes.c_ubyte * len(data))()
- ctypes.memmove(buf, data, len(data))
- core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle)
- return length.value
+ return self.perform_get_instruction_low_level_il(data, addr, il)
def get_low_level_il_from_bytes(self, data, addr):
"""
@@ -1264,6 +1506,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 +1540,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]
@@ -1288,6 +1554,69 @@ class Architecture(object):
return flag.index
return flag
+ def get_semantic_flag_class_index(self, sem_class):
+ if sem_class is None:
+ return 0
+ elif isinstance(sem_class, str):
+ return self._semantic_flag_classes[sem_class]
+ elif isinstance(sem_class, lowlevelil.ILSemanticFlagClass):
+ return sem_class.index
+ return sem_class
+
+ def get_semantic_flag_class_name(self, class_index):
+ """
+ ``get_semantic_flag_class_name`` gets the name of a semantic flag class from the index.
+
+ :param int _index: class_index
+ :return: the name of the semantic flag class
+ :rtype: str
+ """
+ if not isinstance(class_index, (int, long)):
+ raise ValueError("argument 'class_index' must be an integer")
+ try:
+ return self._semantic_flag_classes_by_index[class_index]
+ except KeyError:
+ raise AttributeError("argument class_index is not a valid class index")
+
+ def get_semantic_flag_group_index(self, sem_group):
+ if isinstance(sem_group, str):
+ return self._semantic_flag_groups[sem_group]
+ elif isinstance(sem_group, lowlevelil.ILSemanticFlagGroup):
+ return sem_group.index
+ return sem_group
+
+ def get_semantic_flag_group_name(self, group_index):
+ """
+ ``get_semantic_flag_group_name`` gets the name of a semantic flag group from the index.
+
+ :param int group_index: group_index
+ :return: the name of the semantic flag group
+ :rtype: str
+ """
+ if not isinstance(group_index, (int, long)):
+ raise ValueError("argument 'group_index' must be an integer")
+ try:
+ return self._semantic_flag_groups_by_index[group_index]
+ except KeyError:
+ raise AttributeError("argument group_index is not a valid group index")
+
+ def get_intrinsic_name(self, intrinsic):
+ """
+ ``get_intrinsic_name`` gets an intrinsic name from an intrinsic number.
+
+ :param int intrinsic: intrinsic number
+ :return: the corresponding intrinsic string
+ :rtype: str
+ """
+ return core.BNGetArchitectureIntrinsicName(self.handle, intrinsic)
+
+ def get_intrinsic_index(self, intrinsic):
+ if isinstance(intrinsic, str):
+ return self._intrinsics[intrinsic]
+ elif isinstance(intrinsic, lowlevelil.ILIntrinsic):
+ return intrinsic.index
+ return intrinsic
+
def get_flag_write_type_name(self, write_type):
"""
``get_flag_write_type_name`` gets the flag write type name for the given flag.
@@ -1318,6 +1647,37 @@ class Architecture(object):
"""
return self._flag_write_types[write_type]
+ def get_semantic_flag_class_by_name(self, sem_class):
+ """
+ ``get_semantic_flag_class_by_name`` gets the semantic flag class index by name.
+
+ :param int sem_class: semantic flag class
+ :return: semantic flag class index
+ :rtype: str
+ """
+ return self._semantic_flag_classes[sem_class]
+
+ def get_semantic_flag_group_by_name(self, sem_group):
+ """
+ ``get_semantic_flag_group_by_name`` gets the semantic flag group index by name.
+
+ :param int sem_group: semantic flag group
+ :return: semantic flag group index
+ :rtype: str
+ """
+ return self._semantic_flag_groups[sem_group]
+
+ def get_flag_role(self, flag, sem_class = None):
+ """
+ ``get_flag_role`` gets the role of a given flag.
+
+ :param int flag: flag
+ :param int sem_class: optional semantic flag class
+ :return: flag role
+ :rtype: FlagRole
+ """
+ return self.perform_get_flag_role(flag, sem_class)
+
def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
"""
:param LowLevelILOperation op:
@@ -1328,20 +1688,7 @@ class Architecture(object):
:param LowLevelILFunction il:
:rtype: LowLevelILExpr
"""
- flag = self.get_flag_index(flag)
- operand_list = (core.BNRegisterOrConstant * len(operands))()
- for i in xrange(len(operands)):
- if isinstance(operands[i], str):
- operand_list[i].constant = False
- operand_list[i].reg = self.regs[operands[i]].index
- elif isinstance(operands[i], lowlevelil.ILRegister):
- operand_list[i].constant = False
- operand_list[i].reg = operands[i].index
- else:
- operand_list[i].constant = True
- operand_list[i].value = operands[i]
- return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size,
- self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle))
+ return self.perform_get_flag_write_low_level_il(op, size, write_type, flag, operands, il)
def get_default_flag_write_low_level_il(self, op, size, role, operands, il):
"""
@@ -1367,21 +1714,35 @@ class Architecture(object):
return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size,
role, operand_list, len(operand_list), il.handle))
- def get_flag_condition_low_level_il(self, cond, il):
+ def get_flag_condition_low_level_il(self, cond, sem_class, il):
+ """
+ :param LowLevelILFlagCondition cond: Flag condition to be computed
+ :param str sem_class: Semantic class to be used (None for default semantics)
+ :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to
+ :rtype: LowLevelILExpr
+ """
+ return self.perform_get_flag_condition_low_level_il(cond, sem_class, il)
+
+ def get_default_flag_condition_low_level_il(self, cond, sem_class, il):
"""
:param LowLevelILFlagCondition cond:
:param LowLevelILFunction il:
+ :param str sem_class:
:rtype: LowLevelILExpr
"""
- return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle))
+ class_index = self.get_semantic_flag_class_index(sem_class)
+ return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, class_index, il.handle))
- def get_default_flag_condition_low_level_il(self, cond, il):
+ def get_semantic_flag_group_low_level_il(self, sem_group, il):
"""
- :param LowLevelILFlagCondition cond:
+ :param str sem_group:
:param LowLevelILFunction il:
:rtype: LowLevelILExpr
"""
- return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle))
+ return self.perform_get_semantic_flag_group_low_level_il(sem_group, il)
+
+ def get_flags_required_for_flag_condition(self, cond, sem_class = None):
+ return self.perform_get_flags_required_for_flag_condition(cond, sem_class)
def get_modified_regs_on_write(self, reg):
"""
@@ -1405,6 +1766,648 @@ class Architecture(object):
``assemble`` converts the string of assembly instructions ``code`` loaded at virtual address ``addr`` to the
byte representation of those instructions.
+ .. note:: Architecture subclasses should implement this method.
+
+ Architecture plugins can override this method to provide assembler functionality. This can be done by
+ simply shelling out to an assembler like yasm or llvm-mc, since this method isn't performance sensitive.
+
+ .. note :: It is important that the assembler used accepts a syntax identical to the one emitted by the \
+ disassembler. This will prevent confusing the user.
+
+ :param str code: string representation of the instructions to be assembled
+ :param int addr: virtual address that the instructions will be loaded at
+ :return: the bytes for the assembled instructions or error string
+ :rtype: (a tuple of instructions and empty string) or (or None and error string)
+ :Example:
+
+ >>> arch.assemble("je 10")
+ ('\\x0f\\x84\\x04\\x00\\x00\\x00', '')
+ >>>
+ """
+ return self.perform_assemble(code, addr)
+
+ def is_never_branch_patch_available(self, data, addr):
+ """
+ ``is_never_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be made to **never branch**.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be checked
+ :param int addr: the virtual address of the instruction to be patched
+ :return: True if the instruction can be patched, False otherwise
+ :rtype: bool
+ :Example:
+
+ >>> arch.is_never_branch_patch_available(arch.assemble("je 10")[0], 0)
+ True
+ >>> arch.is_never_branch_patch_available(arch.assemble("nop")[0], 0)
+ False
+ >>>
+ """
+ return self.perform_is_never_branch_patch_available(data, addr)
+
+ def is_always_branch_patch_available(self, data, addr):
+ """
+ ``is_always_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be made to
+ **always branch**.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be checked
+ :param int addr: the virtual address of the instruction to be patched
+ :return: True if the instruction can be patched, False otherwise
+ :rtype: bool
+ :Example:
+
+ >>> arch.is_always_branch_patch_available(arch.assemble("je 10")[0], 0)
+ True
+ >>> arch.is_always_branch_patch_available(arch.assemble("nop")[0], 0)
+ False
+ >>>
+ """
+ return self.perform_is_always_branch_patch_available(data, addr)
+
+ def is_invert_branch_patch_available(self, data, addr):
+ """
+ ``is_always_branch_patch_available`` determines if the instruction ``data`` at ``addr`` can be inverted.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be checked
+ :param int addr: the virtual address of the instruction to be patched
+ :return: True if the instruction can be patched, False otherwise
+ :rtype: bool
+ :Example:
+
+ >>> arch.is_invert_branch_patch_available(arch.assemble("je 10")[0], 0)
+ True
+ >>> arch.is_invert_branch_patch_available(arch.assemble("nop")[0], 0)
+ False
+ >>>
+ """
+ return self.perform_is_invert_branch_patch_available(data, addr)
+
+ def is_skip_and_return_zero_patch_available(self, data, addr):
+ """
+ ``is_skip_and_return_zero_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like*
+ instruction that can be made into an instruction *returns zero*.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be checked
+ :param int addr: the virtual address of the instruction to be patched
+ :return: True if the instruction can be patched, False otherwise
+ :rtype: bool
+ :Example:
+
+ >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call 0")[0], 0)
+ True
+ >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call eax")[0], 0)
+ True
+ >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("jmp eax")[0], 0)
+ False
+ >>>
+ """
+ return self.perform_is_skip_and_return_zero_patch_available(data, addr)
+
+ def is_skip_and_return_value_patch_available(self, data, addr):
+ """
+ ``is_skip_and_return_value_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like*
+ instruction that can be made into an instruction *returns a value*.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be checked
+ :param int addr: the virtual address of the instruction to be patched
+ :return: True if the instruction can be patched, False otherwise
+ :rtype: bool
+ :Example:
+
+ >>> arch.is_skip_and_return_value_patch_available(arch.assemble("call 0")[0], 0)
+ True
+ >>> arch.is_skip_and_return_value_patch_available(arch.assemble("jmp eax")[0], 0)
+ False
+ >>>
+ """
+ return self.perform_is_skip_and_return_value_patch_available(data, addr)
+
+ def convert_to_nop(self, data, addr):
+ """
+ ``convert_to_nop`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of nop
+ instructions of the same length as data.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be converted
+ :param int addr: the virtual address of the instruction to be patched
+ :return: string containing len(data) worth of no-operation instructions
+ :rtype: str
+ :Example:
+
+ >>> arch.convert_to_nop("\\x00\\x00", 0)
+ '\\x90\\x90'
+ >>>
+ """
+ return self.perform_convert_to_nop(data, addr)
+
+ def always_branch(self, data, addr):
+ """
+ ``always_branch`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of bytes
+ of the same length which always branches.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be converted
+ :param int addr: the virtual address of the instruction to be patched
+ :return: string containing len(data) which always branches to the same location as the provided instruction
+ :rtype: str
+ :Example:
+
+ >>> bytes = arch.always_branch(arch.assemble("je 10")[0], 0)
+ >>> arch.get_instruction_text(bytes, 0)
+ (['nop '], 1L)
+ >>> arch.get_instruction_text(bytes[1:], 0)
+ (['jmp ', '0x9'], 5L)
+ >>>
+ """
+ return self.perform_always_branch(data, addr)
+
+ def invert_branch(self, data, addr):
+ """
+ ``invert_branch`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of bytes
+ of the same length which inverts the branch of provided instruction.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be converted
+ :param int addr: the virtual address of the instruction to be patched
+ :return: string containing len(data) which always branches to the same location as the provided instruction
+ :rtype: str
+ :Example:
+
+ >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("je 10")[0], 0), 0)
+ (['jne ', '0xa'], 6L)
+ >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("jo 10")[0], 0), 0)
+ (['jno ', '0xa'], 6L)
+ >>> arch.get_instruction_text(arch.invert_branch(arch.assemble("jge 10")[0], 0), 0)
+ (['jl ', '0xa'], 6L)
+ >>>
+ """
+ return self.perform_invert_branch(data, addr)
+
+ def skip_and_return_value(self, data, addr, value):
+ """
+ ``skip_and_return_value`` reads the instruction(s) in ``data`` at virtual address ``addr`` and returns a string of
+ bytes of the same length which doesn't call and instead *return a value*.
+
+ .. note:: Architecture subclasses should implement this method.
+
+ :param str data: bytes for the instruction to be converted
+ :param int addr: the virtual address of the instruction to be patched
+ :return: string containing len(data) which always branches to the same location as the provided instruction
+ :rtype: str
+ :Example:
+
+ >>> arch.get_instruction_text(arch.skip_and_return_value(arch.assemble("call 10")[0], 0, 0), 0)
+ (['mov ', 'eax', ', ', '0x0'], 5L)
+ >>>
+ """
+ return self.perform_skip_and_return_value(data, addr, value)
+
+ def is_view_type_constant_defined(self, type_name, const_name):
+ """
+
+ :param str type_name: the BinaryView type name of the constant to query
+ :param str const_name: the constant name to query
+ :rtype: None
+ :Example:
+
+ >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
+ >>> arch.is_view_type_constant_defined("ELF", "R_COPY")
+ True
+ >>> arch.is_view_type_constant_defined("ELF", "NOT_THERE")
+ False
+ >>>
+ """
+ return core.BNIsBinaryViewTypeArchitectureConstantDefined(self.handle, type_name, const_name)
+
+ def get_view_type_constant(self, type_name, const_name, default_value=0):
+ """
+ ``get_view_type_constant`` retrieves the view type constant for the given type_name and const_name.
+
+ :param str type_name: the BinaryView type name of the constant to be retrieved
+ :param str const_name: the constant name to retrieved
+ :param int value: optional default value if the type_name is not present. default value is zero.
+ :return: The BinaryView type constant or the default_value if not found
+ :rtype: int
+ :Example:
+
+ >>> ELF_RELOC_COPY = 5
+ >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
+ >>> arch.get_view_type_constant("ELF", "R_COPY")
+ 5L
+ >>> arch.get_view_type_constant("ELF", "NOT_HERE", 100)
+ 100L
+ """
+ return core.BNGetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, default_value)
+
+ def set_view_type_constant(self, type_name, const_name, value):
+ """
+ ``set_view_type_constant`` creates a new binaryview type constant.
+
+ :param str type_name: the BinaryView type name of the constant to be registered
+ :param str const_name: the constant name to register
+ :param int value: the value of the constant
+ :rtype: None
+ :Example:
+
+ >>> ELF_RELOC_COPY = 5
+ >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
+ >>>
+ """
+ core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value)
+
+ def register_calling_convention(self, cc):
+ """
+ ``register_calling_convention`` registers a new calling convention for the Architecture.
+
+ :param CallingConvention cc: CallingConvention object to be registered
+ :rtype: None
+ """
+ core.BNRegisterCallingConvention(self.handle, cc.handle)
+
+
+_architecture_cache = {}
+class CoreArchitecture(Architecture):
+ def __init__(self, handle):
+ super(CoreArchitecture, self).__init__()
+
+ self.handle = core.handle_of_type(handle, core.BNArchitecture)
+ self.__dict__["name"] = core.BNGetArchitectureName(self.handle)
+ self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle))
+ self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle)
+ self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle)
+ self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle)
+ self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle)
+ self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle)
+ self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle,
+ core.BNGetArchitectureStackPointerRegister(self.handle))
+
+ link_reg = core.BNGetArchitectureLinkRegister(self.handle)
+ if link_reg == 0xffffffff:
+ self.__dict__["link_reg"] = None
+ else:
+ self.__dict__["link_reg"] = core.BNGetArchitectureRegisterName(self.handle, link_reg)
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetAllArchitectureRegisters(self.handle, count)
+ self._all_regs = {}
+ self._regs_by_index = {}
+ self._full_width_regs = {}
+ self.__dict__["regs"] = {}
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureRegisterName(self.handle, regs[i])
+ info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i])
+ full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister)
+ self.regs[name] = function.RegisterInfo(full_width_reg, info.size, info.offset,
+ ImplicitRegisterExtend(info.extend), regs[i])
+ self._all_regs[name] = regs[i]
+ self._regs_by_index[regs[i]] = name
+ for i in xrange(0, count.value):
+ info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i])
+ full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister)
+ if full_width_reg not in self._full_width_regs:
+ self._full_width_regs[full_width_reg] = self._all_regs[full_width_reg]
+ core.BNFreeRegisterList(regs)
+
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetAllArchitectureFlags(self.handle, count)
+ self._flags = {}
+ self._flags_by_index = {}
+ self.__dict__["flags"] = []
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureFlagName(self.handle, flags[i])
+ self._flags[name] = flags[i]
+ self._flags_by_index[flags[i]] = name
+ self.flags.append(name)
+ core.BNFreeRegisterList(flags)
+
+ count = ctypes.c_ulonglong()
+ write_types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count)
+ self._flag_write_types = {}
+ self._flag_write_types_by_index = {}
+ self.__dict__["flag_write_types"] = []
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureFlagWriteTypeName(self.handle, write_types[i])
+ self._flag_write_types[name] = write_types[i]
+ self._flag_write_types_by_index[write_types[i]] = name
+ self.flag_write_types.append(name)
+ core.BNFreeRegisterList(write_types)
+
+ count = ctypes.c_ulonglong()
+ sem_classes = core.BNGetAllArchitectureSemanticFlagClasses(self.handle, count)
+ self._semantic_flag_classes = {}
+ self._semantic_flag_classes_by_index = {}
+ self.__dict__["semantic_flag_classes"] = []
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureSemanticFlagClassName(self.handle, sem_classes[i])
+ self._semantic_flag_classes[name] = sem_classes[i]
+ self._semantic_flag_classes_by_index[sem_classes[i]] = name
+ self.semantic_flag_classes.append(name)
+ core.BNFreeRegisterList(sem_classes)
+
+ count = ctypes.c_ulonglong()
+ sem_groups = core.BNGetAllArchitectureSemanticFlagGroups(self.handle, count)
+ self._semantic_flag_groups = {}
+ self._semantic_flag_groups_by_index = {}
+ self.__dict__["semantic_flag_groups"] = []
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureSemanticFlagGroupName(self.handle, sem_groups[i])
+ self._semantic_flag_groups[name] = sem_groups[i]
+ self._semantic_flag_groups_by_index[sem_groups[i]] = name
+ self.semantic_flag_groups.append(name)
+ core.BNFreeRegisterList(sem_groups)
+
+ self._flag_roles = {}
+ self.__dict__["flag_roles"] = {}
+ for flag in self.__dict__["flags"]:
+ role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag], 0))
+ self.__dict__["flag_roles"][flag] = role
+ self._flag_roles[self._flags[flag]] = role
+
+ self.__dict__["flags_required_for_flag_condition"] = {}
+ for cond in LowLevelILFlagCondition:
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, 0, count)
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ self.__dict__["flags_required_for_flag_condition"][cond] = flag_names
+
+ self._flags_required_by_semantic_flag_group = {}
+ self.__dict__["flags_required_for_semantic_flag_group"] = {}
+ for group in self.semantic_flag_groups:
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsRequiredForSemanticFlagGroup(self.handle,
+ self._semantic_flag_groups[group], count)
+ flag_indexes = []
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_indexes.append(flags[i])
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flag_indexes
+ self.__dict__["flags_required_for_semantic_flag_group"][cond] = flag_names
+
+ self._flag_conditions_for_semantic_flag_group = {}
+ self.__dict__["flag_conditions_for_semantic_flag_group"] = {}
+ for group in self.semantic_flag_groups:
+ count = ctypes.c_ulonglong()
+ conditions = core.BNGetArchitectureFlagConditionsForSemanticFlagGroup(self.handle,
+ self._semantic_flag_groups[group], count)
+ class_index_cond = {}
+ class_cond = {}
+ for i in xrange(0, count.value):
+ class_index_cond[conditions[i].semanticClass] = conditions[i].condition
+ if conditions[i].semanticClass == 0:
+ class_cond[None] = conditions[i].condition
+ elif conditions[i].semanticClass in self._semantic_flag_classes_by_index:
+ class_cond[self._semantic_flag_classes_by_index[conditions[i].semanticClass]] = conditions[i].condition
+ core.BNFreeFlagConditionsForSemanticFlagGroup(conditions)
+ self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_index_cond
+ self.__dict__["flag_conditions_for_semantic_flag_group"][group] = class_cond
+
+ self._flags_written_by_flag_write_type = {}
+ self.__dict__["flags_written_by_flag_write_type"] = {}
+ for write_type in self.flag_write_types:
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle,
+ self._flag_write_types[write_type], count)
+ flag_indexes = []
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_indexes.append(flags[i])
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes
+ self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names
+
+ self._semantic_class_for_flag_write_type = {}
+ self.__dict__["semantic_class_for_flag_write_type"] = {}
+ for write_type in self.flag_write_types:
+ sem_class = core.BNGetArchitectureSemanticClassForFlagWriteType(self.handle,
+ self._flag_write_types[write_type])
+ if sem_class == 0:
+ sem_class_name = None
+ else:
+ sem_class_name = self._semantic_flag_classes_by_index[sem_class]
+ self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class
+ self.__dict__["semantic_class_for_flag_write_type"][write_type] = sem_class_name
+
+ count = ctypes.c_ulonglong()
+ regs = core.BNGetArchitectureGlobalRegisters(self.handle, count)
+ self.__dict__["global_regs"] = []
+ 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._all_reg_stacks = {}
+ self._reg_stacks_by_index = {}
+ 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])
+ self._all_reg_stacks[name] = regs[i]
+ self._reg_stacks_by_index[regs[i]] = name
+ core.BNFreeRegisterList(regs)
+
+ count = ctypes.c_ulonglong()
+ intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count)
+ self._intrinsics = {}
+ self._intrinsics_by_index = {}
+ self.__dict__["intrinsics"] = {}
+ for i in xrange(0, count.value):
+ name = core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i])
+ input_count = ctypes.c_ulonglong()
+ inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count)
+ input_list = []
+ for j in xrange(0, input_count.value):
+ input_name = inputs[j].name
+ type_obj = types.Type(core.BNNewTypeReference(inputs[j].type), confidence = inputs[j].typeConfidence)
+ input_list.append(function.IntrinsicInput(type_obj, input_name))
+ core.BNFreeNameAndTypeList(inputs, input_count.value)
+ output_count = ctypes.c_ulonglong()
+ outputs = core.BNGetArchitectureIntrinsicOutputs(self.handle, intrinsics[i], output_count)
+ output_list = []
+ for j in xrange(0, output_count.value):
+ output_list.append(types.Type(core.BNNewTypeReference(outputs[j].type), confidence = outputs[j].confidence))
+ core.BNFreeOutputTypeList(outputs, output_count.value)
+ self.intrinsics[name] = function.IntrinsicInfo(input_list, output_list)
+ self._intrinsics[name] = intrinsics[i]
+ self._intrinsics_by_index[intrinsics[i]] = (name, self.intrinsics[name])
+ core.BNFreeRegisterList(intrinsics)
+ global _architecture_cache
+ _architecture_cache[ctypes.addressof(handle.contents)] = self
+
+ @classmethod
+ def _from_cache(cls, handle):
+ global _architecture_cache
+ return _architecture_cache.get(ctypes.addressof(handle.contents)) or cls(handle)
+
+ def get_associated_arch_by_address(self, addr):
+ new_addr = ctypes.c_ulonglong()
+ new_addr.value = addr
+ result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr)
+ return CoreArchitecture._from_cache(handle = result), new_addr.value
+
+ def get_instruction_info(self, data, addr):
+ """
+ ``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address
+ ``addr`` with data ``data``.
+
+ .. note :: The instruction info object should always set the InstructionInfo.length to the instruction length, \
+ and the branches of the proper types shoulde be added if the instruction is a branch.
+
+ :param str data: max_instruction_length bytes from the binary at virtual address ``addr``
+ :param int addr: virtual address of bytes in ``data``
+ :return: the InstructionInfo for the current instruction
+ :rtype: InstructionInfo
+ """
+ info = core.BNInstructionInfo()
+ data = str(data)
+ buf = (ctypes.c_ubyte * len(data))()
+ ctypes.memmove(buf, data, len(data))
+ if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info):
+ return None
+ result = function.InstructionInfo()
+ result.length = info.length
+ result.arch_transition_by_target_addr = info.archTransitionByTargetAddr
+ result.branch_delay = info.branchDelay
+ for i in xrange(0, info.branchCount):
+ target = info.branchTarget[i]
+ if info.branchArch[i]:
+ arch = CoreArchitecture._from_cache(info.branchArch[i])
+ else:
+ arch = None
+ result.add_branch(BranchType(info.branchType[i]), target, arch)
+ return result
+
+ def get_instruction_text(self, data, addr):
+ """
+ ``get_instruction_text`` returns a list of InstructionTextToken objects for the instruction at the given virtual
+ address ``addr`` with data ``data``.
+
+ :param str data: max_instruction_length bytes from the binary at virtual address ``addr``
+ :param int addr: virtual address of bytes in ``data``
+ :return: an InstructionTextToken list for the current instruction
+ :rtype: list(InstructionTextToken)
+ """
+ data = str(data)
+ count = ctypes.c_ulonglong()
+ length = ctypes.c_ulonglong()
+ length.value = len(data)
+ buf = (ctypes.c_ubyte * len(data))()
+ ctypes.memmove(buf, data, len(data))
+ tokens = ctypes.POINTER(core.BNInstructionTextToken)()
+ if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count):
+ return None, 0
+ result = []
+ for i in xrange(0, count.value):
+ token_type = InstructionTextTokenType(tokens[i].type)
+ text = tokens[i].text
+ value = tokens[i].value
+ size = tokens[i].size
+ operand = tokens[i].operand
+ context = tokens[i].context
+ confidence = tokens[i].confidence
+ address = tokens[i].address
+ result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
+ core.BNFreeInstructionText(tokens, count.value)
+ return result, length.value
+
+ def get_instruction_low_level_il(self, data, addr, il):
+ """
+ ``get_instruction_low_level_il`` appends LowLevelILExpr objects to ``il`` for the instruction at the given
+ virtual address ``addr`` with data ``data``.
+
+ This is used to analyze arbitrary data at an address, if you are working with an existing binary, you likely
+ want to be using ``Function.get_low_level_il_at``.
+
+ :param str data: max_instruction_length bytes from the binary at virtual address ``addr``
+ :param int addr: virtual address of bytes in ``data``
+ :param LowLevelILFunction il: The function the current instruction belongs to
+ :return: the length of the current instruction
+ :rtype: int
+ """
+ data = str(data)
+ length = ctypes.c_ulonglong()
+ length.value = len(data)
+ buf = (ctypes.c_ubyte * len(data))()
+ ctypes.memmove(buf, data, len(data))
+ core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle)
+ return length.value
+
+ def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
+ """
+ :param LowLevelILOperation op:
+ :param int size:
+ :param str write_type:
+ :param list(str or int) operands: a list of either items that are either string register names or constant \
+ integer values
+ :param LowLevelILFunction il:
+ :rtype: LowLevelILExpr
+ """
+ flag = self.get_flag_index(flag)
+ operand_list = (core.BNRegisterOrConstant * len(operands))()
+ for i in xrange(len(operands)):
+ if isinstance(operands[i], str):
+ operand_list[i].constant = False
+ operand_list[i].reg = self.regs[operands[i]].index
+ elif isinstance(operands[i], lowlevelil.ILRegister):
+ operand_list[i].constant = False
+ operand_list[i].reg = operands[i].index
+ else:
+ operand_list[i].constant = True
+ operand_list[i].value = operands[i]
+ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size,
+ self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle))
+
+ def get_flag_condition_low_level_il(self, cond, sem_class, il):
+ """
+ :param LowLevelILFlagCondition cond: Flag condition to be computed
+ :param str sem_class: Semantic class to be used (None for default semantics)
+ :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to
+ :rtype: LowLevelILExpr
+ """
+ class_index = self.get_semantic_flag_class_index(sem_class)
+ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond,
+ class_index, il.handle))
+
+ def get_semantic_flag_group_low_level_il(self, sem_group, il):
+ """
+ :param str sem_group:
+ :param LowLevelILFunction il:
+ :rtype: LowLevelILExpr
+ """
+ group_index = self.get_semantic_flag_group_index(sem_group)
+ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group_index, il.handle))
+
+ def assemble(self, code, addr=0):
+ """
+ ``assemble`` converts the string of assembly instructions ``code`` loaded at virtual address ``addr`` to the
+ byte representation of those instructions.
+
:param str code: string representation of the instructions to be assembled
:param int addr: virtual address that the instructions will be loaded at
:return: the bytes for the assembled instructions or error string
@@ -1511,7 +2514,7 @@ class Architecture(object):
def is_skip_and_return_value_patch_available(self, data, addr):
"""
- ``is_skip_and_return_zero_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like*
+ ``is_skip_and_return_value_patch_available`` determines if the instruction ``data`` at ``addr`` is a *call-like*
instruction that can be made into an instruction *returns a value*.
:param str data: bytes for the instruction to be checked
@@ -1520,9 +2523,9 @@ class Architecture(object):
:rtype: bool
:Example:
- >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("call 0")[0], 0)
+ >>> arch.is_skip_and_return_value_patch_available(arch.assemble("call 0")[0], 0)
True
- >>> arch.is_skip_and_return_zero_patch_available(arch.assemble("jmp eax")[0], 0)
+ >>> arch.is_skip_and_return_value_patch_available(arch.assemble("jmp eax")[0], 0)
False
>>>
"""
@@ -1634,67 +2637,62 @@ class Architecture(object):
ctypes.memmove(result, buf, len(data))
return result.raw
- def is_view_type_constant_defined(self, type_name, const_name):
- """
-
- :param str type_name: the BinaryView type name of the constant to query
- :param str const_name: the constant name to query
- :rtype: None
- :Example:
-
- >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
- >>> arch.is_view_type_constant_defined("ELF", "R_COPY")
- True
- >>> arch.is_view_type_constant_defined("ELF", "NOT_THERE")
- False
- >>>
+ def get_flag_role(self, flag, sem_class = None):
"""
- return core.BNIsBinaryViewTypeArchitectureConstantDefined(self.handle, type_name, const_name)
+ ``get_flag_role`` gets the role of a given flag.
- def get_view_type_constant(self, type_name, const_name, default_value=0):
+ :param int flag: flag
+ :param int sem_class: optional semantic flag class
+ :return: flag role
+ :rtype: FlagRole
"""
- ``get_view_type_constant`` retrieves the view type constant for the given type_name and const_name.
-
- :param str type_name: the BinaryView type name of the constant to be retrieved
- :param str const_name: the constant name to retrieved
- :param int value: optional default value if the type_name is not present. default value is zero.
- :return: The BinaryView type constant or the default_value if not found
- :rtype: int
- :Example:
-
- >>> ELF_RELOC_COPY = 5
- >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
- >>> arch.get_view_type_constant("ELF", "R_COPY")
- 5L
- >>> arch.get_view_type_constant("ELF", "NOT_HERE", 100)
- 100L
- """
- return core.BNGetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, default_value)
+ flag = self.get_flag_index(flag)
+ sem_class = self.get_semantic_flag_class_index(sem_class)
+ return FlagRole(core.BNGetArchitectureFlagRole(self.handle, flag, sem_class))
- def set_view_type_constant(self, type_name, const_name, value):
- """
- ``set_view_type_constant`` creates a new binaryview type constant.
+ def get_flags_required_for_flag_condition(self, cond, sem_class = None):
+ sem_class = self.get_semantic_flag_class_index(sem_class)
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, sem_class, count)
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ return flag_names
- :param str type_name: the BinaryView type name of the constant to be registered
- :param str const_name: the constant name to register
- :param int value: the value of the constant
- :rtype: None
- :Example:
- >>> ELF_RELOC_COPY = 5
- >>> arch.set_view_type_constant("ELF", "R_COPY", ELF_RELOC_COPY)
- >>>
- """
- core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value)
+class ArchitectureHook(CoreArchitecture):
+ def __init__(self, base_arch):
+ self.base_arch = base_arch
+ super(ArchitectureHook, self).__init__(base_arch.handle)
- def register_calling_convention(self, cc):
- """
- ``register_calling_convention`` registers a new calling convention for the Architecture.
+ # To improve performance of simpler hooks, use null callback for functions that are not being overridden
+ if self.get_associated_arch_by_address.__code__ == CoreArchitecture.get_associated_arch_by_address.__code__:
+ self._cb.getAssociatedArchitectureByAddress = self._cb.getAssociatedArchitectureByAddress.__class__()
+ if self.get_instruction_info.__code__ == CoreArchitecture.get_instruction_info.__code__:
+ self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__()
+ if self.get_instruction_text.__code__ == CoreArchitecture.get_instruction_text.__code__:
+ self._cb.getInstructionText = self._cb.getInstructionText.__class__()
+ if self.__class__.stack_pointer is None:
+ self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__()
+ if self.__class__.link_reg is None:
+ self._cb.getLinkRegister = self._cb.getLinkRegister.__class__()
+ if len(self.__class__.regs) == 0:
+ self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__()
+ self._cb.getRegisterName = self._cb.getRegisterName.__class__()
+ if len(self.__class__.reg_stacks) == 0:
+ self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__()
+ self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__()
+ if len(self.__class__.intrinsics) == 0:
+ self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__()
+ self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__()
+ self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__()
+ self._cb.getIntrinsicOutputs = self._cb.getIntrinsicOutputs.__class__()
+ self._cb.freeTypeList = self._cb.freeTypeList.__class__()
- :param CallingConvention cc: CallingConvention object to be registered
- :rtype: None
- """
- core.BNRegisterCallingConvention(self.handle, cc.handle)
+ def register(self):
+ self.__class__._registered_cb = self._cb
+ self.handle = core.BNRegisterArchitectureHook(self.base_arch.handle, self._cb)
class ReferenceSource(object):
diff --git a/python/basicblock.py b/python/basicblock.py
index 8e64c1c1..4dc783c3 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -100,7 +100,7 @@ class BasicBlock(object):
arch = core.BNGetBasicBlockArchitecture(self.handle)
if arch is None:
return None
- self._arch = architecture.Architecture(arch)
+ self._arch = architecture.CoreArchitecture._from_cache(arch)
return self._arch
@property
@@ -256,6 +256,21 @@ class BasicBlock(object):
def highlight(self, value):
self.set_user_highlight(value)
+ @property
+ def is_il(self):
+ """Whether the basic block contains IL"""
+ return core.BNIsILBasicBlock(self.handle)
+
+ @property
+ def is_low_level_il(self):
+ """Whether the basic block contains Low Level IL"""
+ return core.BNIsLowLevelILBasicBlock(self.handle)
+
+ @property
+ def is_medium_level_il(self):
+ """Whether the basic block contains Medium Level IL"""
+ return core.BNIsMediumLevelILBasicBlock(self.handle)
+
@classmethod
def get_iterated_dominance_frontier(self, blocks):
if len(blocks) == 0:
@@ -322,6 +337,10 @@ class BasicBlock(object):
result = []
for i in xrange(0, count.value):
addr = lines[i].addr
+ if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(self, 'il_function'):
+ il_instr = self.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)
@@ -333,7 +352,7 @@ class BasicBlock(object):
confidence = lines[i].tokens[j].confidence
address = lines[i].tokens[j].address
tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
- result.append(function.DisassemblyTextLine(addr, tokens))
+ result.append(function.DisassemblyTextLine(addr, tokens, il_instr))
core.BNFreeDisassemblyTextLines(lines, count.value)
return result
diff --git a/python/binaryview.py b/python/binaryview.py
index 19bff9e5..0b090a9a 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -65,6 +65,9 @@ class BinaryDataNotification(object):
def function_updated(self, view, func):
pass
+ def function_update_requested(self, view, func):
+ pass
+
def data_var_added(self, view, var):
pass
@@ -105,7 +108,8 @@ class StringReference(object):
class AnalysisCompletionEvent(object):
"""
The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving
- callbacks when analysis is complete.
+ callbacks when analysis is complete. The callback runs once. A completion event must be added
+ for each new analysis in order to be notified of each analysis completion.
:Example:
>>> def on_complete(self):
@@ -180,6 +184,7 @@ class BinaryDataNotificationCallbacks(object):
self._cb.functionAdded = self._cb.functionAdded.__class__(self._function_added)
self._cb.functionRemoved = self._cb.functionRemoved.__class__(self._function_removed)
self._cb.functionUpdated = self._cb.functionUpdated.__class__(self._function_updated)
+ self._cb.functionUpdateRequested = self._cb.functionUpdateRequested.__class__(self._function_update_requested)
self._cb.dataVariableAdded = self._cb.dataVariableAdded.__class__(self._data_var_added)
self._cb.dataVariableRemoved = self._cb.dataVariableRemoved.__class__(self._data_var_removed)
self._cb.dataVariableUpdated = self._cb.dataVariableUpdated.__class__(self._data_var_updated)
@@ -230,6 +235,12 @@ class BinaryDataNotificationCallbacks(object):
except:
log.log_error(traceback.format_exc())
+ def _function_update_requested(self, ctxt, view, func):
+ try:
+ self.notify.function_update_requested(self.view, function.Function(self.view, core.BNNewFunctionReference(func)))
+ except:
+ log.log_error(traceback.format_exc())
+
def _data_var_added(self, ctxt, view, var):
try:
address = var[0].address
@@ -400,7 +411,7 @@ class BinaryViewType(object):
arch = core.BNGetArchitectureForViewType(self.handle, ident, endian)
if arch is None:
return None
- return architecture.Architecture(arch)
+ return architecture.CoreArchitecture._from_cache(arch)
def register_platform(self, ident, arch, plat):
core.BNRegisterPlatformForViewType(self.handle, ident, arch.handle, plat.handle)
@@ -857,7 +868,7 @@ class BinaryView(object):
arch = core.BNGetDefaultArchitecture(self.handle)
if arch is None:
return None
- return architecture.Architecture(handle=arch)
+ return architecture.CoreArchitecture._from_cache(handle=arch)
@arch.setter
def arch(self, value):
@@ -1054,6 +1065,15 @@ class BinaryView(object):
result = core.BNGetGlobalPointerValue(self.handle)
return function.RegisterValue(self.arch, result.value, confidence = result.confidence)
+ @property
+ def max_function_size_for_analysis(self):
+ """Maximum size of function (sum of basic block sizes in bytes) for auto analysis"""
+ return core.BNGetMaxFunctionSizeForAnalysis(self.handle)
+
+ @max_function_size_for_analysis.setter
+ def max_function_size_for_analysis(self, size):
+ core.BNSetMaxFunctionSizeForAnalysis(self.handle, size)
+
def __len__(self):
return int(core.BNGetViewLength(self.handle))
@@ -2146,6 +2166,8 @@ class BinaryView(object):
"""
if plat is None:
plat = self.platform
+ if plat is None:
+ return None
func = core.BNGetAnalysisFunction(self.handle, plat.handle, addr)
if func is None:
return None
@@ -2240,7 +2262,7 @@ class BinaryView(object):
else:
func = None
if refs[i].arch:
- arch = architecture.Architecture(refs[i].arch)
+ arch = architecture.CoreArchitecture._from_cache(refs[i].arch)
else:
arch = None
addr = refs[i].addr
diff --git a/python/callingconvention.py b/python/callingconvention.py
index e72475c9..e3ec7261 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,11 +69,13 @@ 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:
self.handle = handle
- self.arch = architecture.Architecture(core.BNGetCallingConventionArchitecture(self.handle))
+ self.arch = architecture.CoreArchitecture._from_cache(core.BNGetCallingConventionArchitecture(self.handle))
self.__dict__["name"] = core.BNGetCallingConventionName(self.handle)
self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle)
self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle)
@@ -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/examples/arch_hook.py b/python/examples/arch_hook.py
new file mode 100644
index 00000000..452bd2b6
--- /dev/null
+++ b/python/examples/arch_hook.py
@@ -0,0 +1,16 @@
+from binaryninja.architecture import Architecture, ArchitectureHook
+
+class X86ReturnHook(ArchitectureHook):
+ def get_instruction_text(self, data, addr):
+ # Call the original implementation's method by calling the superclass
+ result, length = super(X86ReturnHook, self).get_instruction_text(data, addr)
+
+ # Patch the name of the 'retn' instruction to 'ret'
+ if len(result) > 0 and result[0].text == 'retn':
+ result[0].text = 'ret'
+
+ return result, length
+
+# Install the hook by constructing it with the desired architecture to hook, then registering it
+X86ReturnHook(Architecture['x86']).register()
+
diff --git a/python/examples/nes.py b/python/examples/nes.py
index 39544c9f..00451abd 100644
--- a/python/examples/nes.py
+++ b/python/examples/nes.py
@@ -423,7 +423,7 @@ class M6502(Architecture):
return instr, operand, length, value
- def perform_get_instruction_info(self, data, addr):
+ def get_instruction_info(self, data, addr):
instr, operand, length, value = self.decode_instruction(data, addr)
if instr is None:
return None
@@ -445,7 +445,7 @@ class M6502(Architecture):
result.add_branch(BranchType.FalseBranch, addr + 2)
return result
- def perform_get_instruction_text(self, data, addr):
+ def get_instruction_text(self, data, addr):
instr, operand, length, value = self.decode_instruction(data, addr)
if instr is None:
return None
@@ -455,7 +455,7 @@ class M6502(Architecture):
tokens += OperandTokens[operand](value)
return tokens, length
- def perform_get_instruction_low_level_il(self, data, addr, il):
+ def get_instruction_low_level_il(self, data, addr, il):
instr, operand, length, value = self.decode_instruction(data, addr)
if instr is None:
return None
@@ -470,48 +470,48 @@ class M6502(Architecture):
return length
- def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
+ def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il):
if flag == 'c':
if (op == LowLevelILOperation.LLIL_SUB) or (op == LowLevelILOperation.LLIL_SBB):
# Subtraction carry flag is inverted from the commom implementation
return il.not_expr(0, self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il))
# Other operations use a normal carry flag
return self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il)
- return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il)
+ return Architecture.get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il)
- def perform_is_never_branch_patch_available(self, data, addr):
+ def is_never_branch_patch_available(self, data, addr):
if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"):
return True
return False
- def perform_is_invert_branch_patch_available(self, data, addr):
+ def is_invert_branch_patch_available(self, data, addr):
if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"):
return True
return False
- def perform_is_always_branch_patch_available(self, data, addr):
+ def is_always_branch_patch_available(self, data, addr):
return False
- def perform_is_skip_and_return_zero_patch_available(self, data, addr):
+ def is_skip_and_return_zero_patch_available(self, data, addr):
return (data[0] == "\x20") and (len(data) == 3)
- def perform_is_skip_and_return_value_patch_available(self, data, addr):
+ def is_skip_and_return_value_patch_available(self, data, addr):
return (data[0] == "\x20") and (len(data) == 3)
- def perform_convert_to_nop(self, data, addr):
+ def convert_to_nop(self, data, addr):
return "\xea" * len(data)
- def perform_never_branch(self, data, addr):
+ def never_branch(self, data, addr):
if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"):
return "\xea" * len(data)
return None
- def perform_invert_branch(self, data, addr):
+ def invert_branch(self, data, addr):
if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"):
return chr(ord(data[0]) ^ 0x20) + data[1:]
return None
- def perform_skip_and_return_value(self, data, addr, value):
+ def skip_and_return_value(self, data, addr, value):
if (data[0] != "\x20") or (len(data) != 3):
return None
return "\xa9" + chr(value & 0xff) + "\xea"
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
diff --git a/python/interaction.py b/python/interaction.py
index 96cac42d..4f6ed67d 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -121,7 +121,7 @@ class IntegerField(object):
class AddressField(object):
"""
``AddressField`` prompts the user for an address. By passing the optional view and current_address parameters
- offsets can be used instead of just an address. Th reslut is stored as in int in self.result.
+ offsets can be used instead of just an address. The result is stored as in int in self.result.
Note: This API currenlty functions differently on the command line, as the view and current_address are
disregarded. Additionally where as in the ui the result defaults to hexidecimal on the command line 0x must be
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index dfc5af5f..ab6170a5 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
@@ -78,6 +99,57 @@ class ILFlag(object):
return self.name
+class ILSemanticFlagClass(object):
+ def __init__(self, arch, sem_class):
+ self.arch = arch
+ self.index = sem_class
+ self.name = self.arch.get_semantic_flag_class_name(self.index)
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.index == other.index
+
+
+class ILSemanticFlagGroup(object):
+ def __init__(self, arch, sem_group):
+ self.arch = arch
+ self.index = sem_group
+ self.name = self.arch.get_semantic_flag_group_name(self.index)
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.index == other.index
+
+
+class ILIntrinsic(object):
+ def __init__(self, arch, intrinsic):
+ self.arch = arch
+ self.index = intrinsic
+ self.name = self.arch.get_intrinsic_name(self.index)
+ if self.name in self.arch.intrinsics:
+ self.inputs = self.arch.intrinsics[self.name].inputs
+ self.outputs = self.arch.intrinsics[self.name].outputs
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return self.name
+
+ def __eq__(self, other):
+ return self.index == other.index
+
+
class SSARegister(object):
def __init__(self, reg, version):
self.reg = reg
@@ -87,6 +159,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
@@ -96,6 +177,15 @@ class SSAFlag(object):
return "<ssa %s version %d>" % (repr(self.flag), self.version)
+class SSARegisterOrFlag(object):
+ def __init__(self, reg_or_flag, version):
+ self.reg_or_flag = reg_or_flag
+ self.version = version
+
+ def __repr__(self):
+ return "<ssa %s version %d>" % (repr(self.reg_or_flag), self.version)
+
+
class LowLevelILOperationAndSize(object):
def __init__(self, operation, size):
self.operation = operation
@@ -118,14 +208,22 @@ 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_REG_STACK_FREE_REG: [("dest", "reg")],
+ LowLevelILOperation.LLIL_REG_STACK_FREE_REL: [("stack", "reg_stack"), ("dest", "expr")],
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 +244,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,12 +259,13 @@ 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")],
LowLevelILOperation.LLIL_GOTO: [("dest", "int")],
- LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond")],
+ LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond"), ("semantic_class", "sem_class")],
+ LowLevelILOperation.LLIL_FLAG_GROUP: [("semantic_group", "sem_group")],
LowLevelILOperation.LLIL_CMP_E: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_CMP_NE: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_CMP_SLT: [("left", "expr"), ("right", "expr")],
@@ -181,17 +280,49 @@ class LowLevelILInstruction(object):
LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")],
LowLevelILOperation.LLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_SYSCALL: [],
+ LowLevelILOperation.LLIL_INTRINSIC: [("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")],
+ LowLevelILOperation.LLIL_INTRINSIC_SSA: [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")],
LowLevelILOperation.LLIL_BP: [],
LowLevelILOperation.LLIL_TRAP: [("vector", "int")],
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_ROUND_TO_INT: [("src", "expr")],
+ LowLevelILOperation.LLIL_FLOOR: [("src", "expr")],
+ LowLevelILOperation.LLIL_CEIL: [("src", "expr")],
+ LowLevelILOperation.LLIL_FTRUNC: [("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_O: [("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_REG_STACK_FREE_REL_SSA: [("stack", "expr"), ("dest", "expr"), ("top", "expr")],
+ LowLevelILOperation.LLIL_REG_STACK_FREE_ABS_SSA: [("stack", "expr"), ("dest", "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 +330,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: [("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,20 +361,50 @@ 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 == "intrinsic":
+ value = ILIntrinsic(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":
flag = ILFlag(func.arch, instr.operands[i])
i += 1
value = SSAFlag(flag, instr.operands[i])
+ elif operand_type == "sem_class":
+ if instr.operands[i] == 0:
+ value = None
+ else:
+ value = ILSemanticFlagClass(func.arch, instr.operands[i])
+ elif operand_type == "sem_group":
+ value = ILSemanticFlagGroup(func.arch, instr.operands[i])
elif operand_type == "cond":
value = LowLevelILFlagCondition(instr.operands[i])
elif operand_type == "int_list":
@@ -250,29 +412,83 @@ class LowLevelILInstruction(object):
operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
i += 1
value = []
- for i in xrange(count.value):
- value.append(operand_list[i])
+ for j in xrange(count.value):
+ value.append(operand_list[j])
+ 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 j in xrange(count.value):
+ value.append(LowLevelILInstruction(func, operand_list[j]))
+ core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_or_flag_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for j in xrange(count.value):
+ if (operand_list[j] & (1 << 32)) != 0:
+ value.append(ILFlag(func.arch, operand_list[j] & 0xffffffff))
+ else:
+ value.append(ILRegister(func.arch, operand_list[j] & 0xffffffff))
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)
i += 1
value = []
- for i in xrange(count.value / 2):
- reg = operand_list[i * 2]
- reg_version = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ reg = operand_list[j * 2]
+ reg_version = operand_list[(j * 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 j in xrange(count.value / 2):
+ reg_stack = operand_list[j * 2]
+ reg_version = operand_list[(j * 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)
i += 1
value = []
- for i in xrange(count.value / 2):
- flag = operand_list[i * 2]
- flag_version = operand_list[(i * 2) + 1]
+ for j in xrange(count.value / 2):
+ flag = operand_list[j * 2]
+ flag_version = operand_list[(j * 2) + 1]
value.append(SSAFlag(ILFlag(func.arch, flag), flag_version))
core.BNLowLevelILFreeOperandList(operand_list)
+ elif operand_type == "reg_or_flag_ssa_list":
+ count = ctypes.c_ulonglong()
+ operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count)
+ i += 1
+ value = []
+ for j in xrange(count.value / 2):
+ if (operand_list[j * 2] & (1 << 32)) != 0:
+ reg_or_flag = ILFlag(func.arch, operand_list[j * 2] & 0xffffffff)
+ else:
+ reg_or_flag = ILRegister(func.arch, operand_list[j * 2] & 0xffffffff)
+ reg_version = operand_list[(j * 2) + 1]
+ value.append(SSARegisterOrFlag(reg_or_flag, reg_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 j in xrange(count.value / 2):
+ reg_stack = operand_list[j * 2]
+ adjust = operand_list[(j * 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 +926,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``
@@ -723,7 +971,7 @@ class LowLevelILFunction(object):
def load(self, size, addr):
"""
- ``laod`` Reads ``size`` bytes from the expression ``addr``
+ ``load`` Reads ``size`` bytes from the expression ``addr``
:param int size: number of bytes to read
:param LowLevelILExpr addr: the expression to read memory from
@@ -768,7 +1016,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 +1026,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 +1089,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.
@@ -1059,7 +1380,7 @@ class LowLevelILFunction(object):
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``muls.dp.<size>{<flags>}(a, b)``
+ :return: The expression ``mulu.dp.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
return self.expr(LowLevelILOperation.LLIL_MULU_DP, a.index, b.index, size=size, flags=flags)
@@ -1078,21 +1399,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):
"""
@@ -1103,26 +1423,25 @@ class LowLevelILFunction(object):
:param LowLevelILExpr a: LHS expression
:param LowLevelILExpr b: RHS expression
:param str flags: optional, flags to set
- :return: The expression ``divs.<size>{<flags>}(a, b)``
+ :return: The expression ``divu.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_DIVU, 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 ``divu.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_DIVU_DP, a.index, b.index, size=size, flags=flags)
def mod_signed(self, size, a, b, flags=None):
"""
@@ -1138,21 +1457,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):
"""
@@ -1166,23 +1484,22 @@ class LowLevelILFunction(object):
:return: The expression ``modu.<size>{<flags>}(a, b)``
:rtype: LowLevelILExpr
"""
- return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags)
+ return self.expr(LowLevelILOperation.LLIL_MODU, 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_MODU_DP, a.index, b.index, size=size, flags=flags)
def neg_expr(self, size, value, flags=None):
"""
@@ -1226,7 +1543,7 @@ class LowLevelILFunction(object):
:param int size: the size of the result in bytes
:param LowLevelILExpr value: the expression to zero extend
- :return: The expression ``sx.<size>(value)``
+ :return: The expression ``zx.<size>(value)``
:rtype: LowLevelILExpr
"""
return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags)
@@ -1295,11 +1612,12 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_NORET)
- def flag_condition(self, cond):
+ def flag_condition(self, cond, sem_class = None):
"""
``flag_condition`` returns a flag_condition expression for the given LowLevelILFlagCondition
:param LowLevelILFlagCondition cond: Flag condition expression to retrieve
+ :param str sem_class: Optional semantic flag class
:return: A flag_condition expression
:rtype: LowLevelILExpr
"""
@@ -1307,7 +1625,19 @@ class LowLevelILFunction(object):
cond = LowLevelILFlagCondition[cond]
elif isinstance(cond, LowLevelILFlagCondition):
cond = cond.value
- return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond)
+ class_index = self.arch.get_semantic_flag_class_index(sem_class)
+ return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond, class_index)
+
+ def flag_group(self, sem_group):
+ """
+ ``flag_group`` returns a flag_group expression for the given semantic flag group
+
+ :param str sem_group: Semantic flag group to access
+ :return: A flag_group expression
+ :rtype: LowLevelILExpr
+ """
+ group = self.arch.get_semantic_flag_group_index(sem_group)
+ return self.expr(LowLevelILOperation.LLIL_FLAG_GROUP, group)
def compare_equal(self, size, a, b):
"""
@@ -1451,6 +1781,25 @@ class LowLevelILFunction(object):
"""
return self.expr(LowLevelILOperation.LLIL_SYSCALL)
+ def intrinsic(self, outputs, intrinsic, params, flags=None):
+ """
+ ``intrinsic`` return an intrinsic expression.
+
+ :return: an intrinsic expression.
+ :rtype: LowLevelILExpr
+ """
+ output_list = []
+ for output in outputs:
+ if isinstance(output, ILFlag):
+ output_list.append((1 << 32) | output.index)
+ else:
+ output_list.append(output.index)
+ param_list = []
+ for param in params:
+ param_list.append(param.index)
+ return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list),
+ self.arch.get_intrinsic_index(intrinsic), len(params), self.add_operand_list(param_list), flags = flags)
+
def breakpoint(self):
"""
``breakpoint`` returns a processor breakpoint expression.
@@ -1501,6 +1850,280 @@ 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 round_to_int(self, size, value, flags=None):
+ """
+ ``round_to_int`` rounds a floating point value to the nearest integer
+
+ :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 ``roundint.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_ROUND_TO_INT, value.index, size=size, flags=flags)
+
+ def floor(self, size, value, flags=None):
+ """
+ ``floor`` rounds a floating point value to an integer towards negative infinity
+
+ :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 ``roundint.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FLOOR, value.index, size=size, flags=flags)
+
+ def ceil(self, size, value, flags=None):
+ """
+ ``ceil`` rounds a floating point value to an integer towards positive infinity
+
+ :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 ``roundint.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_CEIL, value.index, size=size, flags=flags)
+
+ def float_trunc(self, size, value, flags=None):
+ """
+ ``float_trunc`` rounds a floating point value to an integer towards zero
+
+ :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 ``roundint.<size>{<flags>}(value)``
+ :rtype: LowLevelILExpr
+ """
+ return self.expr(LowLevelILOperation.LLIL_FTRUNC, 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.
@@ -1736,6 +2359,7 @@ class LowLevelILBasicBlock(basicblock.BasicBlock):
def __hash__(self):
return hash((self.start, self.end, self.il_function))
+
def LLIL_TEMP(n):
return n | 0x80000000
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 6f5515bb..caf19e8e 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")],
@@ -147,9 +150,35 @@ class MediumLevelILInstruction(object):
MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")],
MediumLevelILOperation.MLIL_BP: [],
MediumLevelILOperation.MLIL_TRAP: [("vector", "int")],
+ MediumLevelILOperation.MLIL_INTRINSIC: [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_INTRINSIC_SSA: [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_FREE_VAR_SLOT: [("dest", "var")],
+ MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA: [("prev", "var_ssa_dest_and_src")],
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_ROUND_TO_INT: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FLOOR: [("src", "expr")],
+ MediumLevelILOperation.MLIL_CEIL: [("src", "expr")],
+ MediumLevelILOperation.MLIL_FTRUNC: [("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_O: [("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 +188,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,8 +222,17 @@ 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 == "intrinsic":
+ value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i])
elif operand_type == "var":
value = function.Variable.from_identifier(self.function.source_function, instr.operands[i])
elif operand_type == "var_ssa":
diff --git a/python/platform.py b/python/platform.py
index 5e63d836..a79e3b9a 100644
--- a/python/platform.py
+++ b/python/platform.py
@@ -105,7 +105,7 @@ class Platform(object):
else:
self.handle = handle
self.__dict__["name"] = core.BNGetPlatformName(self.handle)
- self.arch = architecture.Architecture(core.BNGetPlatformArchitecture(self.handle))
+ self.arch = architecture.CoreArchitecture._from_cache(core.BNGetPlatformArchitecture(self.handle))
def __del__(self):
core.BNFreePlatform(self.handle)
diff --git a/python/plugin.py b/python/plugin.py
index e0054d86..c6cd9fc0 100644
--- a/python/plugin.py
+++ b/python/plugin.py
@@ -30,6 +30,8 @@ import filemetadata
import binaryview
import function
import log
+import lowlevelil
+import mediumlevelil
class PluginCommandContext(object):
@@ -38,6 +40,7 @@ class PluginCommandContext(object):
self.address = 0
self.length = 0
self.function = None
+ self.instruction = None
class _PluginCommandMetaClass(type):
@@ -118,6 +121,50 @@ class PluginCommand(object):
log.log_error(traceback.format_exc())
@classmethod
+ def _low_level_il_function_action(cls, view, func, action):
+ try:
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func))
+ func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
+ action(view_obj, func_obj)
+ except:
+ log.log_error(traceback.format_exc())
+
+ @classmethod
+ def _low_level_il_instruction_action(cls, view, func, instr, action):
+ try:
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func))
+ func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
+ action(view_obj, func_obj[instr])
+ except:
+ log.log_error(traceback.format_exc())
+
+ @classmethod
+ def _medium_level_il_function_action(cls, view, func, action):
+ try:
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func))
+ func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner)
+ action(view_obj, func_obj)
+ except:
+ log.log_error(traceback.format_exc())
+
+ @classmethod
+ def _medium_level_il_instruction_action(cls, view, func, instr, action):
+ try:
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func))
+ func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner)
+ action(view_obj, func_obj[instr])
+ except:
+ log.log_error(traceback.format_exc())
+
+ @classmethod
def _default_is_valid(cls, view, is_valid):
try:
if is_valid is None:
@@ -167,6 +214,62 @@ class PluginCommand(object):
return False
@classmethod
+ def _low_level_il_function_is_valid(cls, view, func, is_valid):
+ try:
+ if is_valid is None:
+ return True
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func))
+ func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
+ return is_valid(view_obj, func_obj)
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ @classmethod
+ def _low_level_il_instruction_is_valid(cls, view, func, instr, is_valid):
+ try:
+ if is_valid is None:
+ return True
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func))
+ func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner)
+ return is_valid(view_obj, func_obj[instr])
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ @classmethod
+ def _medium_level_il_function_is_valid(cls, view, func, is_valid):
+ try:
+ if is_valid is None:
+ return True
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func))
+ func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner)
+ return is_valid(view_obj, func_obj)
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ @classmethod
+ def _medium_level_il_instruction_is_valid(cls, view, func, instr, is_valid):
+ try:
+ if is_valid is None:
+ return True
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view))
+ view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
+ owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func))
+ func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner)
+ return is_valid(view_obj, func_obj[instr])
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ @classmethod
def register(cls, name, description, action, is_valid = None):
"""
``register`` Register a plugin
@@ -243,6 +346,82 @@ class PluginCommand(object):
core.BNRegisterPluginCommandForFunction(name, description, action_obj, is_valid_obj, None)
@classmethod
+ def register_for_low_level_il_function(cls, name, description, action, is_valid = None):
+ """
+ ``register_for_low_level_il_function`` Register a plugin to be called with a low level IL function argument
+
+ :param str name: name of the plugin
+ :param str description: description of the plugin
+ :param action: function to call with the ``BinaryView`` and a ``LowLevelILFunction`` as arguments
+ :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
+ :rtype: None
+
+ .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin.
+ """
+ startup._init_plugins()
+ action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_action(view, func, action))
+ is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_is_valid(view, func, is_valid))
+ cls._registered_commands.append((action_obj, is_valid_obj))
+ core.BNRegisterPluginCommandForLowLevelILFunction(name, description, action_obj, is_valid_obj, None)
+
+ @classmethod
+ def register_for_low_level_il_instruction(cls, name, description, action, is_valid = None):
+ """
+ ``register_for_low_level_il_instruction`` Register a plugin to be called with a low level IL instruction argument
+
+ :param str name: name of the plugin
+ :param str description: description of the plugin
+ :param action: function to call with the ``BinaryView`` and a ``LowLevelILInstruction`` as arguments
+ :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
+ :rtype: None
+
+ .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin.
+ """
+ startup._init_plugins()
+ action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_action(view, func, instr, action))
+ is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_is_valid(view, func, instr, is_valid))
+ cls._registered_commands.append((action_obj, is_valid_obj))
+ core.BNRegisterPluginCommandForLowLevelILInstruction(name, description, action_obj, is_valid_obj, None)
+
+ @classmethod
+ def register_for_medium_level_il_function(cls, name, description, action, is_valid = None):
+ """
+ ``register_for_medium_level_il_function`` Register a plugin to be called with a medium level IL function argument
+
+ :param str name: name of the plugin
+ :param str description: description of the plugin
+ :param action: function to call with the ``BinaryView`` and a ``MediumLevelILFunction`` as arguments
+ :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
+ :rtype: None
+
+ .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin.
+ """
+ startup._init_plugins()
+ action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_action(view, func, action))
+ is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_is_valid(view, func, is_valid))
+ cls._registered_commands.append((action_obj, is_valid_obj))
+ core.BNRegisterPluginCommandForMediumLevelILFunction(name, description, action_obj, is_valid_obj, None)
+
+ @classmethod
+ def register_for_medium_level_il_instruction(cls, name, description, action, is_valid = None):
+ """
+ ``register_for_medium_level_il_instruction`` Register a plugin to be called with a medium level IL instruction argument
+
+ :param str name: name of the plugin
+ :param str description: description of the plugin
+ :param action: function to call with the ``BinaryView`` and a ``MediumLevelILInstruction`` as arguments
+ :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view
+ :rtype: None
+
+ .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin.
+ """
+ startup._init_plugins()
+ action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_action(view, func, instr, action))
+ is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_is_valid(view, func, instr, is_valid))
+ cls._registered_commands.append((action_obj, is_valid_obj))
+ core.BNRegisterPluginCommandForMediumLevelILInstruction(name, description, action_obj, is_valid_obj, None)
+
+ @classmethod
def get_valid_list(cls, context):
"""Dict of registered plugins"""
commands = cls.list
@@ -275,6 +454,36 @@ class PluginCommand(object):
if not self.command.functionIsValid:
return True
return self.command.functionIsValid(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand:
+ if context.function is None:
+ return False
+ if not self.command.lowLevelILFunctionIsValid:
+ return True
+ return self.command.lowLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand:
+ if context.instruction is None:
+ return False
+ if not isinstance(context.instruction, lowlevelil.LowLevelILInstruction):
+ return False
+ if not self.command.lowLevelILInstructionIsValid:
+ return True
+ return self.command.lowLevelILInstructionIsValid(self.command.context, context.view.handle,
+ context.instruction.function.handle, context.instruction.instr_index)
+ elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand:
+ if context.function is None:
+ return False
+ if not self.command.mediumLevelILFunctionIsValid:
+ return True
+ return self.command.mediumLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand:
+ if context.instruction is None:
+ return False
+ if not isinstance(context.instruction, mediumlevelil.MediumLevelILInstruction):
+ return False
+ if not self.command.mediumLevelILInstructionIsValid:
+ return True
+ return self.command.mediumLevelILInstructionIsValid(self.command.context, context.view.handle,
+ context.instruction.function.handle, context.instruction.instr_index)
return False
def execute(self, context):
@@ -288,6 +497,16 @@ class PluginCommand(object):
self.command.rangeCommand(self.command.context, context.view.handle, context.address, context.length)
elif self.command.type == PluginCommandType.FunctionPluginCommand:
self.command.functionCommand(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand:
+ self.command.lowLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand:
+ self.command.lowLevelILInstructionCommand(self.command.context, context.view.handle,
+ context.instruction.function.handle, context.instruction.instr_index)
+ elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand:
+ self.command.mediumLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle)
+ elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand:
+ self.command.mediumLevelILInstructionCommand(self.command.context, context.view.handle,
+ context.instruction.function.handle, context.instruction.instr_index)
def __repr__(self):
return "<PluginCommand: %s>" % self.name
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index c92c249a..e7838748 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -540,7 +540,7 @@ class PythonScriptingInstance(ScriptingInstance):
self.locals["current_address"] = self.active_addr
self.locals["here"] = self.active_addr
self.locals["current_selection"] = (self.active_selection_begin, self.active_selection_end)
- if self.active_func == None:
+ if self.active_func is None:
self.locals["current_llil"] = None
self.locals["current_mlil"] = None
else:
@@ -556,6 +556,8 @@ class PythonScriptingInstance(ScriptingInstance):
elif self.locals["current_address"] != self.active_addr:
if not self.active_view.file.navigate(self.active_view.file.view, self.locals["current_address"]):
sys.stderr.write("Address 0x%x is not valid for the current view\n" % self.locals["current_address"])
+ if self.active_view is not None:
+ self.active_view.update_analysis()
except:
traceback.print_exc()
finally:
diff --git a/python/types.py b/python/types.py
index f5279047..42ed7ddd 100644
--- a/python/types.py
+++ b/python/types.py
@@ -641,7 +641,7 @@ class Type(object):
return core.BNGenerateAutoDemangledTypeId(name)
@classmethod
- def get_auto_demanged_type_id_source(self):
+ def get_auto_demangled_type_id_source(self):
return core.BNGetAutoDemangledTypeIdSource()
def with_confidence(self, confidence):
@@ -687,6 +687,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