diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/architecture.py | 56 | ||||
| -rw-r--r-- | python/function.py | 2 | ||||
| -rw-r--r-- | python/highlevelil.py | 2172 | ||||
| -rw-r--r-- | python/lowlevelil.py | 3237 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 2366 |
5 files changed, 6085 insertions, 1748 deletions
diff --git a/python/architecture.py b/python/architecture.py index 3a37b5b6..079d080d 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -929,7 +929,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): else: operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) return self.get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, - lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index + lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))) except (KeyError, OSError): log.log_error(traceback.format_exc()) return False @@ -941,7 +941,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): else: sem_class_name = None return self.get_flag_condition_low_level_il(cond, sem_class_name, - lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index + lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))) except OSError: log.log_error(traceback.format_exc()) return 0 @@ -953,7 +953,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): else: sem_group_name = None return self.get_semantic_flag_group_low_level_il(sem_group_name, - lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index + lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))) except OSError: log.log_error(traceback.format_exc()) return 0 @@ -1361,7 +1361,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): def get_instruction_low_level_il(self, data:bytes, addr:int, il:'lowlevelil.LowLevelILFunction') -> int: """ - ``get_instruction_low_level_il`` appends LowLevelILExpr objects to ``il`` for the instruction at the given + ``get_instruction_low_level_il`` appends lowlevelil.ExpressionIndex 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 @@ -1603,7 +1603,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): return FlagRole.SpecialFlagRole def get_flag_write_low_level_il(self, op:LowLevelILOperation, size:int, write_type:Optional[FlagWriteTypeName], flag:FlagType, - operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param LowLevelILOperation op: :param int size: @@ -1611,7 +1611,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): :param operands: a list of either items that are either string register names or constant integer values :type operands: list(str) or list(int) :param LowLevelILFunction il: - :rtype: LowLevelILExpr + :rtype: lowlevelil.ExpressionIndex """ flag = self.get_flag_index(flag) if flag not in self._flag_roles: @@ -1619,7 +1619,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il) def get_default_flag_write_low_level_il(self, op:'lowlevelil.LowLevelILOperation', size:int, role:FlagRole, - operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param LowLevelILOperation op: :param int size: @@ -1627,7 +1627,7 @@ class Architecture(metaclass=_ArchitectureMetaClass): :param operands: a list of either items that are either string register names or constant integer values :type operands: list(str) or list(int) :param LowLevelILFunction il: - :rtype: LowLevelILExpr index + :rtype: ExpressionIndex index """ operand_list = (core.BNRegisterOrConstant * len(operands))() for i in range(len(operands)): @@ -1641,39 +1641,39 @@ class Architecture(metaclass=_ArchitectureMetaClass): else: operand_list[i].constant = True operand_list[i].value = operand - return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, + return lowlevelil.ExpressionIndex(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, role, operand_list, len(operand_list), il.handle)) def get_flag_condition_low_level_il(self, cond:'lowlevelil.LowLevelILFlagCondition', sem_class:Optional[SemanticClassType], - il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param LowLevelILFlagCondition cond: Flag condition to be computed :param SemanticClassType sem_class: Semantic class to be used (None for default semantics) - :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to - :rtype: LowLevelILExpr + :param LowLevelILFunction il: LowLevelILFunction object to append ExpressionIndex objects to + :rtype: ExpressionIndex """ return self.get_default_flag_condition_low_level_il(cond, sem_class, il) def get_default_flag_condition_low_level_il(self, cond:'lowlevelil.LowLevelILFlagCondition', - sem_class:Optional[SemanticClassType], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + sem_class:Optional[SemanticClassType], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param LowLevelILFlagCondition cond: :param SemanticClassType sem_class: :param LowLevelILFunction il: - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _class_index = None if sem_class is not None: _class_index = self.get_semantic_flag_class_index(sem_class) - return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, + return lowlevelil.ExpressionIndex(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, _class_index, il.handle)) def get_semantic_flag_group_low_level_il(self, sem_group:Optional[SemanticGroupType], - il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param Optional[SemanticGroupType] sem_group: :param LowLevelILFunction il: - :rtype: LowLevelILExpr + :rtype: lowlevelil.ExpressionIndex """ return il.unimplemented() @@ -2306,7 +2306,7 @@ class CoreArchitecture(Architecture): def get_instruction_low_level_il(self, data:Union[bytes, str], addr:int, il:lowlevelil.LowLevelILFunction) -> int: """ - ``get_instruction_low_level_il`` appends LowLevelILExpr objects to ``il`` for the instruction at the given + ``get_instruction_low_level_il`` appends lowlevelil.ExpressionIndex 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 @@ -2332,7 +2332,7 @@ class CoreArchitecture(Architecture): return length.value def get_flag_write_low_level_il(self, op:LowLevelILOperation, size:int, write_type:FlagWriteTypeName, - flag:FlagType, operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + flag:FlagType, operands:List['lowlevelil.ILRegisterType'], il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param LowLevelILOperation op: :param int size: @@ -2340,7 +2340,7 @@ class CoreArchitecture(Architecture): :param operands: a list of either items that are either string register names or constant integer values :type operands: list(str) or list(int) :param LowLevelILFunction il: - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ flag = self.get_flag_index(flag) operand_list = (core.BNRegisterOrConstant * len(operands))() @@ -2355,30 +2355,30 @@ class CoreArchitecture(Architecture): else: operand_list[i].constant = True operand_list[i].value = operand - return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, + return lowlevelil.ExpressionIndex(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:LowLevelILFlagCondition, sem_class:SemanticClassType, - il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :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 + :param LowLevelILFunction il: LowLevelILFunction object to append ExpressionIndex objects to + :rtype: ExpressionIndex """ class_index = self.get_semantic_flag_class_index(sem_class) - return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, + return lowlevelil.ExpressionIndex(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, class_index, il.handle)) def get_semantic_flag_group_low_level_il(self, sem_group:SemanticGroupName, - il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.LowLevelILExpr': + il:'lowlevelil.LowLevelILFunction') -> 'lowlevelil.ExpressionIndex': """ :param str sem_group: :param LowLevelILFunction il: - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ group_index = self.get_semantic_flag_group_index(sem_group) - return lowlevelil.LowLevelILExpr(core.BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group_index, il.handle)) + return lowlevelil.ExpressionIndex(core.BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group_index, il.handle)) def assemble(self, code:str, addr:int=0) -> bytes: """ diff --git a/python/function.py b/python/function.py index 5111ea5d..36ecc52f 100644 --- a/python/function.py +++ b/python/function.py @@ -3530,7 +3530,7 @@ class InstructionTextToken: return result @staticmethod - def _get_core_struct(tokens:List['InstructionTextToken']) -> ctypes.Array[core.BNInstructionTextToken]: + def _get_core_struct(tokens:List['InstructionTextToken']) -> 'ctypes.Array[core.BNInstructionTextToken]': """ Helper method for converting between core.BNInstructionTextToken and InstructionTextToken lists """ result = (core.BNInstructionTextToken * len(tokens))() for j in range(len(tokens)): diff --git a/python/highlevelil.py b/python/highlevelil.py index 2c4263d5..7f78ece7 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -20,12 +20,12 @@ import ctypes import struct -from typing import Optional, Generator, List, Union, Any, NewType +from typing import Optional, Generator, List, Union, Any, NewType, Tuple +from dataclasses import dataclass # Binary Ninja components from . import _binaryninjacore as core -from .enums import HighLevelILOperation, InstructionTextTokenType, DataFlowQueryOption, FunctionGraphType -from .variable import Variable +from .enums import HighLevelILOperation, DataFlowQueryOption, FunctionGraphType from . import function from . import binaryview from . import architecture @@ -42,53 +42,36 @@ ExpressionIndex = NewType('ExpressionIndex', int) InstructionIndex = NewType('InstructionIndex', int) HLILInstructionsType = Generator['HighLevelILInstruction', None, None] HLILBasicBlocksType = Generator['HighLevelILBasicBlock', None, None] +OperandsType = Tuple[ExpressionIndex, ExpressionIndex, ExpressionIndex, ExpressionIndex, ExpressionIndex] +HighLevelILOperandType = Union[ + 'HighLevelILInstruction', + 'lowlevelil.ILIntrinsic', + variable.Variable, + 'mediumlevelil.SSAVariable', + List[int], + List[variable.Variable], + List['mediumlevelil.SSAVariable'], + Optional[int], + float, + 'GotoLabel' +] + +@dataclass(frozen=True) class HighLevelILOperationAndSize: - def __init__(self, operation, size): - self._operation = operation - self._size = size + operation:HighLevelILOperation + size:int def __repr__(self): - if self._size == 0: - return "<%s>" % self._operation.name - return "<%s %d>" % (self._operation.name, self._size) - - def __eq__(self, other): - if isinstance(other, HighLevelILOperation): - return other == self._operation - if isinstance(other, self.__class__): - return other.size == self._size and other.operation == self._operation - return NotImplemented - - def __ne__(self, other): - if isinstance(other, self.__class__) or isinstance(other, HighLevelILOperation): - return not (self == other) - return NotImplemented - - def __hash__(self): - return hash((self._operation, self._size)) - - @property - def operation(self): - return self._operation - - @operation.setter - def operation(self, value): - self._operation = value - - @property - def size(self): - return self._size - - @size.setter - def size(self, value): - self._size = value + if self.size == 0: + return "<%s>" % self.operation.name + return "<%s %d>" % (self.operation.name, self.size) +@dataclass(frozen=True) class GotoLabel: - def __init__(self, function, id): - self._function = function - self._id = id + function:'HighLevelILFunction' + id:int def __repr__(self): return "<label: %s>" % self.name @@ -98,236 +81,63 @@ class GotoLabel: @property def label_id(self): - return self._id + return self.id @property def name(self): - return core.BNGetGotoLabelName(self._function.source_function.handle, self._id) + return core.BNGetGotoLabelName(self.function.source_function.handle, self.id) @name.setter def name(self, value): - core.BNSetUserGotoLabelName(self._function.source_function.handle, self._id, value) + core.BNSetUserGotoLabelName(self.function.source_function.handle, self.id, value) @property def definition(self): - return self._function.get_label(self._id) + return self.function.get_label(self.id) @property def uses(self): - return self._function.get_label_uses(self._id) + return self.function.get_label_uses(self.id) + + +@dataclass(frozen=True, order=True) +class CoreHighLevelILInstruction: + operation:HighLevelILOperation + source_operand:int + size:int + operands:OperandsType + address:int + parent:ExpressionIndex + + @classmethod + def from_BNHighLevelILInstruction(cls, instr:core.BNHighLevelILInstruction) -> 'CoreHighLevelILInstruction': + operands:OperandsType = tuple([ExpressionIndex(instr.operands[i]) for i in range(5)]) # type: ignore + return cls(HighLevelILOperation(instr.operation), instr.sourceOperand, instr.size, operands, instr.address, instr.parent) +@dataclass(frozen=True) class HighLevelILInstruction: """ ``class HighLevelILInstruction`` High Level Intermediate Language Instructions form an abstract syntax tree of the code. Control flow structures are present as high level constructs in the HLIL tree. """ + function:'HighLevelILFunction' + expr_index:ExpressionIndex + core_instr:CoreHighLevelILInstruction + as_ast:bool + instr_index:InstructionIndex + operand_names = tuple() - ILOperations = { - HighLevelILOperation.HLIL_NOP: [], - HighLevelILOperation.HLIL_BLOCK: [("body", "expr_list")], - HighLevelILOperation.HLIL_IF: [("condition", "expr"), ("true", "expr"), ("false", "expr")], - HighLevelILOperation.HLIL_WHILE: [("condition", "expr"), ("body", "expr")], - HighLevelILOperation.HLIL_WHILE_SSA: [("condition_phi", "expr"), ("condition", "expr"), ("body", "expr")], - HighLevelILOperation.HLIL_DO_WHILE: [("body", "expr"), ("condition", "expr")], - HighLevelILOperation.HLIL_DO_WHILE_SSA: [("body", "expr"), ("condition_phi", "expr"), ("condition", "expr")], - HighLevelILOperation.HLIL_FOR: [("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")], - HighLevelILOperation.HLIL_FOR_SSA: [("init", "expr"), ("condition_phi", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr")], - HighLevelILOperation.HLIL_SWITCH: [("condition", "expr"), ("default", "expr"), ("cases", "expr_list")], - HighLevelILOperation.HLIL_CASE: [("values", "expr_list"), ("body", "expr")], - HighLevelILOperation.HLIL_BREAK: [], - HighLevelILOperation.HLIL_CONTINUE: [], - HighLevelILOperation.HLIL_JUMP: [("dest", "expr")], - HighLevelILOperation.HLIL_RET: [("src", "expr_list")], - HighLevelILOperation.HLIL_NORET: [], - HighLevelILOperation.HLIL_GOTO: [("target", "label")], - HighLevelILOperation.HLIL_LABEL: [("target", "label")], - HighLevelILOperation.HLIL_VAR_DECLARE: [("var", "var")], - HighLevelILOperation.HLIL_VAR_INIT: [("dest", "var"), ("src", "expr")], - HighLevelILOperation.HLIL_VAR_INIT_SSA: [("dest", "var_ssa"), ("src", "expr")], - HighLevelILOperation.HLIL_ASSIGN: [("dest", "expr"), ("src", "expr")], - HighLevelILOperation.HLIL_ASSIGN_UNPACK: [("dest", "expr_list"), ("src", "expr")], - HighLevelILOperation.HLIL_ASSIGN_MEM_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int")], - HighLevelILOperation.HLIL_ASSIGN_UNPACK_MEM_SSA: [("dest", "expr_list"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int")], - HighLevelILOperation.HLIL_VAR: [("var", "var")], - HighLevelILOperation.HLIL_VAR_SSA: [("var", "var_ssa")], - HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], - HighLevelILOperation.HLIL_MEM_PHI: [("dest", "int"), ("src", "int_list")], - HighLevelILOperation.HLIL_STRUCT_FIELD: [("src", "expr"), ("offset", "int"), ("member_index", "member_index")], - HighLevelILOperation.HLIL_ARRAY_INDEX: [("src", "expr"), ("index", "expr")], - HighLevelILOperation.HLIL_ARRAY_INDEX_SSA: [("src", "expr"), ("src_memory", "int"), ("index", "expr")], - HighLevelILOperation.HLIL_SPLIT: [("high", "expr"), ("low", "expr")], - HighLevelILOperation.HLIL_DEREF: [("src", "expr")], - HighLevelILOperation.HLIL_DEREF_FIELD: [("src", "expr"), ("offset", "int"), ("member_index", "member_index")], - HighLevelILOperation.HLIL_DEREF_SSA: [("src", "expr"), ("src_memory", "int")], - HighLevelILOperation.HLIL_DEREF_FIELD_SSA: [("src", "expr"), ("src_memory", "int"), ("offset", "int"), ("member_index", "member_index")], - HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")], - HighLevelILOperation.HLIL_CONST: [("constant", "int")], - HighLevelILOperation.HLIL_CONST_PTR: [("constant", "int")], - HighLevelILOperation.HLIL_EXTERN_PTR: [("constant", "int"), ("offset", "int")], - HighLevelILOperation.HLIL_FLOAT_CONST: [("constant", "float")], - HighLevelILOperation.HLIL_IMPORT: [("constant", "int")], - HighLevelILOperation.HLIL_ADD: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - HighLevelILOperation.HLIL_SUB: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - HighLevelILOperation.HLIL_AND: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_OR: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_XOR: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_LSL: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_LSR: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_ASR: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_ROL: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - HighLevelILOperation.HLIL_ROR: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - HighLevelILOperation.HLIL_MUL: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MULU_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MULS_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_DIVU: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_DIVU_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_DIVS: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MODU: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MODU_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MODS: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_MODS_DP: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_NEG: [("src", "expr")], - HighLevelILOperation.HLIL_NOT: [("src", "expr")], - HighLevelILOperation.HLIL_SX: [("src", "expr")], - HighLevelILOperation.HLIL_ZX: [("src", "expr")], - HighLevelILOperation.HLIL_LOW_PART: [("src", "expr")], - HighLevelILOperation.HLIL_CALL: [("dest", "expr"), ("params", "expr_list")], - HighLevelILOperation.HLIL_CALL_SSA: [("dest", "expr"), ("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int")], - HighLevelILOperation.HLIL_CMP_E: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_NE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_BOOL_TO_INT: [("src", "expr")], - HighLevelILOperation.HLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_SYSCALL: [("params", "expr_list")], - HighLevelILOperation.HLIL_SYSCALL_SSA: [("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int")], - HighLevelILOperation.HLIL_TAILCALL: [("dest", "expr"), ("params", "expr_list")], - HighLevelILOperation.HLIL_BP: [], - HighLevelILOperation.HLIL_TRAP: [("vector", "int")], - HighLevelILOperation.HLIL_INTRINSIC: [("intrinsic", "intrinsic"), ("params", "expr_list")], - HighLevelILOperation.HLIL_INTRINSIC_SSA: [("intrinsic", "intrinsic"), ("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int")], - HighLevelILOperation.HLIL_UNDEF: [], - HighLevelILOperation.HLIL_UNIMPL: [], - HighLevelILOperation.HLIL_UNIMPL_MEM: [("src", "expr")], - HighLevelILOperation.HLIL_FADD: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FSUB: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FMUL: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FDIV: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FSQRT: [("src", "expr")], - HighLevelILOperation.HLIL_FNEG: [("src", "expr")], - HighLevelILOperation.HLIL_FABS: [("src", "expr")], - HighLevelILOperation.HLIL_FLOAT_TO_INT: [("src", "expr")], - HighLevelILOperation.HLIL_INT_TO_FLOAT: [("src", "expr")], - HighLevelILOperation.HLIL_FLOAT_CONV: [("src", "expr")], - HighLevelILOperation.HLIL_ROUND_TO_INT: [("src", "expr")], - HighLevelILOperation.HLIL_FLOOR: [("src", "expr")], - HighLevelILOperation.HLIL_CEIL: [("src", "expr")], - HighLevelILOperation.HLIL_FTRUNC: [("src", "expr")], - HighLevelILOperation.HLIL_FCMP_E: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_NE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_LT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_O: [("left", "expr"), ("right", "expr")], - HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")] - } - - def __init__(self, func:'HighLevelILFunction', expr_index:ExpressionIndex, as_ast:bool = True, - instr_index:InstructionIndex = None): + @classmethod + def create(cls, func:'HighLevelILFunction', expr_index:ExpressionIndex, as_ast:bool=True, instr_index:Optional[InstructionIndex]=None) -> 'HighLevelILInstruction': + assert func.arch is not None, "Attempted to create IL instruction with function missing an Architecture" instr = core.BNGetHighLevelILByIndex(func.handle, expr_index, as_ast) - self._function = func - if func.arch is None: - raise Exception("HighLevelILFunction architecture must not be None") - self._expr_index = expr_index + assert instr is not None, "core.BNGetHighLevelILByIndex returned None" + core_instr = CoreHighLevelILInstruction.from_BNHighLevelILInstruction(instr) if instr_index is None: - self._instr_index = core.BNGetHighLevelILInstructionForExpr(func.handle, expr_index) - else: - self._instr_index = instr_index - self._operation = HighLevelILOperation(instr.operation) - self._size = instr.size - self._address = instr.address - self._source_operand = instr.sourceOperand - self._parent = instr.parent - self._as_ast = as_ast - operands = HighLevelILInstruction.ILOperations[instr.operation] - self._operands = [] - i = 0 - for operand in operands: - name, operand_type = operand - value = None - if operand_type == "int": - value = instr.operands[i] - value = (value & ((1 << 63) - 1)) - (value & (1 << 63)) - 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 = HighLevelILInstruction(func, instr.operands[i], self._as_ast) - elif operand_type == "intrinsic": - value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) - elif operand_type == "var": - value = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) - elif operand_type == "var_ssa": - var = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) - version = instr.operands[i + 1] - i += 1 - value = mediumlevelil.SSAVariable(var, version) - elif operand_type == "int_list": - count = ctypes.c_ulonglong() - operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" - value = [] - for j in range(count.value): - value.append(operand_list[j]) - core.BNHighLevelILFreeOperandList(operand_list) - elif operand_type == "expr_list": - count = ctypes.c_ulonglong() - operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(count.value): - value.append(HighLevelILInstruction(func, operand_list[j], self._as_ast)) - core.BNHighLevelILFreeOperandList(operand_list) - elif operand_type == "var_ssa_list": - count = ctypes.c_ulonglong() - operand_list = core.BNHighLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(count.value // 2): - var_id = operand_list[j * 2] - var_version = operand_list[(j * 2) + 1] - value.append(mediumlevelil.SSAVariable(variable.Variable.from_identifier(self._function.source_function, - var_id), var_version)) - core.BNHighLevelILFreeOperandList(operand_list) - elif operand_type == "member_index": - value = instr.operands[i] - if (value & (1 << 63)) != 0: - value = None - elif operand_type == "label": - value = GotoLabel(self.function, instr.operands[i]) - self._operands.append(value) - self.__dict__[name] = value - i += 1 + instr_index = core.BNGetHighLevelILInstructionForExpr(func.handle, expr_index) + assert instr_index is not None, "core.BNGetHighLevelILInstructionForExpr returned None" + return ILInstruction[instr.operation](func, expr_index, core_instr, as_ast, instr_index) def __str__(self): lines = self.lines @@ -352,52 +162,47 @@ class HighLevelILInstruction: first_line += token.text if len(list(lines)) > 1: continuation = "..." - return "<%s: %s%s>" % (self._operation.name, first_line, continuation) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return core.BNHighLevelILExprEqual(self._function.handle, self._expr_index, other._function.handle, other._expr_index) + return "<%s: %s%s>" % (self.operation.name, first_line, continuation) - def __ne__(self, other): + def __eq__(self, other:'HighLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return not core.BNHighLevelILExprEqual(self._function.handle, self._expr_index, other._function.handle, other._expr_index) + return self.function == other.function and self.expr_index == other.expr_index - def __lt__(self, other): + def __lt__(self, other:'HighLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return core.BNHighLevelILExprLessThan(self._function.handle, self._expr_index, other._function.handle, other._expr_index) + return self.function == other.function and self.expr_index < other.expr_index - def __le__(self, other): + def __le__(self, other:'HighLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return not core.BNHighLevelILExprLessThan(other._function.handle, other._expr_index, self._function.handle, self._expr_index) + return self.function == other.function and self.expr_index <= other.expr_index - def __gt__(self, other): + def __gt__(self, other:'HighLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return core.BNHighLevelILExprLessThan(other._function.handle, other._expr_index, self._function.handle, self._expr_index) + return self.function == other.function and self.expr_index > other.expr_index - def __ge__(self, other): + def __ge__(self, other:'HighLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return not core.BNHighLevelILExprLessThan(self._function.handle, self._expr_index, other._function, other._expr_index) + return self.function == other.function and self.expr_index >= other.expr_index def __hash__(self): - return hash((self._function, self._expr_index)) + return hash((self.function, self.expr_index)) @property def lines(self) -> LinesType: """HLIL text lines (read-only)""" count = ctypes.c_ulonglong() - lines = core.BNGetHighLevelILExprText(self._function.handle, self._expr_index, self._as_ast, count, None) + lines = core.BNGetHighLevelILExprText(self.function.handle, self.expr_index, self.as_ast, count, None) assert lines is not None, "core.BNGetHighLevelILExprText returned None" try: for i in range(0, count.value): addr = lines[i].addr if lines[i].instrIndex != 0xffffffffffffffff: - il_instr = self._function[lines[i].instrIndex] + il_instr = self.function[lines[i].instrIndex] else: il_instr = None color = highlight.HighlightColor._from_core_struct(lines[i].highlight) @@ -407,137 +212,123 @@ class HighLevelILInstruction: core.BNFreeDisassemblyTextLines(lines, count.value) @property - def prefix_operands(self) -> List[Any]: + def prefix_operands(self) -> List[Union[HighLevelILOperandType, HighLevelILOperationAndSize]]: """All operands in the expression tree in prefix order""" - result = [HighLevelILOperationAndSize(self._operation, self._size)] - for operand in self._operands: + result:List[Union[HighLevelILOperandType, HighLevelILOperationAndSize]] = [ + HighLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: if isinstance(operand, HighLevelILInstruction): - result += operand.prefix_operands + result.extend(operand.prefix_operands) else: result.append(operand) return result @property - def postfix_operands(self) -> List[Any]: + def postfix_operands(self) -> List[Union[HighLevelILOperandType, HighLevelILOperationAndSize]]: """All operands in the expression tree in postfix order""" - result = [] - for operand in self._operands: + result:List[Union[HighLevelILOperandType, HighLevelILOperationAndSize]] = [] + for operand in self.operands: if isinstance(operand, HighLevelILInstruction): - result += operand.postfix_operands + result.extend(operand.postfix_operands) else: result.append(operand) - result.append(HighLevelILOperationAndSize(self._operation, self._size)) + result.append(HighLevelILOperationAndSize(self.operation, self.size)) return result @property - def function(self) -> 'HighLevelILFunction': - return self._function - - @property - def expr_index(self) -> ExpressionIndex: - return self._expr_index - - @expr_index.setter - def expr_index(self, value:ExpressionIndex) -> None: - self._expr_index = value - - @property - def instr_index(self) -> int: - """Index of the statement that this expression belongs to (read-only)""" - return core.BNGetHighLevelILInstructionForExpr(self._function.handle, self._expr_index) - - @property def instr(self) -> 'HighLevelILInstruction': """The statement that this expression belongs to (read-only)""" - return self._function[self.instr_index] + return self.function[self.instr_index] @property def ast(self) -> 'HighLevelILInstruction': """This expression with full AST printing (read-only)""" - if self._as_ast: + if self.as_ast: return self - return HighLevelILInstruction(self._function, self._expr_index, True) + return HighLevelILInstruction.create(self.function, self.expr_index, True) @property def non_ast(self) -> 'HighLevelILInstruction': """This expression without full AST printing (read-only)""" - if not self._as_ast: + if not self.as_ast: return self - return HighLevelILInstruction(self._function, self._expr_index, False) + return HighLevelILInstruction.create(self.function, self.expr_index, False) @property def operation(self) -> HighLevelILOperation: - return self._operation - - @operation.setter - def operation(self, value:HighLevelILOperation) -> None: - self._operation = value + return self.core_instr.operation @property def size(self) -> int: - return self._size - - @size.setter - def size(self, value:int) -> None: - self._size = value + return self.core_instr.size @property def address(self) -> int: - return self._address - - @address.setter - def address(self, value:int) -> None: - self._address = value + return self.core_instr.address @property def source_operand(self): - return self._source_operand + return self.core_instr.source_operand - @source_operand.setter - def source_operand(self, value): - self._source_operand = value + @property + def core_operands(self) -> Any: + return self.core_instr.operands @property - def operands(self) -> Any: - return self._operands + def vars_written(self) -> List[Union[variable.Variable, 'mediumlevelil.SSAVariable']]: + """List of variables written by instruction""" + return [] - @operands.setter - def operands(self, value: Any): - self._operands = value + @property + def operands(self) -> Generator[HighLevelILOperandType, None, None]: + for operand_name in self.operand_names: + assert hasattr(self, operand_name), f"No operand '{operand_name}' for instruction {repr(self)}({self.operation})" + yield self.__getattribute__(operand_name) + + @property + def vars_read(self) -> List[Union[variable.Variable, 'mediumlevelil.SSAVariable']]: + """List of variables read by instruction""" + result = [] + for operand in self.operands: + if (isinstance(operand, variable.Variable)) or (isinstance(operand, mediumlevelil.SSAVariable)): + result.append(operand) + elif isinstance(operand, HighLevelILInstruction): + result += operand.vars_read + return result @property def parent(self) -> Optional['HighLevelILInstruction']: - if self._parent >= core.BNGetHighLevelILExprCount(self._function.handle): + if self.core_instr.parent >= core.BNGetHighLevelILExprCount(self.function.handle): return None - return HighLevelILInstruction(self._function, self._parent, self._as_ast) + return HighLevelILInstruction.create(self.function, self.core_instr.parent, self.as_ast) @property def ssa_form(self) -> 'HighLevelILInstruction': """SSA form of expression (read-only)""" - assert self._function.ssa_form is not None - return HighLevelILInstruction(self._function.ssa_form, - core.BNGetHighLevelILSSAExprIndex(self._function.handle, self._expr_index), self._as_ast) + assert self.function.ssa_form is not None + return HighLevelILInstruction.create(self.function.ssa_form, + core.BNGetHighLevelILSSAExprIndex(self.function.handle, self.expr_index), self.as_ast) @property def non_ssa_form(self) -> Optional['HighLevelILInstruction']: """Non-SSA form of expression (read-only)""" - if self._function.non_ssa_form is None: + if self.function.non_ssa_form is None: return None - return HighLevelILInstruction(self._function.non_ssa_form, - core.BNGetHighLevelILNonSSAExprIndex(self._function.handle, self._expr_index), self._as_ast) + return HighLevelILInstruction.create(self.function.non_ssa_form, + core.BNGetHighLevelILNonSSAExprIndex(self.function.handle, self.expr_index), self.as_ast) @property def medium_level_il(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: """Medium level IL form of this expression""" - expr = self._function.get_medium_level_il_expr_index(self._expr_index) + expr = self.function.get_medium_level_il_expr_index(self.expr_index) if expr is None: return None - mlil = self._function.medium_level_il + mlil = self.function.medium_level_il if mlil is None: return None ssa_func = mlil.ssa_form assert ssa_func is not None, "medium_level_il.ssa_form is None" - return mediumlevelil.MediumLevelILInstruction(ssa_func, expr) + return mediumlevelil.MediumLevelILInstruction.create(ssa_func, expr) @property def mlil(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: @@ -546,13 +337,13 @@ class HighLevelILInstruction: @property def mlils(self) -> Generator['mediumlevelil.MediumLevelILInstruction', None, None]: - for expr in self._function.get_medium_level_il_expr_indexes(self._expr_index): - mlil = self._function.medium_level_il + for expr in self.function.get_medium_level_il_expr_indexes(self.expr_index): + mlil = self.function.medium_level_il if mlil is None: return ssa_func = mlil.ssa_form assert ssa_func is not None, "medium_level_il.ssa_form is None" - yield mediumlevelil.MediumLevelILInstruction(ssa_func, expr) + yield mediumlevelil.MediumLevelILInstruction.create(ssa_func, expr) @property def low_level_il(self) -> Optional['lowlevelil.LowLevelILInstruction']: @@ -567,7 +358,7 @@ class HighLevelILInstruction: return self.low_level_il @property - def llils(self) -> List['lowlevelil.LowLevelILExpr']: + def llils(self) -> List['lowlevelil.ExpressionIndex']: result = set() for mlil_expr in self.mlils: for llil_expr in mlil_expr.llils: @@ -580,10 +371,10 @@ class HighLevelILInstruction: IL basic block object containing this expression (read-only) (only available on finalized functions). Returns None for HLIL_BLOCK expressions as these can contain multiple basic blocks. """ - block = core.BNGetHighLevelILBasicBlockForInstruction(self._function.handle, self._instr_index) - if not block or self._function.source_function is None: + block = core.BNGetHighLevelILBasicBlockForInstruction(self.function.handle, self.instr_index) + if not block or self.function.source_function is None: return None - return HighLevelILBasicBlock(self._function.source_function.view, block, self._function) + return HighLevelILBasicBlock(self.function.source_function.view, block, self.function) @property def value(self) -> 'variable.RegisterValue': @@ -604,11 +395,11 @@ class HighLevelILInstruction: @property def expr_type(self) -> Optional['types.Type']: """Type of expression""" - result = core.BNGetHighLevelILExprType(self._function.handle, self._expr_index) + result = core.BNGetHighLevelILExprType(self.function.handle, self.expr_index) if result.type: platform = None - if self._function.source_function: - platform = self._function.source_function.platform + if self.function.source_function: + platform = self.function.source_function.platform return types.Type(result.type, platform = platform, confidence = result.confidence) return None @@ -621,12 +412,1669 @@ class HighLevelILInstruction: @property def ssa_memory_version(self) -> int: """Version of active memory contents in SSA form for this instruction""" - return core.BNGetHighLevelILSSAMemoryVersionAtILInstruction(self._function.handle, self._instr_index) + return core.BNGetHighLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index) def get_ssa_var_version(self, var:'variable.Variable') -> int: var_data = var.to_BNVariable() - return core.BNGetHighLevelILSSAVarVersionAtILInstruction(self._function.handle, var_data, self._instr_index) + return core.BNGetHighLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index) + + def get_int(self, operand_index:int) -> int: + value = self.core_instr.operands[operand_index] + return (value & ((1 << 63) - 1)) - (value & (1 << 63)) + + def get_float(self, operand_index:int) -> float: + value = self.core_instr.operands[operand_index] + if self.core_instr.size == 4: + return struct.unpack("f", struct.pack("I", value & 0xffffffff))[0] + elif self.core_instr.size == 8: + return struct.unpack("d", struct.pack("Q", value))[0] + else: + return float(value) + + def get_expr(self, operand_index:int) -> 'HighLevelILInstruction': + return HighLevelILInstruction.create(self.function, + ExpressionIndex(self.core_instr.operands[operand_index])) + + def get_intrinsic(self, operand_index:int) -> 'lowlevelil.ILIntrinsic': + assert self.function.arch is not None, "Attempting to create ILIntrinsic from function with no Architecture" + return lowlevelil.ILIntrinsic(self.function.arch, + architecture.IntrinsicIndex(self.core_instr.operands[operand_index])) + + def get_var(self, operand_index:int) -> variable.Variable: + value = self.core_instr.operands[operand_index] + return variable.Variable.from_identifier(self.function.source_function, self.core_instr.operands[operand_index]) + + def get_var_ssa(self, operand_index1:int, operand_index2:int) -> 'mediumlevelil.SSAVariable': + var = variable.Variable.from_identifier(self.function.source_function, self.core_instr.operands[operand_index1]) + version = self.core_instr.operands[operand_index2] + return mediumlevelil.SSAVariable(var, version) + + def get_var_ssa_dest_and_src(self, operand_index1:int, operand_index2:int) -> 'mediumlevelil.SSAVariable': + var = variable.Variable.from_identifier(self.function.source_function, self.core_instr.operands[operand_index1]) + dest_version = self.core_instr.operands[operand_index2] + return mediumlevelil.SSAVariable(var, dest_version) + + def get_int_list(self, operand_index:int) -> List[int]: + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" + value:List[int] = [] + try: + for j in range(count.value): + value.append(operand_list[j]) + return value + finally: + core.BNHighLevelILFreeOperandList(operand_list) + + def get_expr_list(self, operand_index1:int, operand_index2:int) -> List[variable.Variable]: + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" + value:List[variable.Variable] = [] + try: + for j in range(count.value): + value.append(variable.Variable.from_identifier(self.function.source_function, operand_list[j])) + return value + finally: + core.BNHighLevelILFreeOperandList(operand_list) + + def get_var_ssa_list(self, operand_index1:int, _:int) -> List['mediumlevelil.SSAVariable']: + count = ctypes.c_ulonglong() + operand_list = core.BNHighLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNHighLevelILGetOperandList returned None" + value = [] + try: + for j in range(count.value // 2): + var_id = operand_list[j * 2] + var_version = operand_list[(j * 2) + 1] + value.append(mediumlevelil.SSAVariable(variable.Variable.from_identifier(self.function.source_function, + var_id), var_version)) + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + def get_member_index(self, operand_index:int) -> Optional[int]: + value = self.core_instr.operands[operand_index] + if (value & (1 << 63)) != 0: + value = None + return value + + def get_label(self, operand_index:int) -> GotoLabel: + return GotoLabel(self.function, self.core_instr.operands[operand_index]) + + +@dataclass(frozen=True, repr=False) +class Arithmetic(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Memory(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class ControlFlow(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Loop(ControlFlow): + pass + + +@dataclass(frozen=True, repr=False) +class Call(ControlFlow): + + @property + def params(self) -> List[HighLevelILInstruction]: + return NotImplemented + + @property + def vars_read(self) -> List[Union['mediumlevelil.SSAVariable', variable.Variable]]: + result = [] + for param in self.params: + if isinstance(param, HighLevelILInstruction): + result.extend(param.vars_read) + else: + assert False, "Call.params returned object other than Variable, SSAVariable or MediumLevelILInstruction" + return result + +@dataclass(frozen=True, repr=False) +class UnaryOperation(HighLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self) -> HighLevelILInstruction: + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class BinaryOperation(HighLevelILInstruction): + operand_names = tuple(["left", "right"]) + + @property + def left(self) -> HighLevelILInstruction: + return self.get_expr(0) + + @property + def right(self) -> HighLevelILInstruction: + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class Carry(Arithmetic): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self) -> HighLevelILInstruction: + return self.get_expr(0) + + @property + def right(self) -> HighLevelILInstruction: + return self.get_expr(1) + + @property + def carry(self) -> HighLevelILInstruction: + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class Comparison(BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class Constant(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class SSA(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Phi(SSA): + pass + + +@dataclass(frozen=True, repr=False) +class FloatingPoint(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Terminal(ControlFlow): + pass + + +@dataclass(frozen=True, repr=False) +class Return(Terminal): + pass + + +@dataclass(frozen=True, repr=False) +class Signed(HighLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class DoublePrecision(Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class Syscall(Call): + pass + + +@dataclass(frozen=True, repr=False) +class Tailcall(Call): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILNop(HighLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILBlock(HighLevelILInstruction): + operand_names = tuple(["body"]) + + @property + def body(self): + return self.get_expr_list(0, 1) + + def __iter__(self): + for expr in self.body: + yield expr + +@dataclass(frozen=True, repr=False) +class HighLevelILIf(ControlFlow): + operand_names = tuple(["condition", "true", "false"]) + + @property + def condition(self): + return self.get_expr(0) + + @property + def true(self): + return self.get_expr(1) + + @property + def false(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILWhile(Loop): + operand_names = tuple(["condition", "body"]) + + @property + def condition(self): + return self.get_expr(0) + + @property + def body(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILWhile_ssa(Loop, SSA): + operand_names = tuple(["condition_phi", "condition", "body"]) + + @property + def condition_phi(self): + return self.get_expr(0) + + @property + def condition(self): + return self.get_expr(1) + + @property + def body(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDo_while(Loop): + operand_names = tuple(["body", "condition"]) + + @property + def body(self): + return self.get_expr(0) + + @property + def condition(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDo_while_ssa(Loop, SSA): + operand_names = tuple(["body", "condition_phi", "condition"]) + + @property + def body(self): + return self.get_expr(0) + + @property + def condition_phi(self): + return self.get_expr(1) + + @property + def condition(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFor(Loop): + operand_names = tuple(["init", "condition", "update", "body"]) + + @property + def init(self): + return self.get_expr(0) + + @property + def condition(self): + return self.get_expr(1) + + @property + def update(self): + return self.get_expr(2) + + @property + def body(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFor_ssa(Loop, SSA): + operand_names = tuple(["init", "condition_phi", "condition", "update"]) + + @property + def init(self): + return self.get_expr(0) + + @property + def condition_phi(self): + return self.get_expr(1) + + @property + def condition(self): + return self.get_expr(2) + + @property + def update(self): + return self.get_expr(3) + + @property + def body(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILSwitch(ControlFlow): + operand_names = tuple(["condition", "default", "cases"]) + + @property + def condition(self): + return self.get_expr(0) + + @property + def default(self): + return self.get_expr(1) + + @property + def cases(self): + return self.get_expr_list(2, 3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCase(HighLevelILInstruction): + operand_names = tuple(["values", "body"]) + + @property + def values(self): + return self.get_expr_list(0, 1) + + @property + def body(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILBreak(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILContinue(ControlFlow): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILJump(Terminal): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILRet(ControlFlow): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr_list(0, 1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILNoret(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILGoto(Terminal): + operand_names = tuple(["target"]) + + @property + def target(self): + return self.get_label(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILLabel(HighLevelILInstruction): + operand_names = tuple(["target"]) + + @property + def target(self): + return self.get_label(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar_declare(HighLevelILInstruction): + operand_names = tuple(["var"]) + + @property + def var(self): + return self.get_var(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar_init(HighLevelILInstruction): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar_init_ssa(SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var_ssa(0, 1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAssign(HighLevelILInstruction): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAssign_unpack(HighLevelILInstruction): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_expr_list(0, 1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAssign_mem_ssa(SSA): + operand_names = tuple(["dest", "dest_memory", "src", "src_memory"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def dest_memory(self): + return self.get_int(1) + + @property + def src(self): + return self.get_expr(2) + + @property + def src_memory(self): + return self.get_int(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAssign_unpack_mem_ssa(SSA): + operand_names = tuple(["dest", "dest_memory", "src", "src_memory"]) + + @property + def dest(self): + return self.get_expr_list(0, 1) + + @property + def dest_memory(self): + return self.get_int(2) + + @property + def src(self): + return self.get_expr(3) + + @property + def src_memory(self): + return self.get_int(4) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar(HighLevelILInstruction): + operand_names = tuple(["var"]) + + @property + def var(self): + return self.get_var(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar_ssa(SSA): + operand_names = tuple(["var"]) + + @property + def var(self): + return self.get_var_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILVar_phi(SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var_ssa(0, 1) + + @property + def src(self): + return self.get_var_ssa_list(2, 3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILMem_phi(Memory): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_int(0) + + @property + def src(self): + return self.get_int_list(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILStruct_field(HighLevelILInstruction): + operand_names = tuple(["src", "offset", "member_index"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def member_index(self): + return self.get_member_index(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILArray_index(HighLevelILInstruction): + operand_names = tuple(["src", "index"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def index(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILArray_index_ssa(SSA): + operand_names = tuple(["src", "src_memory", "index"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def src_memory(self): + return self.get_int(1) + + @property + def index(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILSplit(HighLevelILInstruction): + operand_names = tuple(["high", "low"]) + + @property + def high(self): + return self.get_expr(0) + + @property + def low(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDeref(HighLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDeref_field(HighLevelILInstruction): + operand_names = tuple(["src", "offset", "member_index"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def member_index(self): + return self.get_member_index(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDeref_ssa(SSA): + operand_names = tuple(["src", "src_memory"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def src_memory(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDeref_field_ssa(SSA): + operand_names = tuple(["src", "src_memory", "offset", "member_index"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def src_memory(self): + return self.get_int(1) + + @property + def offset(self): + return self.get_int(2) + + @property + def member_index(self): + return self.get_member_index(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAddress_of(HighLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILConst(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILConst_ptr(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + +@dataclass(frozen=True, repr=False) +class HighLevelILExtern_ptr(Constant): + operand_names = tuple(["constant", "offset"]) + + @property + def constant(self): + return self.get_int(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFloat_const(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_float(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILImport(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAdd(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILAdc(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILSub(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILSbb(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILAnd(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILOr(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILXor(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILLsl(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILLsr(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILAsr(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILRol(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILRlc(Arithmetic, BinaryOperation): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILRor(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILRrc(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILMul(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILMulu_dp(BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILMuls_dp(Signed, BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDivu(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILDivu_dp(BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILDivs(Signed, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILDivs_dp(Signed, BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILModu(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILModu_dp(BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILMods(Signed, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILMods_dp(Signed, BinaryOperation, DoublePrecision): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILNeg(Arithmetic, UnaryOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILNot(Arithmetic, UnaryOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILSx(Arithmetic, UnaryOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILZx(Arithmetic, UnaryOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILLow_part(Arithmetic, UnaryOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCall(Call): + operand_names = tuple(["dest", "params"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def params(self): + return self.get_expr_list(1, 2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCall_ssa(Call, SSA): + operand_names = tuple(["dest", "params", "dest_memory", "src_memory"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def params(self): + return self.get_expr_list(1, 2) + + @property + def dest_memory(self): + return self.get_int(3) + + @property + def src_memory(self): + return self.get_int(4) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_e(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_ne(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_slt(Comparison, Signed): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_ult(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_sle(Comparison, Signed): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_ule(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_sge(Comparison, Signed): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_uge(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_sgt(Comparison, Signed): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCmp_ugt(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILTest_bit(Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILBool_to_int(HighLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILAdd_overflow(Arithmetic, BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class HighLevelILSyscall(Call): + operand_names = tuple(["params"]) + + @property + def params(self): + return self.get_expr_list(0, 1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILSyscall_ssa(Call, SSA): + operand_names = tuple(["params", "dest_memory", "src_memory"]) + + @property + def params(self): + return self.get_expr_list(0, 1) + + @property + def dest_memory(self): + return self.get_int(2) + + @property + def src_memory(self): + return self.get_int(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILTailcall(Tailcall): + operand_names = tuple(["dest", "params"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def params(self): + return self.get_expr_list(1, 2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILBp(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILTrap(Terminal): + operand_names = tuple(["vector"]) + + @property + def vector(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILIntrinsic(HighLevelILInstruction): + operand_names = tuple(["intrinsic", "params"]) + + @property + def intrinsic(self): + return self.get_intrinsic(0) + + @property + def params(self): + return self.get_expr_list(1, 2) + + +@dataclass(frozen=True, repr=False) +class HighLevelILIntrinsic_ssa(SSA): + operand_names = tuple(["intrinsic", "params", "dest_memory", "src_memory"]) + + @property + def intrinsic(self): + return self.get_intrinsic(0) + + @property + def params(self): + return self.get_expr_list(1, 2) + + @property + def dest_memory(self): + return self.get_int(2) + + @property + def src_memory(self): + return self.get_int(3) + + +@dataclass(frozen=True, repr=False) +class HighLevelILUndef(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILUnimpl(HighLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class HighLevelILUnimpl_mem(Memory): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFadd(FloatingPoint): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFsub(FloatingPoint): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFmul(FloatingPoint): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFdiv(FloatingPoint): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFsqrt(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFneg(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFabs(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFloat_to_int(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILInt_to_float(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFloat_conv(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILRound_to_int(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFloor(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILCeil(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFtrunc(FloatingPoint): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_e(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_ne(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_lt(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_le(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_ge(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_gt(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_o(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class HighLevelILFcmp_uo(FloatingPoint, Comparison): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +ILInstruction = { + HighLevelILOperation.HLIL_NOP:HighLevelILNop, # , + HighLevelILOperation.HLIL_BLOCK:HighLevelILBlock, # ("body", "expr_list"), + HighLevelILOperation.HLIL_IF:HighLevelILIf, # ("condition", "expr"), ("true", "expr"), ("false", "expr"), + HighLevelILOperation.HLIL_WHILE:HighLevelILWhile, # ("condition", "expr"), ("body", "expr"), + HighLevelILOperation.HLIL_WHILE_SSA:HighLevelILWhile_ssa, # ("condition_phi", "expr"), ("condition", "expr"), ("body", "expr"), + HighLevelILOperation.HLIL_DO_WHILE:HighLevelILDo_while, # ("body", "expr"), ("condition", "expr"), + HighLevelILOperation.HLIL_DO_WHILE_SSA:HighLevelILDo_while_ssa, # ("body", "expr"), ("condition_phi", "expr"), ("condition", "expr"), + HighLevelILOperation.HLIL_FOR:HighLevelILFor, # ("init", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr"), + HighLevelILOperation.HLIL_FOR_SSA:HighLevelILFor_ssa, # ("init", "expr"), ("condition_phi", "expr"), ("condition", "expr"), ("update", "expr"), ("body", "expr"), + HighLevelILOperation.HLIL_SWITCH:HighLevelILSwitch, # ("condition", "expr"), ("default", "expr"), ("cases", "expr_list"), + HighLevelILOperation.HLIL_CASE:HighLevelILCase, # ("values", "expr_list"), ("body", "expr"), + HighLevelILOperation.HLIL_BREAK:HighLevelILBreak, # , + HighLevelILOperation.HLIL_CONTINUE:HighLevelILContinue, # , + HighLevelILOperation.HLIL_JUMP:HighLevelILJump, # ("dest", "expr"), + HighLevelILOperation.HLIL_RET:HighLevelILRet, # ("src", "expr_list"), + HighLevelILOperation.HLIL_NORET:HighLevelILNoret, # , + HighLevelILOperation.HLIL_GOTO:HighLevelILGoto, # ("target", "label"), + HighLevelILOperation.HLIL_LABEL:HighLevelILLabel, # ("target", "label"), + HighLevelILOperation.HLIL_VAR_DECLARE:HighLevelILVar_declare, # ("var", "var"), + HighLevelILOperation.HLIL_VAR_INIT:HighLevelILVar_init, # ("dest", "var"), ("src", "expr"), + HighLevelILOperation.HLIL_VAR_INIT_SSA:HighLevelILVar_init_ssa, # ("dest", "var_ssa"), ("src", "expr"), + HighLevelILOperation.HLIL_ASSIGN:HighLevelILAssign, # ("dest", "expr"), ("src", "expr"), + HighLevelILOperation.HLIL_ASSIGN_UNPACK:HighLevelILAssign_unpack, # ("dest", "expr_list"), ("src", "expr"), + HighLevelILOperation.HLIL_ASSIGN_MEM_SSA:HighLevelILAssign_mem_ssa, # ("dest", "expr"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int"), + HighLevelILOperation.HLIL_ASSIGN_UNPACK_MEM_SSA:HighLevelILAssign_unpack_mem_ssa, # ("dest", "expr_list"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int"), + HighLevelILOperation.HLIL_VAR:HighLevelILVar, # ("var", "var"), + HighLevelILOperation.HLIL_VAR_SSA:HighLevelILVar_ssa, # ("var", "var_ssa"), + HighLevelILOperation.HLIL_VAR_PHI:HighLevelILVar_phi, # ("dest", "var_ssa"), ("src", "var_ssa_list"), + HighLevelILOperation.HLIL_MEM_PHI:HighLevelILMem_phi, # ("dest", "int"), ("src", "int_list"), + HighLevelILOperation.HLIL_STRUCT_FIELD:HighLevelILStruct_field, # ("src", "expr"), ("offset", "int"), ("member_index", "member_index"), + HighLevelILOperation.HLIL_ARRAY_INDEX:HighLevelILArray_index, # ("src", "expr"), ("index", "expr"), + HighLevelILOperation.HLIL_ARRAY_INDEX_SSA:HighLevelILArray_index_ssa, # ("src", "expr"), ("src_memory", "int"), ("index", "expr"), + HighLevelILOperation.HLIL_SPLIT:HighLevelILSplit, # ("high", "expr"), ("low", "expr"), + HighLevelILOperation.HLIL_DEREF:HighLevelILDeref, # ("src", "expr"), + HighLevelILOperation.HLIL_DEREF_FIELD:HighLevelILDeref_field, # ("src", "expr"), ("offset", "int"), ("member_index", "member_index"), + HighLevelILOperation.HLIL_DEREF_SSA:HighLevelILDeref_ssa, # ("src", "expr"), ("src_memory", "int"), + HighLevelILOperation.HLIL_DEREF_FIELD_SSA:HighLevelILDeref_field_ssa, # ("src", "expr"), ("src_memory", "int"), ("offset", "int"), ("member_index", "member_index"), + HighLevelILOperation.HLIL_ADDRESS_OF:HighLevelILAddress_of, # ("src", "expr"), + HighLevelILOperation.HLIL_CONST:HighLevelILConst, # ("constant", "int"), + HighLevelILOperation.HLIL_CONST_PTR:HighLevelILConst_ptr, # ("constant", "int"), + HighLevelILOperation.HLIL_EXTERN_PTR:HighLevelILExtern_ptr, # ("constant", "int"), ("offset", "int"), + HighLevelILOperation.HLIL_FLOAT_CONST:HighLevelILFloat_const, # ("constant", "float"), + HighLevelILOperation.HLIL_IMPORT:HighLevelILImport, # ("constant", "int"), + HighLevelILOperation.HLIL_ADD:HighLevelILAdd, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_ADC:HighLevelILAdc, # ("left", "expr"), ("right", "expr"), ("carry", "expr"), + HighLevelILOperation.HLIL_SUB:HighLevelILSub, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_SBB:HighLevelILSbb, # ("left", "expr"), ("right", "expr"), ("carry", "expr"), + HighLevelILOperation.HLIL_AND:HighLevelILAnd, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_OR:HighLevelILOr, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_XOR:HighLevelILXor, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_LSL:HighLevelILLsl, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_LSR:HighLevelILLsr, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_ASR:HighLevelILAsr, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_ROL:HighLevelILRol, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_RLC:HighLevelILRlc, # ("left", "expr"), ("right", "expr"), ("carry", "expr"), + HighLevelILOperation.HLIL_ROR:HighLevelILRor, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_RRC:HighLevelILRrc, # ("left", "expr"), ("right", "expr"), ("carry", "expr"), + HighLevelILOperation.HLIL_MUL:HighLevelILMul, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MULU_DP:HighLevelILMulu_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MULS_DP:HighLevelILMuls_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_DIVU:HighLevelILDivu, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_DIVU_DP:HighLevelILDivu_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_DIVS:HighLevelILDivs, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_DIVS_DP:HighLevelILDivs_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MODU:HighLevelILModu, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MODU_DP:HighLevelILModu_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MODS:HighLevelILMods, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_MODS_DP:HighLevelILMods_dp, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_NEG:HighLevelILNeg, # ("src", "expr"), + HighLevelILOperation.HLIL_NOT:HighLevelILNot, # ("src", "expr"), + HighLevelILOperation.HLIL_SX:HighLevelILSx, # ("src", "expr"), + HighLevelILOperation.HLIL_ZX:HighLevelILZx, # ("src", "expr"), + HighLevelILOperation.HLIL_LOW_PART:HighLevelILLow_part, # ("src", "expr"), + HighLevelILOperation.HLIL_CALL:HighLevelILCall, # ("dest", "expr"), ("params", "expr_list"), + HighLevelILOperation.HLIL_CALL_SSA:HighLevelILCall_ssa, # ("dest", "expr"), ("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int"), + HighLevelILOperation.HLIL_CMP_E:HighLevelILCmp_e, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_NE:HighLevelILCmp_ne, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_SLT:HighLevelILCmp_slt, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_ULT:HighLevelILCmp_ult, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_SLE:HighLevelILCmp_sle, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_ULE:HighLevelILCmp_ule, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_SGE:HighLevelILCmp_sge, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_UGE:HighLevelILCmp_uge, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_SGT:HighLevelILCmp_sgt, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_CMP_UGT:HighLevelILCmp_ugt, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_TEST_BIT:HighLevelILTest_bit, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_BOOL_TO_INT:HighLevelILBool_to_int, # ("src", "expr"), + HighLevelILOperation.HLIL_ADD_OVERFLOW:HighLevelILAdd_overflow, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_SYSCALL:HighLevelILSyscall, # ("params", "expr_list"), + HighLevelILOperation.HLIL_SYSCALL_SSA:HighLevelILSyscall_ssa, # ("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int"), + HighLevelILOperation.HLIL_TAILCALL:HighLevelILTailcall, # ("dest", "expr"), ("params", "expr_list"), + HighLevelILOperation.HLIL_BP:HighLevelILBp, # , + HighLevelILOperation.HLIL_TRAP:HighLevelILTrap, # ("vector", "int"), + HighLevelILOperation.HLIL_INTRINSIC:HighLevelILIntrinsic, # ("intrinsic", "intrinsic"), ("params", "expr_list"), + HighLevelILOperation.HLIL_INTRINSIC_SSA:HighLevelILIntrinsic_ssa, # ("intrinsic", "intrinsic"), ("params", "expr_list"), ("dest_memory", "int"), ("src_memory", "int"), + HighLevelILOperation.HLIL_UNDEF:HighLevelILUndef, # , + HighLevelILOperation.HLIL_UNIMPL:HighLevelILUnimpl, # , + HighLevelILOperation.HLIL_UNIMPL_MEM:HighLevelILUnimpl_mem, # ("src", "expr"), + HighLevelILOperation.HLIL_FADD:HighLevelILFadd, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FSUB:HighLevelILFsub, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FMUL:HighLevelILFmul, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FDIV:HighLevelILFdiv, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FSQRT:HighLevelILFsqrt, # ("src", "expr"), + HighLevelILOperation.HLIL_FNEG:HighLevelILFneg, # ("src", "expr"), + HighLevelILOperation.HLIL_FABS:HighLevelILFabs, # ("src", "expr"), + HighLevelILOperation.HLIL_FLOAT_TO_INT:HighLevelILFloat_to_int, # ("src", "expr"), + HighLevelILOperation.HLIL_INT_TO_FLOAT:HighLevelILInt_to_float, # ("src", "expr"), + HighLevelILOperation.HLIL_FLOAT_CONV:HighLevelILFloat_conv, # ("src", "expr"), + HighLevelILOperation.HLIL_ROUND_TO_INT:HighLevelILRound_to_int, # ("src", "expr"), + HighLevelILOperation.HLIL_FLOOR:HighLevelILFloor, # ("src", "expr"), + HighLevelILOperation.HLIL_CEIL:HighLevelILCeil, # ("src", "expr"), + HighLevelILOperation.HLIL_FTRUNC:HighLevelILFtrunc, # ("src", "expr"), + HighLevelILOperation.HLIL_FCMP_E:HighLevelILFcmp_e, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_NE:HighLevelILFcmp_ne, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_LT:HighLevelILFcmp_lt, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_LE:HighLevelILFcmp_le, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_GE:HighLevelILFcmp_ge, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_GT:HighLevelILFcmp_gt, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_O:HighLevelILFcmp_o, # ("left", "expr"), ("right", "expr"), + HighLevelILOperation.HLIL_FCMP_UO:HighLevelILFcmp_uo, # ("left", "expr"), ("right", "expr"), +} class HighLevelILExpr: """ @@ -643,7 +2091,6 @@ class HighLevelILExpr: return self._index - class HighLevelILFunction: """ ``class HighLevelILFunction`` contains the a HighLevelILInstruction object that makes up the abstract syntax tree of @@ -701,19 +2148,16 @@ class HighLevelILFunction: def __len__(self): return int(core.BNGetHighLevelILInstructionCount(self.handle)) - def __getitem__(self, i:Union[HighLevelILExpr, HighLevelILInstruction, int]) -> HighLevelILInstruction: + def __getitem__(self, i:Union[HighLevelILExpr, int]) -> HighLevelILInstruction: if isinstance(i, slice) or isinstance(i, tuple): raise IndexError("expected integer instruction index") if isinstance(i, HighLevelILExpr): - return HighLevelILInstruction(self, i.index) - # for backwards compatibility - if isinstance(i, HighLevelILInstruction): - return i + return HighLevelILInstruction.create(self, i.index) if i < -len(self) or i >= len(self): raise IndexError("index out of range") if i < 0: i = len(self) + i - return HighLevelILInstruction(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False, + return HighLevelILInstruction.create(self, core.BNGetHighLevelILIndexForInstruction(self.handle, i), False, InstructionIndex(i)) def __setitem__(self, i, j): @@ -757,7 +2201,7 @@ class HighLevelILFunction: expr_index = core.BNGetHighLevelILRootExpr(self.handle) if expr_index >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction(self, expr_index) + return HighLevelILInstruction.create(self, expr_index) @root.setter def root(self, value:HighLevelILInstruction) -> None: @@ -838,13 +2282,13 @@ class HighLevelILFunction: result = core.BNGetHighLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction(self, result) + return HighLevelILInstruction.create(self, result) def get_ssa_memory_definition(self, version:int) -> Optional[HighLevelILInstruction]: result = core.BNGetHighLevelILSSAMemoryDefinition(self.handle, version) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction(self, result) + return HighLevelILInstruction.create(self, result) def get_ssa_var_uses(self, ssa_var:'mediumlevelil.SSAVariable') -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() @@ -853,7 +2297,7 @@ class HighLevelILFunction: assert instrs is not None, "core.BNGetHighLevelILSSAVarUses returned None" result = [] for i in range(0, count.value): - result.append(HighLevelILInstruction(self, instrs[i])) + result.append(HighLevelILInstruction.create(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result @@ -863,7 +2307,7 @@ class HighLevelILFunction: assert instrs is not None, "core.BNGetHighLevelILSSAMemoryUses returned None" result = [] for i in range(0, count.value): - result.append(HighLevelILInstruction(self, instrs[i])) + result.append(HighLevelILInstruction.create(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result @@ -885,7 +2329,7 @@ class HighLevelILFunction: assert instrs is not None, "core.BNGetHighLevelILVariableDefinitions returned None" result = [] for i in range(0, count.value): - result.append(HighLevelILInstruction(self, instrs[i])) + result.append(HighLevelILInstruction.create(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result @@ -896,7 +2340,7 @@ class HighLevelILFunction: assert instrs is not None, "core.BNGetHighLevelILVariableUses returned None" result = [] for i in range(0, count.value): - result.append(HighLevelILInstruction(self, instrs[i])) + result.append(HighLevelILInstruction.create(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result @@ -1029,7 +2473,7 @@ class HighLevelILFunction: result = core.BNGetHighLevelILExprIndexForLabel(self.handle, label_idx) if result >= core.BNGetHighLevelILExprCount(self.handle): return None - return HighLevelILInstruction(self, result) + return HighLevelILInstruction.create(self, result) def get_label_uses(self, label_idx:int) -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() @@ -1037,7 +2481,7 @@ class HighLevelILFunction: assert uses is not None, "core.BNGetHighLevelILUsesForLabel returned None" result = [] for i in range(0, count.value): - result.append(HighLevelILInstruction(self, uses[i])) + result.append(HighLevelILInstruction.create(self, uses[i])) core.BNFreeILInstructionList(uses) return result diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 093dd212..21b12909 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -21,11 +21,11 @@ import ctypes from enum import Flag import struct -from typing import Generator, List, Optional, Any, Mapping, Union, Tuple, NewType +from typing import Generator, List, Optional, Mapping, Union, Tuple, NewType from dataclasses import dataclass # Binary Ninja components -from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType, DataFlowQueryOption, FunctionGraphType +from .enums import LowLevelILOperation, LowLevelILFlagCondition, DataFlowQueryOption, FunctionGraphType from . import _binaryninjacore as core from . import basicblock #required for LowLevelILBasicBlock from . import function @@ -41,11 +41,11 @@ ExpressionIndex = NewType('ExpressionIndex', int) InstructionIndex = NewType('InstructionIndex', int) Index = Union[ExpressionIndex, InstructionIndex] TokenList = List['function.InstructionTextToken'] -InstructionOrExpression = Union['LowLevelILInstruction', 'LowLevelILExpr', Index] +InstructionOrExpression = Union['LowLevelILInstruction', Index] ILRegisterType = Union[str, 'ILRegister', int] LLILInstructionsType = Generator['LowLevelILInstruction', None, None] LLILBasicBlocksType = Generator['LowLevelILBasicBlock', None, None] - +OperandsType = Tuple[ExpressionIndex, ExpressionIndex, ExpressionIndex, ExpressionIndex] class LowLevelILLabel: def __init__(self, handle:core.BNLowLevelILLabel=None): @@ -87,7 +87,7 @@ class ILRegister: return (self.index & 0x80000000) != 0 @property - def name(self) -> architecture.RegisterName: + def name(self) -> 'architecture.RegisterName': if self.temp: return architecture.RegisterName(f"temp{self.index & 0x7fffffff}") else: @@ -251,9 +251,50 @@ class LowLevelILOperationAndSize: def __repr__(self): if self.size == 0: return f"<{self.operation.name}>" - return "<{self.operation.name} {self.size}>" + return f"<{self.operation.name} {self.size}>" + +LowLevelILOperandType = Union[ + LowLevelILOperationAndSize, + ILRegister, + ILFlag, + ILIntrinsic, + ILRegisterStack, + int, + Mapping[int, int], + float, + 'LowLevelILInstruction', + Mapping['architecture.RegisterStackName', int], + SSAFlag, + SSARegister, + SSARegisterStack, + ILSemanticFlagClass, + ILSemanticFlagGroup, + LowLevelILFlagCondition, + List[int], + List['LowLevelILInstruction'], + List[Union[ILFlag, ILRegister]], + List[SSARegister], + List[SSARegisterStack], + List[SSAFlag], + List[SSARegisterOrFlag], +] + +@dataclass(frozen=True) +class CoreLowLevelILInstruction: + operation:LowLevelILOperation + size:int + flags:int + source_operand:ExpressionIndex + operands:OperandsType + address:int + + @classmethod + def from_BNLowLevelILInstruction(cls, instr:core.BNLowLevelILInstruction) -> 'CoreLowLevelILInstruction': + operands:OperandsType = tuple([ExpressionIndex(instr.operands[i]) for i in range(4)]) # type: ignore + return cls(LowLevelILOperation(instr.operation), instr.size, instr.flags, instr.sourceOperand, operands, instr.address) +@dataclass(frozen=True) class LowLevelILInstruction: """ ``class LowLevelILInstruction`` Low Level Intermediate Language Instructions are infinite length tree-based @@ -261,322 +302,19 @@ class LowLevelILInstruction: Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. LLIL ``eax = 0``). """ - ILOperations = { - 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_EXTERN_PTR: [("constant", "int"), ("offset", "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")], - LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - LowLevelILOperation.LLIL_SUB: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - LowLevelILOperation.LLIL_AND: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_OR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_XOR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_LSL: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_LSR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_ASR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_ROL: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - LowLevelILOperation.LLIL_ROR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - LowLevelILOperation.LLIL_MUL: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVU: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVU_DP: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVS: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MODU: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MODU_DP: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_MODS: [("left", "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")], - LowLevelILOperation.LLIL_ZX: [("src", "expr")], - LowLevelILOperation.LLIL_LOW_PART: [("src", "expr")], - LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], - LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "target_map")], - LowLevelILOperation.LLIL_CALL: [("dest", "expr")], - LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")], - LowLevelILOperation.LLIL_TAILCALL: [("dest", "expr")], - 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"), ("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")], - LowLevelILOperation.LLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], - 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")], - LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], - LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], - LowLevelILOperation.LLIL_TAILCALL_SSA: [("output", "expr"), ("dest", "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: [("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")] - } - - def __init__(self, func:'LowLevelILFunction', expr_index:ExpressionIndex, instr_index:InstructionIndex=None): - instr = core.BNGetLowLevelILByIndex(func.handle, expr_index) - if func.arch is None: - raise Exception("Attempting to create a LowLevelILInstruction with function that doesn't have an architecture.") - self._function = func - self._expr_index = expr_index - self._instr_index = instr_index - self._operation = LowLevelILOperation(instr.operation) - self._size = instr.size - self._address = instr.address - self._source_operand = instr.sourceOperand - if instr.flags == 0: - self._flags = None - else: - self._flags = func.arch.get_flag_write_type_name(instr.flags) - if self._source_operand == 0xffffffff: - self._source_operand = None - operands = LowLevelILInstruction.ILOperations[instr.operation] - self._operands = [] - i = 0 + function:'LowLevelILFunction' + expr_index:ExpressionIndex + instr:CoreLowLevelILInstruction + instr_index:Optional[InstructionIndex] + operand_names = tuple() - for operand in operands: - name, operand_type = operand - value:Optional[Any] = None - if operand_type == "int": - value = instr.operands[i] - assert isinstance(value, int) - value = (value & ((1 << 63) - 1)) - (value & (1 << 63)) - 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.__dict__['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": - count = ctypes.c_ulonglong() - operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(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) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = {} - for j in range(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) - elif operand_type == "target_map": - count = ctypes.c_ulonglong() - operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) - assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" - i += 1 - value = {} - for j in range(count.value // 2): - key = operand_list[j * 2] - target = operand_list[(j * 2) + 1] - value[key] = target - core.BNLowLevelILFreeOperandList(operand_list) - self._operands.append(value) - self.__dict__[name] = value - i += 1 + @classmethod + def create(cls, func:'LowLevelILFunction', expr_index:ExpressionIndex, instr_index:Optional[InstructionIndex]=None) -> 'LowLevelILInstruction': + assert func.arch is not None, "Attempted to create IL instruction with function missing an Architecture" + inst = core.BNGetLowLevelILByIndex(func.handle, expr_index) + assert inst is not None, "core.BNGetLowLevelILByIndex returned None" + core_inst = CoreLowLevelILInstruction.from_BNLowLevelILInstruction(inst) + return ILInstruction[core_inst.operation](func, expr_index, core_inst, instr_index) # type: ignore def __str__(self): tokens = self.tokens @@ -593,7 +331,7 @@ class LowLevelILInstruction: def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index == other.expr_index + return self.function == other.function and self.expr_index == other.expr_index def __ne__(self, other): if not isinstance(other, self.__class__): @@ -603,39 +341,51 @@ class LowLevelILInstruction: def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index < other.expr_index + return self.function == other.function and self.expr_index < other.expr_index def __le__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index <= other.expr_index + return self.function == other.function and self.expr_index <= other.expr_index def __gt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index > other.expr_index + return self.function == other.function and self.expr_index > other.expr_index def __ge__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index >= other.expr_index + return self.function == other.function and self.expr_index >= other.expr_index def __hash__(self): - return hash((self._function, self.expr_index)) + return hash((self.function, self.expr_index)) + + @property + def address(self) -> int: + return self.instr.address + + @property + def operation(self) -> LowLevelILOperation: + return self.instr.operation + + @property + def source_operand(self) -> Optional[ExpressionIndex]: + return self.instr.source_operand @property def tokens(self) -> Optional[TokenList]: """LLIL tokens (read-only)""" count = ctypes.c_ulonglong() - assert self._function.arch is not None + assert self.function.arch is not None, f"type(self.function): {type(self.function)} " tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if (self._instr_index is not None) and (self._function.source_function is not None): - if not core.BNGetLowLevelILInstructionText(self._function.handle, self._function.source_function.handle, - self._function.arch.handle, self._instr_index, tokens, count): + if (self.instr_index is not None) and (self.function.source_function is not None): + if not core.BNGetLowLevelILInstructionText(self.function.handle, self.function.source_function.handle, + self.function.arch.handle, self.instr_index, tokens, count): return None else: # TODO: Special case LLIL_CALL_OUTPUT_SSA - if not core.BNGetLowLevelILExprText(self._function.handle, self._function.arch.handle, + if not core.BNGetLowLevelILExprText(self.function.handle, self.function.arch.handle, self.expr_index, tokens, count): return None result = function.InstructionTextToken._from_core_struct(tokens, count.value) @@ -645,39 +395,39 @@ class LowLevelILInstruction: @property def il_basic_block(self) -> 'LowLevelILBasicBlock': """IL basic block object containing this expression (read-only) (only available on finalized functions)""" - assert self._function.source_function is not None - view = self._function.source_function.view - core_block = core.BNGetLowLevelILBasicBlockForInstruction(self._function.handle, self._insstr_index) + assert self.function.source_function is not None + view = self.function.source_function.view + core_block = core.BNGetLowLevelILBasicBlockForInstruction(self.function.handle, self.instr_index) assert core_block is not None, "BNGetLowLevelILBasicBlockForInstruction returned None" - return LowLevelILBasicBlock(view, core_block, self._function) + return LowLevelILBasicBlock(view, core_block, self.function) @property def ssa_form(self) -> 'LowLevelILInstruction': """SSA form of expression (read-only)""" - ssa_func = self._function.ssa_form + ssa_func = self.function.ssa_form assert ssa_func is not None - return LowLevelILInstruction(ssa_func, - core.BNGetLowLevelILSSAExprIndex(self._function.handle, self.expr_index), - core.BNGetLowLevelILSSAInstructionIndex(self._function.handle, self._instr_index) if self._instr_index is not None else None) + return LowLevelILInstruction.create(ssa_func, + core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index), + core.BNGetLowLevelILSSAInstructionIndex(self.function.handle, self.instr_index) if self.instr_index is not None else None) @property def non_ssa_form(self) -> 'LowLevelILInstruction': """Non-SSA form of expression (read-only)""" - non_ssa_function = self._function.non_ssa_form + non_ssa_function = self.function.non_ssa_form assert non_ssa_function is not None - return LowLevelILInstruction(non_ssa_function, - core.BNGetLowLevelILNonSSAExprIndex(self._function.handle, self.expr_index), - core.BNGetLowLevelILNonSSAInstructionIndex(self._function.handle, self._instr_index) if self._instr_index is not None else None) + return LowLevelILInstruction.create(non_ssa_function, + core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index), + core.BNGetLowLevelILNonSSAInstructionIndex(self.function.handle, self.instr_index) if self.instr_index is not None else None) @property def medium_level_il(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: """Gets the medium level IL expression corresponding to this expression (may be None for eliminated instructions)""" - expr = self._function.get_medium_level_il_expr_index(self.expr_index) + expr = self.function.get_medium_level_il_expr_index(self.expr_index) if expr is None: return None - mlil_func = self._function.medium_level_il - assert mlil_func is not None, "self._function.medium_level_il is None" - return mediumlevelil.MediumLevelILInstruction(mlil_func, expr) + mlil_func = self.function.medium_level_il + assert mlil_func is not None, "self.function.medium_level_il is None" + return mediumlevelil.MediumLevelILInstruction.create(mlil_func, expr) @property def mlil(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: @@ -686,17 +436,17 @@ class LowLevelILInstruction: @property def mlils(self) -> List['mediumlevelil.MediumLevelILInstruction']: result = [] - for expr in self._function.get_medium_level_il_expr_indexes(self.expr_index): - result.append(mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il, expr)) + for expr in self.function.get_medium_level_il_expr_indexes(self.expr_index): + result.append(mediumlevelil.MediumLevelILInstruction.create(self.function.medium_level_il, expr)) return result @property def mapped_medium_level_il(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: """Gets the mapped medium level IL expression corresponding to this expression""" - expr = self._function.get_mapped_medium_level_il_expr_index(self.expr_index) + expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index) if expr is None: return None - return mediumlevelil.MediumLevelILInstruction(self._function.mapped_medium_level_il, expr) + return mediumlevelil.MediumLevelILInstruction.create(self.function.mapped_medium_level_il, expr) @property def mmlil(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: @@ -718,46 +468,55 @@ class LowLevelILInstruction: result = set() for mlil_expr in self.mlils: for hlil_expr in mlil_expr.hlils: - result.add(hlil_expr) + try: + result.add(hlil_expr) + except: + assert False, f"mlil_expr.hlils returned list of lists: {hlil_expr} {type(hlil_expr)}" return list(result) @property def value(self) -> 'variable.RegisterValue': """Value of expression if constant or a known value (read-only)""" - value = core.BNGetLowLevelILExprValue(self._function.handle, self.expr_index) - return variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) + return variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) @property def possible_values(self) -> 'variable.PossibleValueSet': """Possible values of expression using path-sensitive static data flow analysis (read-only)""" - value = core.BNGetLowLevelILPossibleExprValues(self._function.handle, self.expr_index, None, 0) - result = variable.PossibleValueSet(self._function.arch, value) + value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index, None, 0) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @property - def prefix_operands(self) -> List[Any]: + def operands(self) -> Generator[LowLevelILOperandType, None, None]: + for operand_name in self.operand_names: + assert hasattr(self, operand_name), f"No operand '{operand_name}' for instruction {repr(self)}({self.operation})" + yield self.__getattribute__(operand_name) + + @property + def prefix_operands(self) -> List[LowLevelILOperandType]: """All operands in the expression tree in prefix order""" - # TODO: There is probably a much better type hint we can provide here - result = [LowLevelILOperationAndSize(self._operation, self._size)] - for operand in self._operands: + result:List[LowLevelILOperandType] = [LowLevelILOperationAndSize(self.instr.operation, self.instr.size)] + for operand in self.operands: if isinstance(operand, LowLevelILInstruction): - result += operand.prefix_operands + assert id(self) != id(operand), f"circular reference {operand}({repr(operand)}) is {self}({repr(self)})" + result.extend(operand.prefix_operands) else: result.append(operand) return result @property - def postfix_operands(self) -> List[Any]: + def postfix_operands(self) -> List[LowLevelILOperandType]: """All operands in the expression tree in postfix order""" - # TODO: There is probably a much better type hint we can provide here - result = [] - for operand in self._operands: + result:List[LowLevelILOperandType] = [] + for operand in self.operands: if isinstance(operand, LowLevelILInstruction): - result += operand.postfix_operands + assert id(self) != id(operand), f"circular reference {operand}({repr(operand)}) is {self}({repr(self)})" + result.extend(operand.postfix_operands) else: result.append(operand) - result.append(LowLevelILOperationAndSize(self._operation, self._size)) + result.append(LowLevelILOperationAndSize(self.instr.operation, self.instr.size)) return result def get_possible_values(self, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: @@ -766,109 +525,109 @@ class LowLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleExprValues(self._function.handle, self.expr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, len(options)) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_reg_value(self, reg:'architecture.RegisterType') -> variable.RegisterValue: - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_reg_value on function with Architecture set to None") - reg = self._function.arch.get_reg_index(reg) - value = core.BNGetLowLevelILRegisterValueAtInstruction(self._function.handle, reg, self._instr_index) - return variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + reg = self.function.arch.get_reg_index(reg) + value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + return variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) def get_reg_value_after(self, reg:'architecture.RegisterType') -> variable.RegisterValue: - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_reg_value_after on function with Architecture set to None") - reg = self._function.arch.get_reg_index(reg) - value = core.BNGetLowLevelILRegisterValueAfterInstruction(self._function.handle, reg, self._instr_index) - return variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + reg = self.function.arch.get_reg_index(reg) + value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + return variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) def get_possible_reg_values(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_possible_reg_values on function with Architecture set to None") - reg = self._function.arch.get_reg_index(reg) + reg = self.function.arch.get_reg_index(reg) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self._function.handle, reg, self._instr_index, + value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_possible_reg_values_after on function with Architecture set to None") - reg = self._function.arch.get_reg_index(reg) + reg = self.function.arch.get_reg_index(reg) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self._function.handle, reg, self._instr_index, + value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag:'architecture.FlagType') -> 'variable.RegisterValue': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_flag_value on function with Architecture set to None") - flag = self._function.arch.get_flag_index(flag) - value = core.BNGetLowLevelILFlagValueAtInstruction(self._function.handle, flag, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + flag = self.function.arch.get_flag_index(flag) + value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_flag_value_after(self, flag:'architecture.FlagType') -> 'variable.RegisterValue': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_flag_value_after on function with Architecture set to None") - flag = self._function.arch.get_flag_index(flag) - value = core.BNGetLowLevelILFlagValueAfterInstruction(self._function.handle, flag, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + flag = self.function.arch.get_flag_index(flag) + value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_possible_flag_values(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_possible_flag_values on function with Architecture set to None") - flag = self._function.arch.get_flag_index(flag) + flag = self.function.arch.get_flag_index(flag) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self._function.handle, flag, self._instr_index, + value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - if self._function.arch is None: + if self.function.arch is None: raise Exception("Can not call get_possible_flag_values_after on function with Architecture set to None") - flag = self._function.arch.get_flag_index(flag) + flag = self.function.arch.get_flag_index(flag) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self._function.handle, flag, self._instr_index, + value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset:int, size:int) -> 'variable.RegisterValue': - value = core.BNGetLowLevelILStackContentsAtInstruction(self._function.handle, offset, size, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_stack_contents_after(self, offset:int, size:int) -> 'variable.RegisterValue': - value = core.BNGetLowLevelILStackContentsAfterInstruction(self._function.handle, offset, size, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_possible_stack_contents(self, offset:int, size:int, options:List[DataFlowQueryOption]=[]) -> variable.PossibleValueSet: @@ -877,9 +636,9 @@ class LowLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self._function.handle, offset, size, self._instr_index, + value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -889,68 +648,1747 @@ class LowLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self._function.handle, offset, size, self._instr_index, + value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @property - def function(self) -> 'LowLevelILFunction': - return self._function + def flags(self) -> Optional['architecture.FlagWriteTypeName']: + return self.function.arch.get_flag_write_type_name(architecture.FlagWriteTypeIndex(self.instr.flags)) + + def get_reg(self, operand_index:int) -> ILRegister: + return ILRegister(self.function.arch, architecture.RegisterIndex(self.instr.operands[operand_index])) + + def get_flag(self, operand_index:int) -> ILFlag: + return ILFlag(self.function.arch, architecture.FlagIndex(self.instr.operands[operand_index])) + + def get_intrinsic(self, operand_index:int) -> ILIntrinsic: + return ILIntrinsic(self.function.arch, architecture.IntrinsicIndex(self.instr.operands[operand_index])) + + def get_reg_stack(self, operand_index:int) -> ILRegisterStack: + return ILRegisterStack(self.function.arch, architecture.RegisterStackIndex(self.instr.operands[operand_index])) + + def get_int(self, operand_index:int) -> int: + return (self.instr.operands[operand_index] & ((1 << 63) - 1)) - (self.instr.operands[operand_index] & (1 << 63)) + + def get_target_map(self, operand_index:int) -> Mapping[int, int]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + try: + value:Mapping[int, int] = {} + for j in range(count.value // 2): + key = operand_list[j * 2] + target = operand_list[(j * 2) + 1] + value[key] = target + return value + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_float(self, operand_index:int) -> float: + if self.instr.size == 4: + return struct.unpack("f", struct.pack("I", self.instr.operands[operand_index] & 0xffffffff))[0] + elif self.instr.size == 8: + return struct.unpack("d", struct.pack("Q", self.instr.operands[operand_index]))[0] + else: + return float(self.instr.operands[operand_index]) + + def get_expr(self, operand_index:int) -> 'LowLevelILInstruction': + return LowLevelILInstruction.create(self.function, self.instr.operands[operand_index], self.instr_index) + + def get_reg_stack_adjust(self, operand_index:int) -> Mapping['architecture.RegisterStackName', int]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result:Mapping['architecture.RegisterStackName', int] = {} + try: + for j in range(count.value // 2): + reg_stack = operand_list[j * 2] + adjust = operand_list[(j * 2) + 1] + if adjust & 0x80000000: + adjust |= ~0x80000000 + result[self.function.arch.get_reg_stack_name(reg_stack)] = adjust + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_flag_ssa(self, operand_index1:int, operand_index2:int) -> SSAFlag: + return SSAFlag(ILFlag(self.function.arch, architecture.FlagIndex(self.instr.operands[operand_index1])), + self.instr.operands[operand_index2]) + + def get_reg_ssa(self, operand_index1:int, operand_index2:int) -> SSARegister: + return SSARegister(ILRegister(self.function.arch, + architecture.RegisterIndex(self.instr.operands[operand_index1])), + self.instr.operands[operand_index2]) + + def get_reg_stack_ssa(self, operand_index1:int, operand_index2:int) -> SSARegisterStack: + reg_stack = ILRegisterStack(self.function.arch, + architecture.RegisterStackIndex(self.instr.operands[operand_index1])) + return SSARegisterStack(reg_stack, self.instr.operands[operand_index2]) + + def get_sem_class(self, operand_index:int) -> ILSemanticFlagClass: + return ILSemanticFlagClass(self.function.arch, + architecture.SemanticClassIndex(self.instr.operands[operand_index])) + + def get_sem_group(self, operand_index:int) -> ILSemanticFlagGroup: + return ILSemanticFlagGroup(self.function.arch, + architecture.SemanticGroupIndex(self.instr.operands[operand_index])) + + def get_cond(self, operand_index:int) -> LowLevelILFlagCondition: + return LowLevelILFlagCondition(self.instr.operands[operand_index]) + + def get_int_list(self, operand_index:int) -> List[int]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result:List[int] = [] + try: + for j in range(count.value): + result.append(operand_list[j]) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_expr_list(self, operand_index:int) -> List['LowLevelILInstruction']: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result = [] + try: + for j in range(count.value): + result.append(LowLevelILInstruction.create(self.function, operand_list[j], None)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_reg_or_flag_list(self, operand_index:int) -> List[Union[ILFlag, ILRegister]]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + + result:List[Union[ILFlag, ILRegister]] = [] + try: + for j in range(count.value): + if (operand_list[j] & (1 << 32)) != 0: + result.append(ILFlag(self.function.arch, operand_list[j] & 0xffffffff)) + else: + result.append(ILRegister(self.function.arch, operand_list[j] & 0xffffffff)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_reg_ssa_list(self, operand_index:int) -> List[SSARegister]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result = [] + try: + for j in range(count.value // 2): + reg = operand_list[j * 2] + reg_version = operand_list[(j * 2) + 1] + result.append(SSARegister(ILRegister(self.function.arch, reg), reg_version)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_reg_stack_ssa_list(self, operand_index:int) -> List[SSARegisterStack]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result:List[SSARegisterStack] = [] + try: + for j in range(count.value // 2): + reg_stack = operand_list[j * 2] + reg_version = operand_list[(j * 2) + 1] + result.append(SSARegisterStack(ILRegisterStack(self.function.arch, reg_stack), reg_version)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_flag_ssa_list(self, operand_index:int) -> List[SSAFlag]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + try: + result:List[SSAFlag] = [] + for j in range(count.value // 2): + flag = operand_list[j * 2] + flag_version = operand_list[(j * 2) + 1] + result.append(SSAFlag(ILFlag(self.function.arch, flag), flag_version)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + def get_reg_or_flag_ssa_list(self, operand_index:int) -> List[SSARegisterOrFlag]: + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNLowLevelILGetOperandList returned None" + result:List[SSARegisterOrFlag] = [] + try: + for j in range(count.value // 2): + if (operand_list[j * 2] & (1 << 32)) != 0: + reg_or_flag = ILFlag(self.function.arch, operand_list[j * 2] & 0xffffffff) + else: + reg_or_flag = ILRegister(self.function.arch, operand_list[j * 2] & 0xffffffff) + reg_version = operand_list[(j * 2) + 1] + result.append(SSARegisterOrFlag(reg_or_flag, reg_version)) + return result + finally: + core.BNLowLevelILFreeOperandList(operand_list) + + +@dataclass(frozen=True, repr=False) +class Terminal(LowLevelILInstruction): + """This class indicates that the instruction ends a BasicBlock""" + pass + +@dataclass(frozen=True, repr=False) +class BinaryOperation(LowLevelILInstruction): + operand_names = tuple(['left', 'right']) @property - def expr_index(self) -> ExpressionIndex: - return self._expr_index + def left(self) -> LowLevelILInstruction: + return self.get_expr(0) @property - def instr_index(self) -> Optional[InstructionIndex]: - return self._instr_index + def right(self) -> LowLevelILInstruction: + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class UnaryOperation(LowLevelILInstruction): + operand_names = tuple(['src']) @property - def operation(self) -> LowLevelILOperation: - return self._operation + def src(self) -> LowLevelILInstruction: + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class Arithmetic(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Signed(LowLevelILInstruction): + """The operation is a signed operation""" + pass + + +@dataclass(frozen=True, repr=False) +class Carry(LowLevelILInstruction): + """Arithmetic with carry operation""" + pass + + +@dataclass(frozen=True, repr=False) +class Comparison(BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class Constant(LowLevelILInstruction): + operand_names = tuple(['constant']) + + def __int__(self): + return self.constant + + def __bool__(self): + return self.constant != 0 + + def __eq__(self, other): + return int(self) == int(other) + + def __ne__(self, other): + return int(self) != int(other) + + def __lt__(self, other): + return int(self) < int(other) + + def __gt__(self, other): + return int(self) > int(other) + + def __le__(self, other): + return int(self) <= int(other) + + def __ge__(self, other): + return int(self) >= int(other) @property - def size(self) -> int: - return self._size + def constant(self) -> int: + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class FloatingPoint(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class ControlFlow(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Memory(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Return(Terminal): + pass + + +@dataclass(frozen=True, repr=False) +class RegisterStack(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class SSA(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class StackOperation(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class SetReg(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class DoublePrecision(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Store(Memory): + pass + + +@dataclass(frozen=True, repr=False) +class Load(Memory): + pass + + +@dataclass(frozen=True, repr=False) +class Call(LowLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILNop(LowLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILPop(StackOperation): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILNoret(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILSyscall(Call): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILBp(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILUndef(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILUnimpl(LowLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class LowLevelILNeg(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILNot(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILSx(UnaryOperation, Arithmetic): + pass + +@dataclass(frozen=True, repr=False) +class LowLevelILZx(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILLow_part(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILJump(ControlFlow, Terminal): + operand_names = tuple(["dest"]) @property - def address(self) -> int: - return self._address + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall(Call): + operand_names = tuple(["dest"]) @property - def source_operand(self) -> Optional[ExpressionIndex]: - return self._source_operand + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILTailcall(Call): + operand_names = tuple(["dest"]) @property - def flags(self) -> Optional[str]: - return self._flags + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILRet(Return): + operand_names = tuple(["dest"]) @property - def operands(self) -> List[Any]: - return self._operands + def dest(self): + return self.get_expr(0) -@dataclass(frozen=True) -class LowLevelILExpr: - """ - ``class LowLevelILExpr`` hold the index of IL Expressions. +@dataclass(frozen=True, repr=False) +class LowLevelILUnimpl_mem(Memory): + operand_names = tuple(["src"]) - .. note:: This class shouldn't be instantiated directly. Rather the helper members of LowLevelILFunction should be \ - used instead. - """ - index:ExpressionIndex + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFsqrt(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFneg(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFabs(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFloat_to_int(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILInt_to_float(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFloat_conv(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILRound_to_int(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFloor(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCeil(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFtrunc(FloatingPoint, Arithmetic): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILLoad(Memory): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILPush(StackOperation): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg(LowLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_reg(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_pop(RegisterStack): + operand_names = tuple(["stack"]) + + @property + def stack(self): + return self.get_reg_stack(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_free_reg(RegisterStack): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_reg(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILConst(Constant): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILConst_ptr(Constant): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFloat_const(Constant, FloatingPoint): + + @property + def constant(self) -> float: + return self.get_float(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag(LowLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_flag(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILGoto(Terminal): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_group(LowLevelILInstruction): + operand_names = tuple(["semantic_group"]) + + @property + def semantic_group(self): + return self.get_sem_group(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILBool_to_int(LowLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILTrap(Terminal): + operand_names = tuple(["vector"]) + + @property + def vector(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_split_dest_ssa(SSA): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_reg_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_dest_ssa(RegisterStack, SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_reg_stack_ssa(0, 1) + + @property + def src(self): + return self.get_reg_stack_ssa(0, 2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_ssa(SSA): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_reg_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_ssa(SSA): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_flag_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall_param(SSA): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr_list(0) + + +@dataclass(frozen=True, repr=False) +class LowLevelILMem_phi(Memory, SSA): + operand_names = tuple(["dest_memory", "src_memory"]) + + @property + def dest_memory(self): + return self.get_int(0) + + @property + def src_memory(self): + return self.get_int_list(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg(SetReg): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_reg(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_push(RegisterStack): + operand_names = tuple(["stack", "src"]) + + @property + def stack(self): + return self.get_reg_stack(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_flag(LowLevelILInstruction): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_flag(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILStore(Memory): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_split(LowLevelILInstruction): + operand_names = tuple(["hi", "lo"]) + + @property + def hi(self): + return self.get_reg(0) + + @property + def lo(self): + return self.get_reg(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_rel(RegisterStack): + operand_names = tuple(["stack", "src"]) + + @property + def stack(self): + return self.get_reg_stack(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_free_rel(RegisterStack): + operand_names = tuple(["stack", "dest"]) + + @property + def stack(self): + return self.get_reg_stack(0) + + @property + def dest(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILExtern_ptr(Constant): + operand_names = tuple(["constant", "offset"]) + + @property + def constant(self): + return self.get_int(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_bit(LowLevelILInstruction): + operand_names = tuple(["src", "bit"]) + + @property + def src(self): + return self.get_flag(0) + + @property + def bit(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILAdd(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILSub(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILAnd(BinaryOperation, Arithmetic): + pass - def __int__(self) -> int: - return self.index + +@dataclass(frozen=True, repr=False) +class LowLevelILOr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILXor(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILLsl(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILLsr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILAsr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILRol(BinaryOperation, Arithmetic): + pass + +@dataclass(frozen=True, repr=False) +class LowLevelILRor(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILMul(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILMulu_dp(BinaryOperation, DoublePrecision): + pass + +@dataclass(frozen=True, repr=False) +class LowLevelILMuls_dp(BinaryOperation, DoublePrecision): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILDivu(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILDivu_dp(BinaryOperation, DoublePrecision): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILDivs(BinaryOperation, Arithmetic, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILDivs_dp(BinaryOperation, DoublePrecision, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILModu(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILModu_dp(BinaryOperation, DoublePrecision): + pass + +@dataclass(frozen=True, repr=False) +class LowLevelILMods(BinaryOperation, Arithmetic, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILMods_dp(BinaryOperation, DoublePrecision, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_e(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_ne(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_slt(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_ult(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_sle(Comparison,Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_ule(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_sge(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_uge(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_sgt(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILCmp_ugt(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILTest_bit(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFadd(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFsub(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFmul(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFdiv(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_e(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_ne(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_lt(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_le(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_ge(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_gt(Comparison, FloatingPoint): + pass + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_o(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILFcmp_uo(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class LowLevelILJump_to(LowLevelILInstruction): + operand_names = tuple(["dest", "targets"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def targets(self): + return self.get_target_map(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_cond(LowLevelILInstruction): + operand_names = tuple(["condition", "semantic_class"]) + + @property + def condition(self): + return self.get_cond(0) + + @property + def semantic_class(self): + return self.get_sem_class(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILAdd_overflow(BinaryOperation, Arithmetic): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_ssa(SetReg, SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_reg_ssa(0, 1) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_ssa_partial(SetReg, SSA): + operand_names = tuple(["full_reg", "src"]) + + @property + def full_reg(self): + return self.get_reg_ssa(0, 1) + + @property + def src(self): + return self.get_reg(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_split_ssa(SetReg, SSA): + operand_names = tuple(["hi", "lo"]) + + @property + def hi(self): + return self.get_reg_ssa(0, 1) + + @property + def lo(self): + return self.get_reg_ssa(2, 3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_abs_ssa(RegisterStack, SSA): + operand_names = tuple(["stack", "src"]) + + @property + def stack(self): + return self.get_reg_stack_ssa(0, 1) + + @property + def src(self): + return self.get_reg(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_free_abs_ssa(RegisterStack): + operand_names = tuple(["stack", "dest"]) + + @property + def stack(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_reg(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_flag_ssa(SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_flag_ssa(0, 1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_bit_ssa(SSA): + operand_names = tuple(["src", "bit"]) + + @property + def src(self): + return self.get_flag_ssa(0, 1) + + @property + def bit(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall_output_ssa(SSA): + operand_names = tuple(["dest_memory", "dest"]) + + @property + def dest_memory(self): + return self.get_int(0) + + @property + def dest(self): + return self.get_reg_ssa_list(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall_stack_ssa(SSA): + operand_names = tuple(["src", "src_memory"]) + + @property + def src(self): + return self.get_reg_ssa(0, 1) + + @property + def src_memory(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILLoad_ssa(Load, SSA): + operand_names = tuple(["src", "src_memory"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def src_memory(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_phi(SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_reg_ssa(0, 1) + + @property + def src(self): + return self.get_reg_ssa_list(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_phi(RegisterStack, SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_reg_stack_ssa(0, 1) + + @property + def src(self): + return self.get_reg_stack_ssa_list(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILFlag_phi(SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_flag_ssa(0, 1) + + @property + def src(self): + return self.get_flag_ssa_list(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_split(SetReg): + operand_names = tuple(["hi", "lo", "src"]) + + @property + def hi(self): + return self.get_reg(0) + + @property + def lo(self): + return self.get_reg(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_stack_rel(RegisterStack): + operand_names = tuple(["stack", "dest", "src"]) + + @property + def stack(self): + return self.get_reg_stack(0) + + @property + def dest(self): + return self.get_expr(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSbb(Carry): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILAdc(Carry): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILRlc(Carry): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILRrc(Carry): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall_stack_adjust(Call): + operand_names = tuple(["dest", "stack_adjustment", "reg_stack_adjustments"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def stack_adjustment(self): + return self.get_int(1) + + @property + def reg_stack_adjustments(self): + return self.get_reg_stack_adjust(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILIf(Terminal): + operand_names = tuple(["condition", "true", "false"]) + + @property + def condition(self): + return self.get_expr(0) + + @property + def true(self): + return self.get_int(1) + + @property + def false(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILIntrinsic(LowLevelILInstruction): + operand_names = tuple(["output", "intrinsic", "param"]) + + @property + def output(self): + return self.get_reg_or_flag_list(0) + + @property + def intrinsic(self): + return self.get_intrinsic(2) + + @property + def param(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILIntrinsic_ssa(SSA): + operand_names = tuple(["output", "intrinsic", "param"]) + + @property + def output(self): + return self.get_reg_or_flag_ssa_list(0) + + @property + def intrinsic(self): + return self.get_intrinsic(2) + + @property + def param(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_ssa_partial(SetReg, SSA): + operand_names = tuple(["full_reg", "dest", "src"]) + + @property + def full_reg(self): + return self.get_reg_ssa(0, 1) + + @property + def dest(self): + return self.get_reg(2) + + @property + def src(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_split_ssa(SetReg, SSA): + operand_names = tuple(["hi", "lo", "src"]) + + @property + def hi(self): + return self.get_expr(0) + + @property + def lo(self): + return self.get_expr(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_stack_abs_ssa(RegisterStack, SSA): + operand_names = tuple(["stack", "dest", "src"]) + + @property + def stack(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_reg(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_rel_ssa(RegisterStack, SSA): + operand_names = tuple(["stack", "src", "top"]) + + @property + def stack(self): + return self.get_reg_stack_ssa(0, 1) + + @property + def src(self): + return self.get_expr(2) + + @property + def top(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILReg_stack_free_rel_ssa(RegisterStack, SSA): + operand_names = tuple(["stack", "dest", "top"]) + + @property + def stack(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_expr(1) + + @property + def top(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSyscall_ssa(Call, SSA): + operand_names = tuple(["output", "stack", "param"]) + + @property + def output(self): + return self.get_expr(0) + + @property + def stack(self): + return self.get_expr(1) + + @property + def param(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class LowLevelILSet_reg_stack_rel_ssa(RegisterStack, SSA): + operand_names = tuple(["stack", "dest", "top", "src"]) + + @property + def stack(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_expr(1) + + @property + def top(self): + return self.get_expr(2) + + @property + def src(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILCall_ssa(Call, SSA): + operand_names = tuple(["output", "dest", "stack", "param"]) + + @property + def output(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_expr(1) + + @property + def stack(self): + return self.get_expr(2) + + @property + def param(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILTailcall_ssa(Call, SSA, Terminal): + operand_names = tuple(["output", "dest", "stack", "param"]) + + @property + def output(self): + return self.get_expr(0) + + @property + def dest(self): + return self.get_expr(1) + + @property + def stack(self): + return self.get_expr(2) + + @property + def param(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class LowLevelILStore_ssa(Store, SSA): + operand_names = tuple(["dest", "dest_memory", "src_memory", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def dest_memory(self): + return self.get_int(1) + + @property + def src_memory(self): + return self.get_int(2) + + @property + def src(self): + return self.get_expr(3) + + + + + +ILInstruction:Mapping[LowLevelILOperation, LowLevelILInstruction] = { # type: ignore + LowLevelILOperation.LLIL_NOP: LowLevelILNop, # [], + LowLevelILOperation.LLIL_SET_REG: LowLevelILSet_reg, # [("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SPLIT: LowLevelILSet_reg_split, # [("hi", "reg"), ("lo", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_REL: LowLevelILSet_reg_stack_rel, # [("stack", "reg_stack"), ("dest", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_STACK_PUSH: LowLevelILReg_stack_push, # [("stack", "reg_stack"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_FLAG: LowLevelILSet_flag, # [("dest", "flag"), ("src", "expr")], + LowLevelILOperation.LLIL_LOAD: LowLevelILLoad, # [("src", "expr")], + LowLevelILOperation.LLIL_STORE: LowLevelILStore, # [("dest", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_PUSH: LowLevelILPush, # [("src", "expr")], + LowLevelILOperation.LLIL_POP: LowLevelILPop, # [], + LowLevelILOperation.LLIL_REG: LowLevelILReg, # [("src", "reg")], + LowLevelILOperation.LLIL_REG_SPLIT: LowLevelILReg_split, # [("hi", "reg"), ("lo", "reg")], + LowLevelILOperation.LLIL_REG_STACK_REL: LowLevelILReg_stack_rel, # [("stack", "reg_stack"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_STACK_POP: LowLevelILReg_stack_pop, # [("stack", "reg_stack")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REG: LowLevelILReg_stack_free_reg, # [("dest", "reg")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REL: LowLevelILReg_stack_free_rel, # [("stack", "reg_stack"), ("dest", "expr")], + LowLevelILOperation.LLIL_CONST: LowLevelILConst, # [("constant", "int")], + LowLevelILOperation.LLIL_CONST_PTR: LowLevelILConst_ptr, # [("constant", "int")], + LowLevelILOperation.LLIL_EXTERN_PTR: LowLevelILExtern_ptr, # [("constant", "int"), ("offset", "int")], + LowLevelILOperation.LLIL_FLOAT_CONST: LowLevelILFloat_const, # [("constant", "float")], + LowLevelILOperation.LLIL_FLAG: LowLevelILFlag, # [("src", "flag")], + LowLevelILOperation.LLIL_FLAG_BIT: LowLevelILFlag_bit, # [("src", "flag"), ("bit", "int")], + LowLevelILOperation.LLIL_ADD: LowLevelILAdd, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_ADC: LowLevelILAdc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + LowLevelILOperation.LLIL_SUB: LowLevelILSub, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_SBB: LowLevelILSbb, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + LowLevelILOperation.LLIL_AND: LowLevelILAnd, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_OR: LowLevelILOr, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_XOR: LowLevelILXor, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_LSL: LowLevelILLsl, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_LSR: LowLevelILLsr, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_ASR: LowLevelILAsr, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_ROL: LowLevelILRol, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RLC: LowLevelILRlc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + LowLevelILOperation.LLIL_ROR: LowLevelILRor, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RRC: LowLevelILRrc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + LowLevelILOperation.LLIL_MUL: LowLevelILMul, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MULU_DP: LowLevelILMulu_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MULS_DP: LowLevelILMuls_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVU: LowLevelILDivu, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVU_DP: LowLevelILDivu_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVS: LowLevelILDivs, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_DIVS_DP: LowLevelILDivs_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODU: LowLevelILModu, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODU_DP: LowLevelILModu_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODS: LowLevelILMods, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_MODS_DP: LowLevelILMods_dp, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_NEG: LowLevelILNeg, # [("src", "expr")], + LowLevelILOperation.LLIL_NOT: LowLevelILNot, # [("src", "expr")], + LowLevelILOperation.LLIL_SX: LowLevelILSx, # [("src", "expr")], + LowLevelILOperation.LLIL_ZX: LowLevelILZx, # [("src", "expr")], + LowLevelILOperation.LLIL_LOW_PART: LowLevelILLow_part, # [("src", "expr")], + LowLevelILOperation.LLIL_JUMP: LowLevelILJump, # [("dest", "expr")], + LowLevelILOperation.LLIL_JUMP_TO: LowLevelILJump_to, # [("dest", "expr"), ("targets", "target_map")], + LowLevelILOperation.LLIL_CALL: LowLevelILCall, # [("dest", "expr")], + LowLevelILOperation.LLIL_CALL_STACK_ADJUST: LowLevelILCall_stack_adjust, # [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")], + LowLevelILOperation.LLIL_TAILCALL: LowLevelILTailcall, # [("dest", "expr")], + LowLevelILOperation.LLIL_RET: LowLevelILRet, # [("dest", "expr")], + LowLevelILOperation.LLIL_NORET: LowLevelILNoret, # [], + LowLevelILOperation.LLIL_IF: LowLevelILIf, # [("condition", "expr"), ("true", "int"), ("false", "int")], + LowLevelILOperation.LLIL_GOTO: LowLevelILGoto, # [("dest", "int")], + LowLevelILOperation.LLIL_FLAG_COND: LowLevelILFlag_cond, # [("condition", "cond"), ("semantic_class", "sem_class")], + LowLevelILOperation.LLIL_FLAG_GROUP: LowLevelILFlag_group, # [("semantic_group", "sem_group")], + LowLevelILOperation.LLIL_CMP_E: LowLevelILCmp_e, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_NE: LowLevelILCmp_ne, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_SLT: LowLevelILCmp_slt, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_ULT: LowLevelILCmp_ult, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_SLE: LowLevelILCmp_sle, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_ULE: LowLevelILCmp_ule, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_SGE: LowLevelILCmp_sge, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_UGE: LowLevelILCmp_uge, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_SGT: LowLevelILCmp_sgt, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_CMP_UGT: LowLevelILCmp_ugt, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_TEST_BIT: LowLevelILTest_bit, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_BOOL_TO_INT: LowLevelILBool_to_int, # [("src", "expr")], + LowLevelILOperation.LLIL_ADD_OVERFLOW: LowLevelILAdd_overflow, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_SYSCALL: LowLevelILSyscall, # [], + LowLevelILOperation.LLIL_INTRINSIC: LowLevelILIntrinsic, # [("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")], + LowLevelILOperation.LLIL_INTRINSIC_SSA: LowLevelILIntrinsic_ssa, # [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")], + LowLevelILOperation.LLIL_BP: LowLevelILBp, # [], + LowLevelILOperation.LLIL_TRAP: LowLevelILTrap, # [("vector", "int")], + LowLevelILOperation.LLIL_UNDEF: LowLevelILUndef, # [], + LowLevelILOperation.LLIL_UNIMPL: LowLevelILUnimpl, # [], + LowLevelILOperation.LLIL_UNIMPL_MEM: LowLevelILUnimpl_mem, # [("src", "expr")], + LowLevelILOperation.LLIL_FADD: LowLevelILFadd, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FSUB: LowLevelILFsub, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FMUL: LowLevelILFmul, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FDIV: LowLevelILFdiv, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FSQRT: LowLevelILFsqrt, # [("src", "expr")], + LowLevelILOperation.LLIL_FNEG: LowLevelILFneg, # [("src", "expr")], + LowLevelILOperation.LLIL_FABS: LowLevelILFabs, # [("src", "expr")], + LowLevelILOperation.LLIL_FLOAT_TO_INT: LowLevelILFloat_to_int, # [("src", "expr")], + LowLevelILOperation.LLIL_INT_TO_FLOAT: LowLevelILInt_to_float, # [("src", "expr")], + LowLevelILOperation.LLIL_FLOAT_CONV: LowLevelILFloat_conv, # [("src", "expr")], + LowLevelILOperation.LLIL_ROUND_TO_INT: LowLevelILRound_to_int, # [("src", "expr")], + LowLevelILOperation.LLIL_FLOOR: LowLevelILFloor, # [("src", "expr")], + LowLevelILOperation.LLIL_CEIL: LowLevelILCeil, # [("src", "expr")], + LowLevelILOperation.LLIL_FTRUNC: LowLevelILFtrunc, # [("src", "expr")], + LowLevelILOperation.LLIL_FCMP_E: LowLevelILFcmp_e, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_NE: LowLevelILFcmp_ne, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_LT: LowLevelILFcmp_lt, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_LE: LowLevelILFcmp_le, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_GE: LowLevelILFcmp_ge, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_GT: LowLevelILFcmp_gt, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_O: LowLevelILFcmp_o, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_UO: LowLevelILFcmp_uo, # [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA: LowLevelILSet_reg_ssa, # [("dest", "reg_ssa"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: LowLevelILSet_reg_ssa_partial, # [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: LowLevelILSet_reg_split_ssa, # [("hi", "expr"), ("lo", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_REL_SSA: LowLevelILSet_reg_stack_rel_ssa, # [("stack", "expr"), ("dest", "expr"), ("top", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_STACK_ABS_SSA: LowLevelILSet_reg_stack_abs_ssa, # [("stack", "expr"), ("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: LowLevelILReg_split_dest_ssa, # [("dest", "reg_ssa")], + LowLevelILOperation.LLIL_REG_STACK_DEST_SSA: LowLevelILReg_stack_dest_ssa, # [("src", "reg_stack_ssa_dest_and_src")], + LowLevelILOperation.LLIL_REG_SSA: LowLevelILReg_ssa, # [("src", "reg_ssa")], + LowLevelILOperation.LLIL_REG_SSA_PARTIAL: LowLevelILReg_ssa_partial, # [("full_reg", "reg_ssa"), ("src", "reg")], + LowLevelILOperation.LLIL_REG_SPLIT_SSA: LowLevelILReg_split_ssa, # [("hi", "reg_ssa"), ("lo", "reg_ssa")], + LowLevelILOperation.LLIL_REG_STACK_REL_SSA: LowLevelILReg_stack_rel_ssa, # [("stack", "reg_stack_ssa"), ("src", "expr"), ("top", "expr")], + LowLevelILOperation.LLIL_REG_STACK_ABS_SSA: LowLevelILReg_stack_abs_ssa, # [("stack", "reg_stack_ssa"), ("src", "reg")], + LowLevelILOperation.LLIL_REG_STACK_FREE_REL_SSA: LowLevelILReg_stack_free_rel_ssa, # [("stack", "expr"), ("dest", "expr"), ("top", "expr")], + LowLevelILOperation.LLIL_REG_STACK_FREE_ABS_SSA: LowLevelILReg_stack_free_abs_ssa, # [("stack", "expr"), ("dest", "reg")], + LowLevelILOperation.LLIL_SET_FLAG_SSA: LowLevelILSet_flag_ssa, # [("dest", "flag_ssa"), ("src", "expr")], + LowLevelILOperation.LLIL_FLAG_SSA: LowLevelILFlag_ssa, # [("src", "flag_ssa")], + LowLevelILOperation.LLIL_FLAG_BIT_SSA: LowLevelILFlag_bit_ssa, # [("src", "flag_ssa"), ("bit", "int")], + LowLevelILOperation.LLIL_CALL_SSA: LowLevelILCall_ssa, # [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_SYSCALL_SSA: LowLevelILSyscall_ssa, # [("output", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_TAILCALL_SSA: LowLevelILTailcall_ssa, # [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: LowLevelILCall_output_ssa, # [("dest_memory", "int"), ("dest", "reg_ssa_list")], + LowLevelILOperation.LLIL_CALL_STACK_SSA: LowLevelILCall_stack_ssa, # [("src", "reg_ssa"), ("src_memory", "int")], + LowLevelILOperation.LLIL_CALL_PARAM: LowLevelILCall_param, # [("src", "expr_list")], + LowLevelILOperation.LLIL_LOAD_SSA: LowLevelILLoad_ssa, # [("src", "expr"), ("src_memory", "int")], + LowLevelILOperation.LLIL_STORE_SSA: LowLevelILStore_ssa, # [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_PHI: LowLevelILReg_phi, # [("dest", "reg_ssa"), ("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_REG_STACK_PHI: LowLevelILReg_stack_phi, # [("dest", "reg_stack_ssa"), ("src", "reg_stack_ssa_list")], + LowLevelILOperation.LLIL_FLAG_PHI: LowLevelILFlag_phi, # [("dest", "flag_ssa"), ("src", "flag_ssa_list")], + LowLevelILOperation.LLIL_MEM_PHI: LowLevelILMem_phi, # [("dest_memory", "int"), ("src_memory", "int_list")] +} class LowLevelILFunction: """ - ``class LowLevelILFunction`` contains the list of LowLevelILExpr objects that make up a function. LowLevelILExpr + ``class LowLevelILFunction`` contains the list of ExpressionIndex objects that make up a function. ExpressionIndex objects can be added to the LowLevelILFunction by calling :func:`append` and passing the result of the various class - methods which return LowLevelILExpr objects. + methods which return ExpressionIndex objects. LowLevelILFlagCondition values used as parameters in the :func:`flag_condition` method. @@ -1011,12 +2449,10 @@ class LowLevelILFunction: core.BNFreeLowLevelILFunction(self.handle) def __repr__(self): - source_function = getattr(self, "source_function", None) - arch = getattr(source_function, "arch", None) - if arch and source_function: - return "<llil func: %s@%#x>" % (arch.name, self.__dict__['source_function'].start) - elif source_function: - return "<llil func: %#x>" % self.__dict__['source_function'].start + if self.source_function is not None and self.source_function.arch is not None: + return f"<llil func: {self.source_function.arch.name}@{self.source_function.start:#x}>" + elif self.source_function is not None: + return f"<llil func: {self.source_function.start:#x}>" else: return "<llil func: anonymous>" @@ -1042,16 +2478,11 @@ class LowLevelILFunction: def __getitem__(self, i): if isinstance(i, slice) or isinstance(i, tuple): raise IndexError("expected integer instruction index") - if isinstance(i, LowLevelILExpr): - return LowLevelILInstruction(self, i.index) - # for backwards compatibility - if isinstance(i, LowLevelILInstruction): - return i if i < -len(self) or i >= len(self): raise IndexError("index out of range") if i < 0: i = len(self) + i - return LowLevelILInstruction(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) + return LowLevelILInstruction.create(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) def __setitem__(self, i, j): raise IndexError("instruction modification not implemented") @@ -1341,68 +2772,68 @@ class LowLevelILFunction: _flags = architecture.FlagIndex(0) else: assert False, "flags type unsupported" - return LowLevelILExpr(core.BNLowLevelILAddExpr(self.handle, operation, size, _flags, a, b, c, d)) + return ExpressionIndex(core.BNLowLevelILAddExpr(self.handle, operation, size, _flags, a, b, c, d)) def replace_expr(self, original:InstructionOrExpression, new:InstructionOrExpression) -> None: """ - ``replace_expr`` allows modification of LowLevelILExpressions but ONLY during lifting. + ``replace_expr`` allows modification of ExpressionIndexessions but ONLY during lifting. .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re-analysis of IL levels at this time. - :param LowLevelILExpr original: the LowLevelILExpr to replace (may also be an expression index) - :param LowLevelILExpr new: the LowLevelILExpr to add to the current LowLevelILFunction (may also be an expression index) + :param ExpressionIndex original: the ExpressionIndex to replace (may also be an expression index) + :param ExpressionIndex new: the ExpressionIndex to add to the current LowLevelILFunction (may also be an expression index) :rtype: None """ if isinstance(original, LowLevelILInstruction): original = original.expr_index - elif isinstance(original, LowLevelILExpr): - original = original.index + elif isinstance(original, ExpressionIndex): + original = original if isinstance(new, LowLevelILInstruction): new = new.expr_index - elif isinstance(new, LowLevelILExpr): - new = new.index + elif isinstance(new, ExpressionIndex): + new = new core.BNReplaceLowLevelILExpr(self.handle, original, new) - def append(self, expr:LowLevelILExpr) -> int: + def append(self, expr:ExpressionIndex) -> int: """ - ``append`` adds the LowLevelILExpr ``expr`` to the current LowLevelILFunction. + ``append`` adds the ExpressionIndex ``expr`` to the current LowLevelILFunction. - :param LowLevelILExpr expr: the LowLevelILExpr to add to the current LowLevelILFunction - :return: number of LowLevelILExpr in the current function + :param ExpressionIndex expr: the ExpressionIndex to add to the current LowLevelILFunction + :return: number of ExpressionIndex in the current function :rtype: int """ - return core.BNLowLevelILAddInstruction(self.handle, expr.index) + return core.BNLowLevelILAddInstruction(self.handle, expr) - def nop(self) -> LowLevelILExpr: + def nop(self) -> ExpressionIndex: """ ``nop`` no operation, this instruction does nothing :return: The no operation expression - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_NOP) - def set_reg(self, size:int, reg:'architecture.RegisterType', value:LowLevelILExpr, - flags:Optional['architecture.FlagType']=None) -> LowLevelILExpr: + def set_reg(self, size:int, reg:'architecture.RegisterType', value:ExpressionIndex, + flags:Optional['architecture.FlagType']=None) -> ExpressionIndex: """ ``set_reg`` sets the register ``reg`` of size ``size`` to the expression ``value`` :param int size: size of the register parameter in bytes :param str reg: the register name - :param LowLevelILExpr value: an expression to set the register to + :param ExpressionIndex value: an expression to set the register to :param str flags: which flags are set by this operation :return: The expression ``reg = value`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _reg = ExpressionIndex(self.arch.get_reg_index(reg)) if flags is None: flags = architecture.FlagIndex(0) - return self.expr(LowLevelILOperation.LLIL_SET_REG, _reg, value.index, size = size, flags = flags) + return self.expr(LowLevelILOperation.LLIL_SET_REG, _reg, value, size = size, flags = flags) def set_reg_split(self, size:int, hi:'architecture.RegisterType', lo:'architecture.RegisterType', - value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``set_reg_split`` uses ``hi`` and ``lo`` as a single extended register setting ``hi:lo`` to the expression ``value``. @@ -1410,125 +2841,125 @@ class LowLevelILFunction: :param int size: size of the register parameter in bytes :param str hi: the high register name :param str lo: the low register name - :param LowLevelILExpr value: an expression to set the split registers to + :param ExpressionIndex value: an expression to set the split registers to :param str flags: which flags are set by this operation :return: The expression ``hi:lo = value`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _hi = ExpressionIndex(self.arch.get_reg_index(hi)) _lo = ExpressionIndex(self.arch.get_reg_index(lo)) if flags is None: flags = architecture.FlagIndex(0) - return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, _hi, _lo, value.index, size = size, flags = flags) + return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, _hi, _lo, value, size = size, flags = flags) - def set_reg_stack_top_relative(self, size:int, reg_stack:'architecture.RegisterStackType', entry:LowLevelILExpr, - value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def set_reg_stack_top_relative(self, size:int, reg_stack:'architecture.RegisterStackType', entry:ExpressionIndex, + value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex entry: an expression for which stack entry to set + :param ExpressionIndex 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 + :rtype: ExpressionIndex """ _reg_stack = ExpressionIndex(self.arch.get_reg_stack_index(reg_stack)) if flags is None: flags = architecture.FlagIndex(0) - return self.expr(LowLevelILOperation.LLIL_SET_REG_STACK_REL, _reg_stack, entry.index, value.index, + return self.expr(LowLevelILOperation.LLIL_SET_REG_STACK_REL, _reg_stack, entry, value, size = size, flags = flags) - def reg_stack_push(self, size:int, reg_stack:'architecture.RegisterStackType', value:LowLevelILExpr, - flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def reg_stack_push(self, size:int, reg_stack:'architecture.RegisterStackType', value:ExpressionIndex, + flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: an expression to push :param str flags: which flags are set by this operation :return: The expression ``reg_stack.push(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _reg_stack = ExpressionIndex(self.arch.get_reg_stack_index(reg_stack)) if flags is None: flags = architecture.FlagIndex(0) - return self.expr(LowLevelILOperation.LLIL_REG_STACK_PUSH, _reg_stack, value.index, size = size, flags = flags) + return self.expr(LowLevelILOperation.LLIL_REG_STACK_PUSH, _reg_stack, value, size = size, flags = flags) - def set_flag(self, flag:'architecture.FlagName', value:LowLevelILExpr) -> LowLevelILExpr: + def set_flag(self, flag:'architecture.FlagName', value:ExpressionIndex) -> ExpressionIndex: """ - ``set_flag`` sets the flag ``flag`` to the LowLevelILExpr ``value`` + ``set_flag`` sets the flag ``flag`` to the ExpressionIndex ``value`` :param str flag: the low register name - :param LowLevelILExpr value: an expression to set the flag to + :param ExpressionIndex value: an expression to set the flag to :return: The expression FLAG.flag = value - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_SET_FLAG, ExpressionIndex(self.arch.get_flag_by_name(flag)), - value.index) + value) - def load(self, size:int, addr:LowLevelILExpr) -> LowLevelILExpr: + def load(self, size:int, addr:ExpressionIndex) -> ExpressionIndex: """ ``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 + :param ExpressionIndex addr: the expression to read memory from :return: The expression ``[addr].size`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_LOAD, addr.index, size=size) + return self.expr(LowLevelILOperation.LLIL_LOAD, addr, size=size) - def store(self, size:int, addr:LowLevelILExpr, value:LowLevelILExpr, flags=None) -> LowLevelILExpr: + def store(self, size:int, addr:ExpressionIndex, value:ExpressionIndex, flags=None) -> ExpressionIndex: """ ``store`` Writes ``size`` bytes to expression ``addr`` read from expression ``value`` :param int size: number of bytes to write - :param LowLevelILExpr addr: the expression to write to - :param LowLevelILExpr value: the expression to be written + :param ExpressionIndex addr: the expression to write to + :param ExpressionIndex value: the expression to be written :param str flags: which flags are set by this operation :return: The expression ``[addr].size = value`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_STORE, addr.index, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_STORE, addr, value, size=size, flags=flags) - def push(self, size:int, value:LowLevelILExpr) -> LowLevelILExpr: + def push(self, size:int, value:ExpressionIndex) -> ExpressionIndex: """ ``push`` writes ``size`` bytes from expression ``value`` to the stack, adjusting the stack by ``size``. :param int size: number of bytes to write and adjust the stack by - :param LowLevelILExpr value: the expression to write + :param ExpressionIndex value: the expression to write :return: The expression push(value) - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_PUSH, value.index, size=size) + return self.expr(LowLevelILOperation.LLIL_PUSH, value, size=size) - def pop(self, size:int) -> LowLevelILExpr: + def pop(self, size:int) -> ExpressionIndex: """ ``pop`` reads ``size`` bytes from the stack, adjusting the stack by ``size``. :param int size: number of bytes to read from the stack :return: The expression ``pop`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_POP, size=size) - def reg(self, size:int, reg:'architecture.RegisterType') -> LowLevelILExpr: + def reg(self, size:int, reg:'architecture.RegisterType') -> ExpressionIndex: """ ``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 :return: A register expression for the given string - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _reg = ExpressionIndex(self.arch.get_reg_index(reg)) return self.expr(LowLevelILOperation.LLIL_REG, _reg, size=size) - def reg_split(self, size:int, hi:'architecture.RegisterType', lo:'architecture.RegisterType') -> LowLevelILExpr: + def reg_split(self, size:int, hi:'architecture.RegisterType', lo:'architecture.RegisterType') -> ExpressionIndex: """ ``reg_split`` combines registers of size ``size`` with names ``hi`` and ``lo`` @@ -1536,27 +2967,27 @@ class LowLevelILFunction: :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 + :rtype: ExpressionIndex """ _hi = ExpressionIndex(self.arch.get_reg_index(hi)) _lo = ExpressionIndex(self.arch.get_reg_index(lo)) return self.expr(LowLevelILOperation.LLIL_REG_SPLIT, _hi, _lo, size=size) - def reg_stack_top_relative(self, size:int, reg_stack:'architecture.RegisterStackType', entry:LowLevelILExpr) -> LowLevelILExpr: + def reg_stack_top_relative(self, size:int, reg_stack:'architecture.RegisterStackType', entry:ExpressionIndex) -> ExpressionIndex: """ ``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 + :param ExpressionIndex entry: an expression for which stack entry to fetch :return: The expression ``reg_stack[entry]`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ _reg_stack = self.arch.get_reg_stack_index(reg_stack) - return self.expr(LowLevelILOperation.LLIL_REG_STACK_REL, _reg_stack, entry.index, size=size) + return self.expr(LowLevelILOperation.LLIL_REG_STACK_REL, _reg_stack, entry, size=size) - def reg_stack_pop(self, size:int, reg_stack:'architecture.RegisterStackType') -> LowLevelILExpr: + def reg_stack_pop(self, size:int, reg_stack:'architecture.RegisterStackType') -> ExpressionIndex: """ ``reg_stack_pop`` returns the top entry of size ``size`` in register stack with name ``reg_stack``, and removes the entry from the stack @@ -1564,45 +2995,45 @@ class LowLevelILFunction: :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 + :rtype: ExpressionIndex """ _reg_stack = ExpressionIndex(self.arch.get_reg_stack_index(reg_stack)) return self.expr(LowLevelILOperation.LLIL_REG_STACK_POP, _reg_stack, size=size) - def const(self, size:int, value:int) -> LowLevelILExpr: + def const(self, size:int, value:int) -> ExpressionIndex: """ ``const`` returns an expression for the constant integer ``value`` with size ``size`` :param int size: the size of the constant in bytes :param int value: integer value of the constant :return: A constant expression of given value and size - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_CONST, ExpressionIndex(value), size=size) - def const_pointer(self, size:int, value:int) -> LowLevelILExpr: + def const_pointer(self, size:int, value:int) -> ExpressionIndex: """ ``const_pointer`` returns an expression for the constant pointer ``value`` with size ``size`` :param int size: the size of the pointer in bytes :param int value: address referenced by pointer :return: A constant expression of given value and size - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size) - def reloc_pointer(self, size:int, value:int) -> LowLevelILExpr: + def reloc_pointer(self, size:int, value:int) -> ExpressionIndex: """ ``reloc_pointer`` returns an expression for the constant relocated pointer ``value`` with size ``size`` :param int size: the size of the pointer in bytes :param int value: address referenced by pointer :return: A constant expression of given value and size - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_EXTERN_PTR, value, size=size) - def float_const_raw(self, size:int, value:int) -> LowLevelILExpr: + def float_const_raw(self, size:int, value:int) -> ExpressionIndex: """ ``float_const_raw`` returns an expression for the constant raw binary floating point value ``value`` with size ``size`` @@ -1610,41 +3041,41 @@ class LowLevelILFunction: :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 + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, value, size=size) - def float_const_single(self, value:float) -> LowLevelILExpr: + def float_const_single(self, value:float) -> ExpressionIndex: """ ``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 + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("I", struct.pack("f", value))[0], size=4) - def float_const_double(self, value:float) -> LowLevelILExpr: + def float_const_double(self, value:float) -> ExpressionIndex: """ ``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 + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_FLOAT_CONST, struct.unpack("Q", struct.pack("d", value))[0], size=8) - def flag(self, reg:'architecture.FlagName') -> LowLevelILExpr: + def flag(self, reg:'architecture.FlagName') -> ExpressionIndex: """ ``flag`` returns a flag expression for the given flag name. :param architecture.FlagName reg: name of the flag expression to retrieve :return: A flag expression of given flag name - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_FLAG, self.arch.get_flag_by_name(reg)) - def flag_bit(self, size:int, reg:'architecture.FlagName', bit:int) -> LowLevelILExpr: + def flag_bit(self, size:int, reg:'architecture.FlagName', bit:int) -> ExpressionIndex: """ ``flag_bit`` sets the flag named ``reg`` and size ``size`` to the constant integer value ``bit`` @@ -1652,502 +3083,502 @@ class LowLevelILFunction: :param str reg: flag value :param int bit: integer value to set the bit to :return: A constant expression of given value and size ``FLAG.reg = bit`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_FLAG_BIT, self.arch.get_flag_by_name(reg), bit, size=size) - def add(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def add(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``add`` adds 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``add.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ADD, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ADD, a, b, size=size, flags=flags) - def add_carry(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, carry:LowLevelILExpr, - flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def add_carry(self, size:int, a:ExpressionIndex, b:ExpressionIndex, carry:ExpressionIndex, + flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``add_carry`` adds with carry 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 LowLevelILExpr carry: Carry flag expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression + :param ExpressionIndex carry: Carry flag expression :param str flags: flags to set :return: The expression ``adc.<size>{<flags>}(a, b, carry)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, carry.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ADC, a, b, carry, size=size, flags=flags) - def sub(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def sub(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``sub`` subtracts 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``sub.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_SUB, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_SUB, a, b, size=size, flags=flags) - def sub_borrow(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, carry:LowLevelILExpr, - flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def sub_borrow(self, size:int, a:ExpressionIndex, b:ExpressionIndex, carry:ExpressionIndex, + flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``sub_borrow`` subtracts with borrow 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 LowLevelILExpr carry: Carry flag expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression + :param ExpressionIndex carry: Carry flag expression :param str flags: flags to set :return: The expression ``sbb.<size>{<flags>}(a, b, carry)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, carry.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_SBB, a, b, carry, size=size, flags=flags) - def and_expr(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def and_expr(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``and_expr`` bitwise and's expression ``a`` and 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``and.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_AND, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_AND, a, b, size=size, flags=flags) - def or_expr(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def or_expr(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``or_expr`` bitwise or's expression ``a`` and 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``or.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_OR, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_OR, a, b, size=size, flags=flags) - def xor_expr(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def xor_expr(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``xor_expr`` xor's expression ``a`` with 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``xor.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_XOR, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_XOR, a, b, size=size, flags=flags) - def shift_left(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def shift_left(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``shift_left`` shifts left expression ``a`` by 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``lsl.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_LSL, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_LSL, a, b, size=size, flags=flags) - def logical_shift_right(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def logical_shift_right(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``logical_shift_right`` shifts logically right 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``lsr.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_LSR, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_LSR, a, b, size=size, flags=flags) - def arith_shift_right(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def arith_shift_right(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``arith_shift_right`` shifts arithmetic right 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``asr.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ASR, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ASR, a, b, size=size, flags=flags) - def rotate_left(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def rotate_left(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``rotate_left`` bitwise rotates left 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``rol.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ROL, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ROL, a, b, size=size, flags=flags) - def rotate_left_carry(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, carry:LowLevelILExpr, - flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def rotate_left_carry(self, size:int, a:ExpressionIndex, b:ExpressionIndex, carry:ExpressionIndex, + flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``rotate_left_carry`` bitwise rotates left with carry 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 LowLevelILExpr carry: Carry flag expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression + :param ExpressionIndex carry: Carry flag expression :param str flags: optional, flags to set :return: The expression ``rlc.<size>{<flags>}(a, b, carry)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, carry.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RLC, a, b, carry, size=size, flags=flags) - def rotate_right(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def rotate_right(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``rotate_right`` bitwise rotates right 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``ror.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ROR, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ROR, a, b, size=size, flags=flags) - def rotate_right_carry(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, carry:LowLevelILExpr, - flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def rotate_right_carry(self, size:int, a:ExpressionIndex, b:ExpressionIndex, carry:ExpressionIndex, + flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``rotate_right_carry`` bitwise rotates right with carry 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 LowLevelILExpr carry: Carry flag expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression + :param ExpressionIndex carry: Carry flag expression :param str flags: optional, flags to set :return: The expression ``rrc.<size>{<flags>}(a, b, carry)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, carry.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RRC, a, b, carry, size=size, flags=flags) - def mult(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mult(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``mult`` multiplies 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``sbc.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MUL, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MUL, a, b, size=size, flags=flags) - def mult_double_prec_signed(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mult_double_prec_signed(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``mult_double_prec_signed`` multiplies signed with double precision 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``muls.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MULS_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MULS_DP, a, b, size=size, flags=flags) - def mult_double_prec_unsigned(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mult_double_prec_unsigned(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``mult_double_prec_unsigned`` multiplies unsigned with double precision 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``mulu.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MULU_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MULU_DP, a, b, size=size, flags=flags) - def div_signed(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def div_signed(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``div_signed`` signed divide 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_DIVS, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVS, a, b, size=size, flags=flags) - def div_double_prec_signed(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def div_double_prec_signed(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 a: LHS expression - :param LowLevelILExpr b: RHS expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``divs.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_DIVS_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVS_DP, a, b, size=size, flags=flags) - def div_unsigned(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def div_unsigned(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``div_unsigned`` unsigned divide 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``divu.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_DIVU, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVU, a, b, size=size, flags=flags) - def div_double_prec_unsigned(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def div_double_prec_unsigned(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 a: LHS expression - :param LowLevelILExpr b: RHS expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``divu.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_DIVU_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_DIVU_DP, a, b, size=size, flags=flags) - def mod_signed(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mod_signed(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``mod_signed`` signed modulus 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``mods.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MODS, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODS, a, b, size=size, flags=flags) - def mod_double_prec_signed(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mod_double_prec_signed(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 a: LHS expression - :param LowLevelILExpr b: RHS expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``mods.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MODS_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODS_DP, a, b, size=size, flags=flags) - def mod_unsigned(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mod_unsigned(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``mod_unsigned`` unsigned modulus 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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``modu.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MODU, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODU, a, b, size=size, flags=flags) - def mod_double_prec_unsigned(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def mod_double_prec_unsigned(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 a: LHS expression - :param LowLevelILExpr b: RHS expression + :param ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: optional, flags to set :return: The expression ``modu.dp.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_MODU_DP, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_MODU_DP, a, b, size=size, flags=flags) - def neg_expr(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def neg_expr(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``neg_expr`` two's complement sign negation of 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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``neg.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_NEG, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_NEG, value, size=size, flags=flags) - def not_expr(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def not_expr(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``not_expr`` bitwise inverse of expression ``value`` of size ``size`` potentially setting flags :param int size: the size of the result in bytes - :param LowLevelILExpr value: the expression to bitwise invert + :param ExpressionIndex value: the expression to bitwise invert :param str flags: optional, flags to set :return: The expression ``not.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_NOT, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_NOT, value, size=size, flags=flags) - def sign_extend(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def sign_extend(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``sign_extend`` two's complement sign-extends the expression in ``value`` to ``size`` bytes :param int size: the size of the result in bytes - :param LowLevelILExpr value: the expression to sign extend + :param ExpressionIndex value: the expression to sign extend :param str flags: optional, flags to set :return: The expression ``sx.<size>(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_SX, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_SX, value, size=size, flags=flags) - def zero_extend(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def zero_extend(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``zero_extend`` zero-extends the expression in ``value`` to ``size`` bytes :param int size: the size of the result in bytes - :param LowLevelILExpr value: the expression to zero extend + :param ExpressionIndex value: the expression to zero extend :return: The expression ``zx.<size>(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ZX, value, size=size, flags=flags) - def low_part(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def low_part(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``low_part`` truncates ``value`` to ``size`` bytes :param int size: the size of the result in bytes - :param LowLevelILExpr value: the expression to zero extend + :param ExpressionIndex value: the expression to zero extend :return: The expression ``(value).<size>`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_LOW_PART, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_LOW_PART, value, size=size, flags=flags) - def jump(self, dest:LowLevelILExpr) -> LowLevelILExpr: + def jump(self, dest:ExpressionIndex) -> ExpressionIndex: """ ``jump`` returns an expression which jumps (branches) to the expression ``dest`` - :param LowLevelILExpr dest: the expression to jump to + :param ExpressionIndex dest: the expression to jump to :return: The expression ``jump(dest)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_JUMP, dest.index) + return self.expr(LowLevelILOperation.LLIL_JUMP, dest) - def call(self, dest:LowLevelILExpr) -> LowLevelILExpr: + def call(self, dest:ExpressionIndex) -> ExpressionIndex: """ ``call`` returns an expression which first pushes the address of the next instruction onto the stack then jumps (branches) to the expression ``dest`` - :param LowLevelILExpr dest: the expression to call + :param ExpressionIndex dest: the expression to call :return: The expression ``call(dest)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CALL, dest.index) + return self.expr(LowLevelILOperation.LLIL_CALL, dest) - def call_stack_adjust(self, dest:LowLevelILExpr, stack_adjust:int) -> LowLevelILExpr: + def call_stack_adjust(self, dest:ExpressionIndex, stack_adjust:int) -> ExpressionIndex: """ ``call_stack_adjust`` returns an expression which first pushes the address of the next instruction onto the stack then jumps (branches) to the expression ``dest``. After the function exits, ``stack_adjust`` is added to the stack pointer register. - :param LowLevelILExpr dest: the expression to call + :param ExpressionIndex dest: the expression to call :return: The expression ``call(dest), stack += stack_adjust`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest.index, stack_adjust) + return self.expr(LowLevelILOperation.LLIL_CALL_STACK_ADJUST, dest, stack_adjust) - def tailcall(self, dest:LowLevelILExpr) -> LowLevelILExpr: + def tailcall(self, dest:ExpressionIndex) -> ExpressionIndex: """ ``tailcall`` returns an expression which jumps (branches) to the expression ``dest`` - :param LowLevelILExpr dest: the expression to jump to + :param ExpressionIndex dest: the expression to jump to :return: The expression ``tailcall(dest)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_TAILCALL, dest.index) + return self.expr(LowLevelILOperation.LLIL_TAILCALL, dest) - def ret(self, dest:LowLevelILExpr) -> LowLevelILExpr: + def ret(self, dest:ExpressionIndex) -> ExpressionIndex: """ ``ret`` returns an expression which jumps (branches) to the expression ``dest``. ``ret`` is a special alias for jump that makes the disassembler stop disassembling. - :param LowLevelILExpr dest: the expression to jump to + :param ExpressionIndex dest: the expression to jump to :return: The expression ``jump(dest)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_RET, dest.index) + return self.expr(LowLevelILOperation.LLIL_RET, dest) - def no_ret(self) -> LowLevelILExpr: + def no_ret(self) -> ExpressionIndex: """ ``no_ret`` returns an expression halts disassembly :return: The expression ``noreturn`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_NORET) def flag_condition(self, cond:Union[str, LowLevelILFlagCondition, int], - sem_class:Optional['architecture.SemanticClassType']=None) -> LowLevelILExpr: + sem_class:Optional['architecture.SemanticClassType']=None) -> ExpressionIndex: """ ``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 + :rtype: ExpressionIndex """ if isinstance(cond, str): cond = LowLevelILFlagCondition[cond] @@ -2165,520 +3596,520 @@ class LowLevelILFunction: :param str sem_group: Semantic flag group to access :return: A flag_group expression - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ group = self.arch.get_semantic_flag_group_index(sem_group) return self.expr(LowLevelILOperation.LLIL_FLAG_GROUP, group) - def compare_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_E, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_E, a, b, size = size) - def compare_not_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_not_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_not_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is not equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_NE, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_NE, a, b, size = size) - def compare_signed_less_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_signed_less_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_signed_less_than`` returns comparison expression of size ``size`` checking if expression ``a`` is signed less than expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_SLT, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_SLT, a, b, size = size) - def compare_unsigned_less_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_unsigned_less_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_unsigned_less_than`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned less than expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_ULT, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_ULT, a, b, size = size) - def compare_signed_less_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_signed_less_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_signed_less_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is signed less than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_SLE, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_SLE, a, b, size = size) - def compare_unsigned_less_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_unsigned_less_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_unsigned_less_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned less than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_ULE, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_ULE, a, b, size = size) - def compare_signed_greater_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_signed_greater_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_signed_greater_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is signed greater than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_SGE, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_SGE, a, b, size = size) - def compare_unsigned_greater_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_unsigned_greater_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_unsigned_greater_equal`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned greater than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_UGE, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_UGE, a, b, size = size) - def compare_signed_greater_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_signed_greater_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_signed_greater_than`` returns comparison expression of size ``size`` checking if expression ``a`` is signed greater than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_SGT, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_SGT, a, b, size = size) - def compare_unsigned_greater_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def compare_unsigned_greater_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``compare_unsigned_greater_than`` returns comparison expression of size ``size`` checking if expression ``a`` is unsigned greater than or equal to expression ``b`` :param int size: size in bytes - :param LowLevelILExpr a: LHS of comparison - :param LowLevelILExpr b: RHS of comparison + :param ExpressionIndex a: LHS of comparison + :param ExpressionIndex b: RHS of comparison :return: a comparison expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CMP_UGT, a.index, b.index, size = size) + return self.expr(LowLevelILOperation.LLIL_CMP_UGT, a, b, size = size) - def test_bit(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: - return self.expr(LowLevelILOperation.LLIL_TEST_BIT, a.index, b.index, size = size) + def test_bit(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: + return self.expr(LowLevelILOperation.LLIL_TEST_BIT, a, b, size = size) - def system_call(self) -> LowLevelILExpr: + def system_call(self) -> ExpressionIndex: """ ``system_call`` return a system call expression. :return: a system call expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_SYSCALL) - def intrinsic(self, outputs:List[Union[ILFlag, LowLevelILExpr]], intrinsic:'architecture.IntrinsicType', - params:List[LowLevelILExpr], flags:'architecture.FlagType'=None): + def intrinsic(self, outputs:List[Union[ILFlag, ExpressionIndex]], intrinsic:'architecture.IntrinsicType', + params:List[ExpressionIndex], flags:'architecture.FlagType'=None): """ ``intrinsic`` return an intrinsic expression. :return: an intrinsic expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ output_list = [] for output in outputs: if isinstance(output, ILFlag): - output_list.append((1 << 32) | output.index) + output_list.append((1 << 32) | int(output)) else: - output_list.append(output.index) + output_list.append(output) param_list = [] for param in params: - param_list.append(param.index) - call_param = self.expr(LowLevelILOperation.LLIL_CALL_PARAM, len(params), self.add_operand_list(param_list).index) - return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list).index, - self.arch.get_intrinsic_index(intrinsic), call_param.index, flags = flags) + param_list.append(param) + call_param = self.expr(LowLevelILOperation.LLIL_CALL_PARAM, len(params), self.add_operand_list(param_list)) + return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list), + self.arch.get_intrinsic_index(intrinsic), call_param, flags = flags) - def breakpoint(self) -> LowLevelILExpr: + def breakpoint(self) -> ExpressionIndex: """ ``breakpoint`` returns a processor breakpoint expression. :return: a breakpoint expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_BP) - def trap(self, value:int) -> LowLevelILExpr: + def trap(self, value:int) -> ExpressionIndex: """ ``trap`` returns a processor trap (interrupt) expression of the given integer ``value``. :param int value: trap (interrupt) number :return: a trap expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_TRAP, value) - def undefined(self) -> LowLevelILExpr: + def undefined(self) -> ExpressionIndex: """ ``undefined`` returns the undefined expression. This should be used for instructions which perform functions but aren't important for dataflow or partial emulation purposes. :return: the unimplemented expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_UNDEF) - def unimplemented(self) -> LowLevelILExpr: + def unimplemented(self) -> ExpressionIndex: """ ``unimplemented`` returns the unimplemented expression. This should be used for all instructions which aren't implemented. :return: the unimplemented expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ return self.expr(LowLevelILOperation.LLIL_UNIMPL) - def unimplemented_memory_ref(self, size:int, addr:LowLevelILExpr) -> LowLevelILExpr: + def unimplemented_memory_ref(self, size:int, addr:ExpressionIndex) -> ExpressionIndex: """ ``unimplemented_memory_ref`` a memory reference to expression ``addr`` of size ``size`` with unimplemented operation. :param int size: size in bytes of the memory reference - :param LowLevelILExpr addr: expression to reference memory + :param ExpressionIndex addr: expression to reference memory :return: the unimplemented memory reference expression. - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_UNIMPL_MEM, addr.index, size = size) + return self.expr(LowLevelILOperation.LLIL_UNIMPL_MEM, addr, size = size) - def float_add(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_add(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``fadd.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FADD, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FADD, a, b, size=size, flags=flags) - def float_sub(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_sub(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``fsub.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FSUB, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FSUB, a, b, size=size, flags=flags) - def float_mult(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_mult(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``fmul.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FMUL, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FMUL, a, b, size=size, flags=flags) - def float_div(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_div(self, size:int, a:ExpressionIndex, b:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``fdiv.<size>{<flags>}(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FDIV, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FDIV, a, b, size=size, flags=flags) - def float_sqrt(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_sqrt(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``sqrt.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FSQRT, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FSQRT, value, size=size, flags=flags) - def float_neg(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_neg(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``fneg.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FNEG, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FNEG, value, size=size, flags=flags) - def float_abs(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_abs(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``fabs.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FABS, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FABS, value, size=size, flags=flags) - def float_to_int(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_to_int(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``int.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FLOAT_TO_INT, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FLOAT_TO_INT, value, size=size, flags=flags) - def int_to_float(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def int_to_float(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``float.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_INT_TO_FLOAT, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_INT_TO_FLOAT, value, size=size, flags=flags) - def float_convert(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_convert(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``fconvert.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FLOAT_CONV, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FLOAT_CONV, value, size=size, flags=flags) - def round_to_int(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def round_to_int(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``roundint.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_ROUND_TO_INT, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ROUND_TO_INT, value, size=size, flags=flags) - def floor(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def floor(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``roundint.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FLOOR, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FLOOR, value, size=size, flags=flags) - def ceil(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def ceil(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``roundint.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_CEIL, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_CEIL, value, size=size, flags=flags) - def float_trunc(self, size:int, value:LowLevelILExpr, flags:'architecture.FlagType'=None) -> LowLevelILExpr: + def float_trunc(self, size:int, value:ExpressionIndex, flags:'architecture.FlagType'=None) -> ExpressionIndex: """ ``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 ExpressionIndex value: the expression to negate :param str flags: optional, flags to set :return: The expression ``roundint.<size>{<flags>}(value)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FTRUNC, value.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_FTRUNC, value, size=size, flags=flags) - def float_compare_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f== b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_E, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_E, a, b) - def float_compare_not_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_not_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f!= b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_NE, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_NE, a, b) - def float_compare_less_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_less_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f< b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_LT, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_LT, a, b) - def float_compare_less_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_less_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f<= b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_LE, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_LE, a, b) - def float_compare_greater_equal(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_greater_equal(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f>= b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_GE, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_GE, a, b) - def float_compare_greater_than(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_greater_than(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``a f> b`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_GT, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_GT, a, b) - def float_compare_unordered(self, size:int, a:LowLevelILExpr, b:LowLevelILExpr) -> LowLevelILExpr: + def float_compare_unordered(self, size:int, a:ExpressionIndex, b:ExpressionIndex) -> ExpressionIndex: """ ``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 ExpressionIndex a: LHS expression + :param ExpressionIndex b: RHS expression :param str flags: flags to set :return: The expression ``is_unordered(a, b)`` - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - return self.expr(LowLevelILOperation.LLIL_FCMP_UO, a.index, b.index) + return self.expr(LowLevelILOperation.LLIL_FCMP_UO, a, b) - def goto(self, label:LowLevelILLabel) -> LowLevelILExpr: + def goto(self, label:LowLevelILLabel) -> ExpressionIndex: """ ``goto`` returns a goto expression which jumps to the provided LowLevelILLabel. :param LowLevelILLabel label: Label to jump to - :return: the LowLevelILExpr that jumps to the provided label - :rtype: LowLevelILExpr + :return: the ExpressionIndex that jumps to the provided label + :rtype: ExpressionIndex """ - return LowLevelILExpr(core.BNLowLevelILGoto(self.handle, label.handle)) + return ExpressionIndex(core.BNLowLevelILGoto(self.handle, label.handle)) - def if_expr(self, operand:LowLevelILExpr, t:LowLevelILLabel, f:LowLevelILLabel) -> LowLevelILExpr: + def if_expr(self, operand:ExpressionIndex, t:LowLevelILLabel, f:LowLevelILLabel) -> ExpressionIndex: """ ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the LowLevelILLabel ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. - :param LowLevelILExpr operand: comparison expression to evaluate. + :param ExpressionIndex operand: comparison expression to evaluate. :param LowLevelILLabel t: Label for the true branch :param LowLevelILLabel f: Label for the false branch - :return: the LowLevelILExpr for the if expression - :rtype: LowLevelILExpr + :return: the ExpressionIndex for the if expression + :rtype: ExpressionIndex """ - return LowLevelILExpr(core.BNLowLevelILIf(self.handle, operand.index, t.handle, f.handle)) + return ExpressionIndex(core.BNLowLevelILIf(self.handle, operand, t.handle, f.handle)) def mark_label(self, label:LowLevelILLabel) -> None: """ @@ -2689,14 +4120,14 @@ class LowLevelILFunction: """ core.BNLowLevelILMarkLabel(self.handle, label.handle) - def add_label_map(self, labels:Mapping[int, LowLevelILLabel]) -> LowLevelILExpr: + def add_label_map(self, labels:Mapping[int, LowLevelILLabel]) -> ExpressionIndex: """ ``add_label_map`` returns a label list expression for the given list of LowLevelILLabel objects. :param labels: the list of LowLevelILLabel to get a label list expression from :type labels: dict(int, LowLevelILLabel) :return: the label list expression - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ label_list = (ctypes.POINTER(core.BNLowLevelILLabel) * len(labels))() # type: ignore value_list = (ctypes.POINTER(ctypes.c_ulonglong) * len(labels))() # type: ignore @@ -2704,38 +4135,38 @@ class LowLevelILFunction: value_list[i] = key label_list[i] = value.handle - return LowLevelILExpr(core.BNLowLevelILAddLabelMap(self.handle, value_list, label_list, len(labels))) + return ExpressionIndex(core.BNLowLevelILAddLabelMap(self.handle, value_list, label_list, len(labels))) - def add_operand_list(self, operands:List[Union[ExpressionIndex, LowLevelILExpr]]) -> LowLevelILExpr: + def add_operand_list(self, operands:List[Union[ExpressionIndex, ExpressionIndex]]) -> ExpressionIndex: """ ``add_operand_list`` returns an operand list expression for the given list of integer operands. :param operands: list of operand numbers - :type operands: List(Union[ExpressionIndex, LowLevelILExpr]) + :type operands: List(Union[ExpressionIndex, ExpressionIndex]) :return: an operand list expression - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ operand_list = (ctypes.c_ulonglong * len(operands))() for i in range(len(operands)): op = operands[i] - if isinstance(op, LowLevelILExpr): - operand_list[i] = op.index + if isinstance(op, ExpressionIndex): + operand_list[i] = op elif isinstance(op, int): operand_list[i] = op else: raise Exception("Invalid operand type") - return LowLevelILExpr(core.BNLowLevelILAddOperandList(self.handle, operand_list, len(operands))) + return ExpressionIndex(core.BNLowLevelILAddOperandList(self.handle, operand_list, len(operands))) - def operand(self, n:int, expr:LowLevelILExpr) -> LowLevelILExpr: + def operand(self, n:int, expr:ExpressionIndex) -> ExpressionIndex: """ ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification. :param int n: - :param LowLevelILExpr expr: + :param ExpressionIndex expr: :return: returns the expression ``expr`` unmodified - :rtype: LowLevelILExpr + :rtype: ExpressionIndex """ - core.BNLowLevelILSetExprSourceOperand(self.handle, expr.index, n) + core.BNLowLevelILSetExprSourceOperand(self.handle, expr, n) return expr def finalize(self) -> None: diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 6d038da0..dd219095 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -20,7 +20,8 @@ import ctypes import struct -from typing import Optional, List, Any, Union, Mapping, Generator, NewType +from typing import Optional, List, Union, Mapping, Generator, NewType, Tuple +from dataclasses import dataclass # Binary Ninja components from . import _binaryninjacore as core @@ -40,44 +41,28 @@ ExpressionIndex = NewType('ExpressionIndex', int) InstructionIndex = NewType('InstructionIndex', int) MLILInstructionsType = Generator['MediumLevelILInstruction', None, None] MLILBasicBlocksType = Generator['MediumLevelILBasicBlock', None, None] +OperandsType = Tuple[ExpressionIndex, ExpressionIndex, ExpressionIndex, ExpressionIndex, ExpressionIndex] +MediumLevelILOperandType = Union[ + int, + float, + 'MediumLevelILOperationAndSize', + 'MediumLevelILInstruction', + 'lowlevelil.ILIntrinsic', + 'variable.Variable', + 'SSAVariable', + List[int], + List['SSAVariable'], + List['MediumLevelILInstruction'], + Mapping[int, int] + ] - +@dataclass(frozen=True, repr=False) class SSAVariable: - def __init__(self, var:'variable.Variable', version:int): - self._var = var - self._version = version + var:'variable.Variable' + version:int def __repr__(self): - return "<ssa %s version %d>" % (repr(self._var), self._version) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._var, self._version) == (other.var, other.version) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._var, self._version)) - - @property - def var(self) -> 'variable.Variable': - return self._var - - @var.setter - def var(self, value:'variable.Variable') -> None: - self._var = value - - @property - def version(self) -> int: - return self._version - - @version.setter - def version(self, value=int) -> None: - self._version = value + return f"<ssa {repr(self.var)} version {self.version}>" class MediumLevelILLabel: @@ -89,40 +74,33 @@ class MediumLevelILLabel: self.handle = handle +@dataclass(frozen=True, repr=False) class MediumLevelILOperationAndSize: - def __init__(self, operation:MediumLevelILOperation, size:int): - self._operation = operation - self._size = size + operation:MediumLevelILOperation + size:int def __repr__(self): - if self._size == 0: - return "<%s>" % self._operation.name - return "<%s %d>" % (self._operation.name, self._size) + if self.size == 0: + return f"<{self.operation.name}>" + return f"<{self.operation.name} {self.size}>" - def __eq__(self, other): - if isinstance(other, MediumLevelILOperation): - return other == self._operation - if isinstance(other, self.__class__): - return (other.size, other.operation) == (self._size, self._operation) - return NotImplemented - - def __ne__(self, other): - if isinstance(other, MediumLevelILOperation) or isinstance(other, self.__class__): - return not (self == other) - return NotImplemented - def __hash__(self): - return hash((self._operation, self._size)) +@dataclass(frozen=True) +class CoreMediumLevelILInstruction: + operation:MediumLevelILOperation + source_operand:int + size:int + operands:OperandsType + address:int - @property - def operation(self) -> MediumLevelILOperation: - return self._operation - @property - def size(self) -> int: - return self._size + @classmethod + def from_BNMediumLevelILInstruction(cls, instr:core.BNMediumLevelILInstruction) -> 'CoreMediumLevelILInstruction': + operands:OperandsType = tuple([ExpressionIndex(instr.operands[i]) for i in range(5)]) # type: ignore + return cls(MediumLevelILOperation(instr.operation), instr.sourceOperand, instr.size, operands, instr.address) +@dataclass(frozen=True) class MediumLevelILInstruction: """ ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based @@ -130,241 +108,22 @@ class MediumLevelILInstruction: Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. MLIL ``eax = 0``). """ - ILOperations = { - MediumLevelILOperation.MLIL_NOP: [], - MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SPLIT: [("high", "var"), ("low", "var"), ("src", "expr")], - MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], - MediumLevelILOperation.MLIL_LOAD_STRUCT: [("src", "expr"), ("offset", "int")], - MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], - 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_EXTERN_PTR: [("constant", "int"), ("offset", "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")], - MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_LSL: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], - MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], - 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: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_DIVS_DP: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_MODU_DP: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_MODS: [("left", "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")], - MediumLevelILOperation.MLIL_ZX: [("src", "expr")], - MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")], - MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], - MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "target_map")], - MediumLevelILOperation.MLIL_RET_HINT: [("dest", "expr")], - MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], - MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], - MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], - MediumLevelILOperation.MLIL_CALL_PARAM: [("src", "var_list")], - MediumLevelILOperation.MLIL_RET: [("src", "expr_list")], - MediumLevelILOperation.MLIL_NORET: [], - MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], - MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], - MediumLevelILOperation.MLIL_CMP_E: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_NE: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], - MediumLevelILOperation.MLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], - MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "expr_list")], - MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], - MediumLevelILOperation.MLIL_TAILCALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], - MediumLevelILOperation.MLIL_TAILCALL_UNTYPED: [("output", "expr"), ("dest", "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")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], - MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var_ssa"), ("offset", "int")], - MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var_ssa")], - MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var_ssa"), ("offset", "int")], - MediumLevelILOperation.MLIL_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")], - MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("params", "expr"), ("stack", "expr")], - MediumLevelILOperation.MLIL_TAILCALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], - MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], - MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], - MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], - MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], - MediumLevelILOperation.MLIL_LOAD_STRUCT_SSA: [("src", "expr"), ("offset", "int"), ("src_memory", "int")], - MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_STORE_STRUCT_SSA: [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], - MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] - } + function:'MediumLevelILFunction' + expr_index:ExpressionIndex + instr:CoreMediumLevelILInstruction + instr_index:InstructionIndex + operand_names = tuple() - def __init__(self, func:'MediumLevelILFunction', expr_index:ExpressionIndex, instr_index:InstructionIndex=None): - instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) - self._function = func - self._expr_index = expr_index + @classmethod + def create(cls, func:'MediumLevelILFunction', expr_index:ExpressionIndex, instr_index:Optional[InstructionIndex]=None) -> 'MediumLevelILInstruction': + assert func.arch is not None, "Attempted to create IL instruction with function missing an Architecture" + inst = core.BNGetMediumLevelILByIndex(func.handle, expr_index) + assert inst is not None, "core.BNGetMediumLevelILByIndex returned None" if instr_index is None: - self._instr_index = core.BNGetMediumLevelILInstructionForExpr(func.handle, expr_index) - else: - self._instr_index = instr_index - self._operation = MediumLevelILOperation(instr.operation) - self._size = instr.size - self._address = instr.address - self._source_operand = instr.sourceOperand - operands = MediumLevelILInstruction.ILOperations[instr.operation] - self._operands:List[Any] = [] - i = 0 - for operand in operands: - name, operand_type = operand - value = None - if operand_type == "int": - value = instr.operands[i] - value = (value & ((1 << 63) - 1)) - (value & (1 << 63)) - 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": - assert func.arch is not None, "Attempting to create ILInstrinsice from function with no Architecture" - value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) - elif operand_type == "var": - value = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) - elif operand_type == "var_ssa": - var = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) - version = instr.operands[i + 1] - i += 1 - value = SSAVariable(var, version) - elif operand_type == "var_ssa_dest_and_src": - var = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) - dest_version = instr.operands[i + 1] - src_version = instr.operands[i + 2] - i += 2 - self._operands.append(SSAVariable(var, dest_version)) - #TODO: documentation for dest - self.dest = SSAVariable(var, dest_version) - value = SSAVariable(var, src_version) - elif operand_type == "int_list": - count = ctypes.c_ulonglong() - operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - value = [] - for j in range(count.value): - value.append(operand_list[j]) - core.BNMediumLevelILFreeOperandList(operand_list) - elif operand_type == "var_list": - count = ctypes.c_ulonglong() - operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(count.value): - value.append(variable.Variable.from_identifier(self._function.source_function, operand_list[j])) - core.BNMediumLevelILFreeOperandList(operand_list) - elif operand_type == "var_ssa_list": - count = ctypes.c_ulonglong() - operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(count.value // 2): - var_id = operand_list[j * 2] - var_version = operand_list[(j * 2) + 1] - value.append(SSAVariable(variable.Variable.from_identifier(self._function.source_function, - var_id), var_version)) - core.BNMediumLevelILFreeOperandList(operand_list) - elif operand_type == "expr_list": - count = ctypes.c_ulonglong() - operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - i += 1 - value = [] - for j in range(count.value): - value.append(MediumLevelILInstruction(func, operand_list[j])) - core.BNMediumLevelILFreeOperandList(operand_list) - elif operand_type == "target_map": - count = ctypes.c_ulonglong() - operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) - assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" - i += 1 - value = {} - for j in range(count.value // 2): - key = operand_list[j * 2] - target = operand_list[(j * 2) + 1] - value[key] = target - core.BNMediumLevelILFreeOperandList(operand_list) - self._operands.append(value) - self.__dict__[name] = value - i += 1 + instr_index = core.BNGetMediumLevelILInstructionForExpr(func.handle, expr_index) + assert instr_index is not None, "core.BNGetMediumLevelILInstructionForExpr returned None" + instr = CoreMediumLevelILInstruction.from_BNMediumLevelILInstruction(inst) + return ILInstruction[instr.operation](func, expr_index, instr, instr_index) # type: ignore def __str__(self): tokens = self.tokens @@ -381,46 +140,46 @@ class MediumLevelILInstruction: def __eq__(self, other:'MediumLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self._expr_index == other.expr_index + return self.function == other.function and self.expr_index == other.expr_index def __lt__(self, other:'MediumLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index < other.expr_index + return self.function == other.function and self.expr_index < other.expr_index def __le__(self, other:'MediumLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index <= other.expr_index + return self.function == other.function and self.expr_index <= other.expr_index def __gt__(self, other:'MediumLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index > other.expr_index + return self.function == other.function and self.expr_index > other.expr_index def __ge__(self, other:'MediumLevelILInstruction'): if not isinstance(other, self.__class__): return NotImplemented - return self._function == other.function and self.expr_index >= other.expr_index + return self.function == other.function and self.expr_index >= other.expr_index def __hash__(self): - return hash((self._instr_index, self._function)) + return hash((self.function, self.expr_index)) @property def tokens(self) -> OptionalTokens: """MLIL tokens (read-only)""" count = ctypes.c_ulonglong() tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if self._function.arch is None: + if self.function.arch is None: raise Exception("Attempting to get tokens for MLIL Function with no Architecture set") - if ((self._instr_index is not None) and (self._function.source_function is not None) and - (self._expr_index == core.BNGetMediumLevelILIndexForInstruction(self._function.handle, self._instr_index))): - if not core.BNGetMediumLevelILInstructionText(self._function.handle, self._function.source_function.handle, - self._function.arch.handle, self._instr_index, tokens, count, None): + if ((self.instr_index is not None) and (self.function.source_function is not None) and + (self.expr_index == core.BNGetMediumLevelILIndexForInstruction(self.function.handle, self.instr_index))): + if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle, + self.function.arch.handle, self.instr_index, tokens, count, None): return None else: - if not core.BNGetMediumLevelILExprText(self._function.handle, self._function.arch.handle, - self._expr_index, tokens, count, None): + if not core.BNGetMediumLevelILExprText(self.function.handle, self.function.arch.handle, + self.expr_index, tokens, count, None): return None result = function.InstructionTextToken._from_core_struct(tokens, count.value) core.BNFreeInstructionText(tokens, count.value) @@ -429,39 +188,39 @@ class MediumLevelILInstruction: @property def il_basic_block(self) -> 'MediumLevelILBasicBlock': """IL basic block object containing this expression (read-only) (only available on finalized functions)""" - core_block = core.BNGetMediumLevelILBasicBlockForInstruction(self._function.handle, self._instr_index) + core_block = core.BNGetMediumLevelILBasicBlockForInstruction(self.function.handle, self.instr_index) assert core_block is not None - assert self._function.source_function is not None - return MediumLevelILBasicBlock(core_block, self._function, self._function.source_function.view) + assert self.function.source_function is not None + return MediumLevelILBasicBlock(core_block, self.function, self.function.source_function.view) @property def ssa_form(self) -> 'MediumLevelILInstruction': """SSA form of expression (read-only)""" - ssa_func = self._function.ssa_form + ssa_func = self.function.ssa_form assert ssa_func is not None - return MediumLevelILInstruction(ssa_func, - core.BNGetMediumLevelILSSAExprIndex(self._function.handle, self._expr_index)) + return MediumLevelILInstruction.create(ssa_func, + core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index)) @property def non_ssa_form(self) -> 'MediumLevelILInstruction': """Non-SSA form of expression (read-only)""" - non_ssa_func = self._function.non_ssa_form + non_ssa_func = self.function.non_ssa_form assert non_ssa_func is not None - return MediumLevelILInstruction(non_ssa_func, - core.BNGetMediumLevelILNonSSAExprIndex(self._function.handle, self._expr_index)) + return MediumLevelILInstruction.create(non_ssa_func, + core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) @property def value(self) -> variable.RegisterValue: """Value of expression if constant or a known value (read-only)""" - value = core.BNGetMediumLevelILExprValue(self._function.handle, self._expr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result @property def possible_values(self) -> variable.PossibleValueSet: """Possible values of expression using path-sensitive static data flow analysis (read-only)""" - value = core.BNGetMediumLevelILPossibleExprValues(self._function.handle, self._expr_index, None, 0) - result = variable.PossibleValueSet(self._function.arch, value) + value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index, None, 0) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -469,7 +228,7 @@ class MediumLevelILInstruction: def branch_dependence(self) -> Mapping[int, ILBranchDependence]: """Set of branching instructions that must take the true or false path to reach this instruction""" count = ctypes.c_ulonglong() - deps = core.BNGetAllMediumLevelILBranchDependence(self._function.handle, self._instr_index, count) + deps = core.BNGetAllMediumLevelILBranchDependence(self.function.handle, self.instr_index, count) assert deps is not None, "core.BNGetAllMediumLevelILBranchDependence returned None" result = {} for i in range(0, count.value): @@ -480,10 +239,10 @@ class MediumLevelILInstruction: @property def low_level_il(self) -> Optional['lowlevelil.LowLevelILInstruction']: """Low level IL form of this expression""" - expr = self._function.get_low_level_il_expr_index(self._expr_index) - if expr is None or self._function.low_level_il is None: + expr = self.function.get_low_level_il_expr_index(self.expr_index) + if expr is None or self.function.low_level_il is None: return None - return lowlevelil.LowLevelILInstruction(self._function.low_level_il.ssa_form, expr) + return lowlevelil.LowLevelILInstruction.create(self.function.low_level_il.ssa_form, expr, None) @property def llil(self) -> Optional['lowlevelil.LowLevelILInstruction']: @@ -492,21 +251,21 @@ class MediumLevelILInstruction: @property def llils(self) -> List['lowlevelil.LowLevelILInstruction']: - exprs = self._function.get_low_level_il_expr_indexes(self.expr_index) - if self._function.low_level_il is None: + exprs = self.function.get_low_level_il_expr_indexes(self.expr_index) + if self.function.low_level_il is None: return [] result = [] for expr in exprs: - result.append(lowlevelil.LowLevelILInstruction(self._function.low_level_il.ssa_form, expr)) + result.append(lowlevelil.LowLevelILInstruction.create(self.function.low_level_il.ssa_form, expr, None)) return result @property def high_level_il(self) -> Optional[highlevelil.HighLevelILInstruction]: """High level IL form of this expression""" - expr = self._function.get_high_level_il_expr_index(self._expr_index) - if expr is None or self._function.high_level_il is None: + expr = self.function.get_high_level_il_expr_index(self.expr_index) + if expr is None or self.function.high_level_il is None: return None - return highlevelil.HighLevelILInstruction(self._function.high_level_il, expr) + return highlevelil.HighLevelILInstruction.create(self.function.high_level_il, expr) @property def hlil(self) -> Optional[highlevelil.HighLevelILInstruction]: @@ -515,91 +274,58 @@ class MediumLevelILInstruction: @property def hlils(self) -> List[highlevelil.HighLevelILInstruction]: - exprs = self._function.get_high_level_il_expr_indexes(self.expr_index) + exprs = self.function.get_high_level_il_expr_indexes(self.expr_index) result = [] - if self._function.high_level_il is None: + if self.function.high_level_il is None: return result for expr in exprs: - result.append(highlevelil.HighLevelILInstruction(self._function.high_level_il, expr)) + result.append(highlevelil.HighLevelILInstruction.create(self.function.high_level_il, expr)) return result @property def ssa_memory_version(self) -> int: """Version of active memory contents in SSA form for this instruction""" - return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self._function.handle, self._instr_index) + return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index) @property - def prefix_operands(self) -> List[Any]: + def prefix_operands(self) -> List[MediumLevelILOperandType]: """All operands in the expression tree in prefix order""" - result = [MediumLevelILOperationAndSize(self._operation, self._size)] - for operand in self._operands: + result:List[MediumLevelILOperandType] = [MediumLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: if isinstance(operand, MediumLevelILInstruction): - result += operand.prefix_operands + result.extend(operand.prefix_operands) else: result.append(operand) return result @property - def postfix_operands(self) -> List[Any]: + def postfix_operands(self) -> List[MediumLevelILOperandType]: """All operands in the expression tree in postfix order""" - result = [] - for operand in self._operands: + result:List[MediumLevelILOperandType] = [] + for operand in self.operands: if isinstance(operand, MediumLevelILInstruction): - result += operand.postfix_operands + result.extend(operand.postfix_operands) else: result.append(operand) - result.append(MediumLevelILOperationAndSize(self._operation, self._size)) + result.append(MediumLevelILOperationAndSize(self.operation, self.size)) return result @property def vars_written(self) -> List[Union[variable.Variable, SSAVariable]]: """List of variables written by instruction""" - # We use self.__dict__ directly to work around the linter - if self._operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, - MediumLevelILOperation.MLIL_SET_VAR_SSA, MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, - MediumLevelILOperation.MLIL_SET_VAR_ALIASED, MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD, - MediumLevelILOperation.MLIL_VAR_PHI]: - return [self.dest] - elif self._operation in [MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]: - return [self.__dict__['high'], self.__dict__['low']] - elif self._operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, MediumLevelILOperation.MLIL_TAILCALL]: - return self.__dict__['output'] - elif self._operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, - MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, - MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA, - MediumLevelILOperation.MLIL_TAILCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]: - return self.__dict__['output'].vars_written - elif self._operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: - return self.__dict__['dest'] return [] @property - def vars_read(self) -> List[variable.Variable]: + def operands(self) -> Generator[MediumLevelILOperandType, None, None]: + for operand_name in self.operand_names: + assert hasattr(self, operand_name), f"No operand '{operand_name}' from '{self.operand_names}' for instruction {repr(self)}({self.operation})" + yield self.__getattribute__(operand_name) + + @property + def vars_read(self) -> List[Union[variable.Variable, SSAVariable]]: """List of variables read by instruction""" - # We use self.__dict__ directly to work around the linter - if self._operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, - MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SSA, - MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA, MediumLevelILOperation.MLIL_SET_VAR_ALIASED]: - return self.__dict__['src'].vars_read - elif self._operation in [MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, - MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]: - return [self.__dict__['prev']] + self.__dict__['src'].vars_read - elif self._operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, MediumLevelILOperation.MLIL_TAILCALL, - MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_TAILCALL_SSA]: - result = [] - for param in self.__dict__['params']: - result += param.vars_read - return result - elif self._operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED, - MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA]: - return self.__dict__['params'].vars_read - elif self._operation in [MediumLevelILOperation.MLIL_CALL_PARAM, MediumLevelILOperation.MLIL_CALL_PARAM_SSA, - MediumLevelILOperation.MLIL_VAR_PHI]: - return self.__dict__['src'] - elif self._operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: - return [] result = [] - for operand in self._operands: + for operand in self.operands: if (isinstance(operand, variable.Variable)) or (isinstance(operand, SSAVariable)): result.append(operand) elif isinstance(operand, MediumLevelILInstruction): @@ -609,11 +335,11 @@ class MediumLevelILInstruction: @property def expr_type(self) -> Optional['types.Type']: """Type of expression""" - result = core.BNGetMediumLevelILExprType(self._function.handle, self._expr_index) + result = core.BNGetMediumLevelILExprType(self.function.handle, self.expr_index) if result.type: platform = None - if self._function.source_function: - platform = self._function.source_function.platform + if self.function.source_function: + platform = self.function.source_function.platform return types.Type(result.type, platform = platform, confidence = result.confidence) return None @@ -623,8 +349,8 @@ class MediumLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleExprValues(self._function.handle, self._expr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index, option_array, len(options)) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -635,118 +361,118 @@ class MediumLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleSSAVarValues(self._function.handle, var_data, ssa_var.version, - self._instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, + self.instr_index, option_array, len(options)) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_ssa_var_version(self, var:variable.Variable) -> int: var_data = var.to_BNVariable() - return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self._function.handle, var_data, self._instr_index) + return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index) def get_var_for_reg(self, reg:'architecture.RegisterType') -> variable.Variable: - reg = self._function.arch.get_reg_index(reg) - result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self._function.handle, reg, self._instr_index) - return variable.Variable.from_BNVariable(self._function.source_function, result) + reg = self.function.arch.get_reg_index(reg) + result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) + return variable.Variable.from_BNVariable(self.function.source_function, result) def get_var_for_flag(self, flag:'architecture.FlagType') -> variable.Variable: - flag = self._function.arch.get_flag_index(flag) - result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self._function.handle, flag, self._instr_index) - return variable.Variable.from_BNVariable(self._function.source_function, result) + flag = self.function.arch.get_flag_index(flag) + result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) + return variable.Variable.from_BNVariable(self.function.source_function, result) def get_var_for_stack_location(self, offset:int) -> variable.Variable: - result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self._function.handle, offset, self._instr_index) - return variable.Variable.from_BNVariable(self._function.source_function, result) + result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) + return variable.Variable.from_BNVariable(self.function.source_function, result) def get_reg_value(self, reg:'architecture.RegisterType') -> 'variable.RegisterValue': - reg = self._function.arch.get_reg_index(reg) - value = core.BNGetMediumLevelILRegisterValueAtInstruction(self._function.handle, reg, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + reg = self.function.arch.get_reg_index(reg) + value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_reg_value_after(self, reg:'architecture.RegisterType') -> 'variable.RegisterValue': - reg = self._function.arch.get_reg_index(reg) - value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self._function.handle, reg, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + reg = self.function.arch.get_reg_index(reg) + value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_possible_reg_values(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - reg = self._function.arch.get_reg_index(reg) + reg = self.function.arch.get_reg_index(reg) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self._function.handle, reg, self._instr_index, + value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg:'architecture.RegisterType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - reg = self._function.arch.get_reg_index(reg) + reg = self.function.arch.get_reg_index(reg) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self._function.handle, reg, self._instr_index, + value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag:'architecture.FlagType') -> 'variable.RegisterValue': - flag = self._function.arch.get_flag_index(flag) - value = core.BNGetMediumLevelILFlagValueAtInstruction(self._function.handle, flag, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + flag = self.function.arch.get_flag_index(flag) + value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_flag_value_after(self, flag:'architecture.FlagType') -> 'variable.RegisterValue': - flag = self._function.arch.get_flag_index(flag) - value = core.BNGetMediumLevelILFlagValueAfterInstruction(self._function.handle, flag, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + flag = self.function.arch.get_flag_index(flag) + value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_possible_flag_values(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - flag = self._function.arch.get_flag_index(flag) + flag = self.function.arch.get_flag_index(flag) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self._function.handle, flag, self._instr_index, + value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag:'architecture.FlagType', options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': - flag = self._function.arch.get_flag_index(flag) + flag = self.function.arch.get_flag_index(flag) option_array = (ctypes.c_int * len(options))() idx = 0 for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self._function.handle, flag, self._instr_index, + value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset:int, size:int) -> 'variable.RegisterValue': - value = core.BNGetMediumLevelILStackContentsAtInstruction(self._function.handle, offset, size, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_stack_contents_after(self, offset:int, size:int) -> 'variable.RegisterValue': - value = core.BNGetMediumLevelILStackContentsAfterInstruction(self._function.handle, offset, size, self._instr_index) - result = variable.RegisterValue.from_BNRegisterValue(value, self._function.arch) + value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = variable.RegisterValue.from_BNRegisterValue(value, self.function.arch) return result def get_possible_stack_contents(self, offset:int, size:int, @@ -756,9 +482,9 @@ class MediumLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self._function.handle, offset, size, self._instr_index, + value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -769,47 +495,1783 @@ class MediumLevelILInstruction: for option in options: option_array[idx] = option idx += 1 - value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self._function.handle, offset, size, self._instr_index, + value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index, option_array, len(options)) - result = variable.PossibleValueSet(self._function.arch, value) + result = variable.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_branch_dependence(self, branch_instr:int) -> ILBranchDependence: - return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self._function.handle, self._instr_index, branch_instr)) + return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.function.handle, self.instr_index, branch_instr)) @property - def function(self) -> 'MediumLevelILFunction': - return self._function + def operation(self) -> MediumLevelILOperation: + return self.instr.operation @property - def expr_index(self) -> ExpressionIndex: - return self._expr_index + def size(self) -> int: + return self.instr.size @property - def instr_index(self) -> InstructionIndex: - return self._instr_index + def address(self) -> int: + return self.instr.address @property - def operation(self) -> MediumLevelILOperation: - return self._operation + def source_operand(self) -> ExpressionIndex: + return ExpressionIndex(self.instr.source_operand) @property - def size(self) -> int: - return self._size + def core_operands(self) -> OperandsType: + return self.instr.operands + + def get_int(self, operand_index:int) -> int: + value = self.instr.operands[operand_index] + return (value & ((1 << 63) - 1)) - (value & (1 << 63)) + + def get_float(self, operand_index:int) -> float: + value = self.instr.operands[operand_index] + if self.instr.size == 4: + return struct.unpack("f", struct.pack("I", value & 0xffffffff))[0] + elif self.instr.size == 8: + return struct.unpack("d", struct.pack("Q", value))[0] + else: + return float(value) + + def get_expr(self, operand_index:int) -> 'MediumLevelILInstruction': + return MediumLevelILInstruction.create(self.function, + ExpressionIndex(self.instr.operands[operand_index])) + def get_intrinsic(self, operand_index:int) -> 'lowlevelil.ILIntrinsic': + assert self.function.arch is not None, "Attempting to create ILIntrinsic from function with no Architecture" + return lowlevelil.ILIntrinsic(self.function.arch, + architecture.IntrinsicIndex(self.instr.operands[operand_index])) + + def get_var(self, operand_index:int) -> variable.Variable: + value = self.instr.operands[operand_index] + return variable.Variable.from_identifier(self.function.source_function, self.instr.operands[operand_index]) + + def get_var_ssa(self, operand_index1:int, operand_index2:int) -> SSAVariable: + var = variable.Variable.from_identifier(self.function.source_function, self.instr.operands[operand_index1]) + version = self.instr.operands[operand_index2] + return SSAVariable(var, version) + + def get_var_ssa_dest_and_src(self, operand_index1:int, operand_index2:int) -> SSAVariable: + var = variable.Variable.from_identifier(self.function.source_function, self.instr.operands[operand_index1]) + dest_version = self.instr.operands[operand_index2] + return SSAVariable(var, dest_version) + + def get_int_list(self, operand_index:int) -> List[int]: + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index, count) + assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" + value:List[int] = [] + try: + for j in range(count.value): + value.append(operand_list[j]) + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + def get_var_list(self, operand_index1:int, operand_index2:int) -> List[variable.Variable]: + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" + value:List[variable.Variable] = [] + try: + for j in range(count.value): + value.append(variable.Variable.from_identifier(self.function.source_function, operand_list[j])) + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + def get_var_ssa_list(self, operand_index1:int, _:int) -> List[SSAVariable]: + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" + value = [] + try: + for j in range(count.value // 2): + var_id = operand_list[j * 2] + var_version = operand_list[(j * 2) + 1] + value.append(SSAVariable(variable.Variable.from_identifier(self.function.source_function, + var_id), var_version)) + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + def get_expr_list(self, operand_index1:int, _:int) -> List['MediumLevelILInstruction']: + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" + value:List['MediumLevelILInstruction'] = [] + try: + for j in range(count.value): + value.append(MediumLevelILInstruction.create(self.function, operand_list[j], None)) + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + def get_target_map(self, operand_index1:int, _:int) -> Mapping[int, int]: + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(self.function.handle, self.expr_index, operand_index1, count) + assert operand_list is not None, "core.BNMediumLevelILGetOperandList returned None" + value:Mapping[int, int] = {} + try: + for j in range(count.value // 2): + key = operand_list[j * 2] + target = operand_list[(j * 2) + 1] + value[key] = target + return value + finally: + core.BNMediumLevelILFreeOperandList(operand_list) + + +@dataclass(frozen=True, repr=False) +class Arithmetic(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Memory(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class ControlFlow(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Call(ControlFlow): @property - def address(self) -> int: - return self._address + def output(self) -> List[Union[SSAVariable, variable.Variable]]: + return NotImplemented @property - def source_operand(self) -> ExpressionIndex: - return self._source_operand + def vars_written(self) -> List[Union[SSAVariable, variable.Variable]]: + return self.output + + @property + def params(self) -> List[Union[SSAVariable, variable.Variable]]: + return NotImplemented + + @property + def vars_read(self) -> List[Union[SSAVariable, variable.Variable]]: + result = [] + for param in self.params: + if isinstance(param, MediumLevelILInstruction): + result.extend(param.vars_read) + elif isinstance(param, (variable.Variable, SSAVariable)): + result.append(param) + else: + assert False, "Call.params returned object other than Variable, SSAVariable or MediumLevelILInstruction" + return result + +@dataclass(frozen=True, repr=False) +class UnaryOperation(MediumLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class BinaryOperation(MediumLevelILInstruction): + operand_names = tuple(["left", "right"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class Carry(Arithmetic): + operand_names = tuple(["left", "right", "carry"]) + + @property + def left(self): + return self.get_expr(0) + + @property + def right(self): + return self.get_expr(1) + + @property + def carry(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class Comparison(BinaryOperation): + pass + + +@dataclass(frozen=True, repr=False) +class Constant(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Store(Memory): + pass + + +@dataclass(frozen=True, repr=False) +class Load(Memory): + pass + + +@dataclass(frozen=True, repr=False) +class RegisterStack(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class SSA(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Phi(SSA): + pass + + +@dataclass(frozen=True, repr=False) +class SetVar(MediumLevelILInstruction): + @property + def src(self) -> Union[MediumLevelILInstruction, List[Union[SSAVariable, variable.Variable]]]: + return NotImplemented + + @property + def dest(self) -> Union[SSAVariable, variable.Variable]: + return NotImplemented + + @property + def vars_written(self) -> List[Union[SSAVariable, variable.Variable]]: + d = self.dest + if isinstance(d, list): + return d + return [d] + + @property + def vars_read(self) -> List[Union[SSAVariable, variable.Variable]]: + result = [] + src = self.src + if isinstance(src, MediumLevelILInstruction): + return src.vars_read + + for i in src: + if isinstance(i, (variable.Variable, SSAVariable)): + result.append(i) + else: + assert False, "SetVar.src returned object other than, Variable, SSAVariable" + return result + +@dataclass(frozen=True, repr=False) +class FloatingPoint(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class Terminal(ControlFlow): + pass + + +@dataclass(frozen=True, repr=False) +class Return(Terminal): + pass + + +@dataclass(frozen=True, repr=False) +class Signed(MediumLevelILInstruction): + pass + + +@dataclass(frozen=True, repr=False) +class DoublePrecision(Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class Syscall(Call): + pass + + +@dataclass(frozen=True, repr=False) +class Tailcall(Call, Terminal): + pass + +@dataclass(frozen=True, repr=False) +class MediumLevelILNop(MediumLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class MediumLevelILNoret(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class MediumLevelILBp(Terminal): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class MediumLevelILUndef(MediumLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class MediumLevelILUnimpl(MediumLevelILInstruction): + operand_names = tuple() + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLoad(Load): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar(MediumLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_var(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAddress_of(MediumLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_var(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILConst(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILConst_ptr(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFloat_const(Constant, FloatingPoint): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_float(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILImport(Constant): + operand_names = tuple(["constant"]) + + @property + def constant(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILNeg(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILNot(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSx(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILZx(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLow_part(UnaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILJump(Terminal): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRet_hint(ControlFlow): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_output(MediumLevelILInstruction): + operand_names = tuple(["dest"]) + + @property + def dest(self) -> List[variable.Variable]: + return self.get_var_list(0, 1) + + @property + def vars_written(self) -> List[variable.Variable]: + return self.dest + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_param(MediumLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_var_list(0, 1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRet(Return): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr_list(0, 1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILGoto(Terminal): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILBool_to_int(MediumLevelILInstruction): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFree_var_slot(RegisterStack): + operand_names = tuple(["dest"]) + + @property + def dest(self): + return self.get_var(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTrap(Terminal): + operand_names = tuple(["vector"]) + + @property + def vector(self): + return self.get_int(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFree_var_slot_ssa(RegisterStack): + operand_names = tuple(["dest", "prev"]) + + @property + def dest(self): + return self.get_var_ssa_dest_and_src(0, 1) + + @property + def prev(self): + return self.get_var_ssa_dest_and_src(0, 2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILUnimpl_mem(Memory): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_expr(0) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFsqrt(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFneg(UnaryOperation, Arithmetic, FloatingPoint): + pass + +@dataclass(frozen=True, repr=False) +class MediumLevelILFabs(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFloat_to_int(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILInt_to_float(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFloat_conv(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRound_to_int(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFloor(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCeil(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFtrunc(UnaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_ssa(SSA): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_var_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_aliased(SSA): + operand_names = tuple(["src"]) + + @property + def src(self): + return self.get_var_ssa(0, 1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var(SetVar): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLoad_struct(Load): + operand_names = tuple(["src", "offset"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILStore(Store): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def src(self): + return self.get_expr(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_field(MediumLevelILInstruction): + operand_names = tuple(["src", "offset"]) + + @property + def src(self): + return self.get_var(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_split(MediumLevelILInstruction): + operand_names = tuple(["high", "low"]) + + @property + def high(self): + return self.get_var(0) + + @property + def low(self): + return self.get_var(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAddress_of_field(MediumLevelILInstruction): + operand_names = tuple(["src", "offset"]) + + @property + def src(self): + return self.get_var(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILExtern_ptr(Constant): + operand_names = tuple(["constant", "offset"]) + + @property + def constant(self): + return self.get_int(0) + + @property + def offset(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAdd(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSub(BinaryOperation, Arithmetic): + pass + +@dataclass(frozen=True, repr=False) +class MediumLevelILAnd(BinaryOperation, Arithmetic): + pass + +@dataclass(frozen=True, repr=False) +class MediumLevelILOr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILXor(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLsl(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLsr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAsr(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRol(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRor(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMul(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMulu_dp(BinaryOperation, DoublePrecision): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMuls_dp(BinaryOperation, DoublePrecision, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILDivu(BinaryOperation, Arithmetic): + pass + +@dataclass(frozen=True, repr=False) +class MediumLevelILDivu_dp(BinaryOperation, DoublePrecision): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILDivs(BinaryOperation, Arithmetic, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILDivs_dp(BinaryOperation, DoublePrecision, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILModu(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILModu_dp(BinaryOperation, DoublePrecision): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMods(BinaryOperation, Arithmetic, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMods_dp(BinaryOperation, DoublePrecision, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_e(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_ne(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_slt(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_ult(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_sle(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_ule(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_sge(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_uge(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_sgt(Comparison, Signed): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCmp_ugt(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTest_bit(Comparison): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAdd_overflow(BinaryOperation, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSyscall(Syscall): + operand_names = tuple(["output", "params"]) + + @property + def output(self): + return self.get_var_list(0, 1) + + @property + def params(self): + return self.get_expr_list(2, 3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_ssa_field(SSA): + operand_names = tuple(["src", "offset"]) + + @property + def src(self): + return self.get_var_ssa(0, 1) + + @property + def offset(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_aliased_field(SSA): + operand_names = tuple(["src", "offset"]) + + @property + def src(self): + return self.get_var_ssa(0, 1) + + @property + def offset(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_split_ssa(SSA): + operand_names = tuple(["high", "low"]) + + @property + def high(self): + return self.get_var_ssa(0, 1) + + @property + def low(self): + return self.get_var_ssa(2, 3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_output_ssa(SSA): + operand_names = tuple(["dest_memory", "dest"]) + + @property + def dest_memory(self): + return self.get_int(0) + + @property + def dest(self) -> List[SSAVariable]: + return self.get_var_ssa_list(1, 2) + + @property + def vars_written(self) -> List[SSAVariable]: + return self.dest + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_param_ssa(SSA): + operand_names = tuple(["src_memory", "src"]) + + @property + def src_memory(self): + return self.get_int(0) + + @property + def src(self): + return self.get_var_ssa_list(1, 2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLoad_ssa(Load, SSA): + operand_names = tuple(["src", "src_memory"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def src_memory(self): + return self.get_int(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILVar_phi(Phi, SetVar, SSA): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var_ssa(0, 1) + + @property + def src(self): + return self.get_var_ssa_list(2, 3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILMem_phi(Memory, Phi): + operand_names = tuple(["dest_memory", "src_memory"]) + + @property + def dest_memory(self): + return self.get_int(0) + + @property + def src_memory(self): + return self.get_int_list(1) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_ssa(SetVar): + operand_names = tuple(["dest", "src"]) + + @property + def dest(self): + return self.get_var_ssa(0, 1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_e(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_ne(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_lt(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_le(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_ge(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_gt(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_o(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFcmp_uo(Comparison, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFadd(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFsub(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFmul(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILFdiv(BinaryOperation, Arithmetic, FloatingPoint): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILJump_to(Terminal): + operand_names = tuple(["dest", "targets"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def targets(self): + return self.get_target_map(1, 2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_aliased(SetVar, SSA): + operand_names = tuple(["dest", "prev", "src"]) + + @property + def dest(self): + return self.get_var_ssa_dest_and_src(0, 1) + + @property + def prev(self): + return self.get_var_ssa_dest_and_src(0, 2) + + @property + def src(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSyscall_untyped(Syscall): + operand_names = tuple(["output", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output), "MediumLevelILCall_untyped return bad type for 'output'" + return inst.dest + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + inst = self.get_expr(2) + assert isinstance(inst, MediumLevelILCall_param), "MediumLevelILCall_untyped return bad type for 'params'" + return inst.src + + @property + def stack(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILIntrinsic(MediumLevelILInstruction): + operand_names = tuple(["output", "intrinsic", "params"]) + + @property + def output(self): + return self.get_var_list(0, 1) + + @property + def intrinsic(self): + return self.get_intrinsic(2) + + @property + def params(self): + return self.get_expr_list(3, 4) + + @property + def vars_read(self) -> List[variable.Variable]: + #return self.params + return [] + + @property + def vars_written(self) -> List[variable.Variable]: + #return self.output + return [] + + +@dataclass(frozen=True, repr=False) +class MediumLevelILIntrinsic_ssa(SSA): + operand_names = tuple(["output", "intrinsic", "params"]) + + @property + def output(self): + return self.get_var_ssa_list(0, 1) + + @property + def intrinsic(self): + return self.get_intrinsic(2) + + @property + def params(self): + return self.get_expr_list(3, 4) + + @property + def vars_read(self) -> List[SSAVariable]: + # return self.params + return [] + + @property + def vars_written(self) -> List[SSAVariable]: + # return self.output + return [] + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_ssa_field(SetVar): + operand_names = tuple(["dest", "prev", "offset", "src"]) + + @property + def dest(self): + return self.get_var_ssa_dest_and_src(0, 1) + + @property + def prev(self): + return self.get_var_ssa_dest_and_src(0, 2) + + @property + def offset(self): + return self.get_int(3) + + @property + def src(self): + return self.get_expr(4) + + @property + def vars_read(self) -> List[SSAVariable]: + return [self.prev, *self.src.vars_read] # type: ignore we're guaranteed not to return non-SSAVariables here + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_split_ssa(SetVar): + operand_names = tuple(["high", "low", "src"]) + + @property + def high(self): + return self.get_var_ssa(0, 1) + + @property + def low(self): + return self.get_var_ssa(2, 3) + + @property + def src(self): + return self.get_expr(4) + + @property + def vars_written(self) -> List[SSAVariable]: + return [self.high, self.low] + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_aliased_field(SetVar, SSA): + operand_names = tuple(["dest", "prev", "offset", "src"]) + + @property + def dest(self): + return self.get_var_ssa_dest_and_src(0, 1) + + @property + def prev(self): + return self.get_var_ssa_dest_and_src(0, 2) + + @property + def offset(self): + return self.get_int(3) + + @property + def src(self): + return self.get_expr(4) + + @property + def vars_read(self) -> List[SSAVariable]: + return [self.prev, *self.src.vars_read] # type: ignore we're guaranteed not to return non-SSAVariables here + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSyscall_ssa(Syscall, SSA): + operand_names = tuple(["output", "params", "src_memory"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILSyscall_ssa return bad type for output" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILSyscall_ssa return bad type for output" + return inst.dest_memory + + @property + def params(self): + return self.get_expr_list(1, 2) + + @property + def src_memory(self): + return self.get_int(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSyscall_untyped_ssa(Syscall, SSA): + operand_names = tuple(["output", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILSyscall_untyped_ssa return bad type for 'output'" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILSyscall_untyped_ssa return bad type for 'output_dest_memory'" + return inst.dest_memory + + @property + def params(self): + inst = self.get_expr(1) + assert isinstance(inst, MediumLevelILCall_param_ssa), "MediumLevelILSyscall_untyped_ssa return bad type for 'params'" + return inst.src + + @property + def params_src_memory(self): + inst = self.get_expr(1) + assert isinstance(inst, MediumLevelILCall_param_ssa), "MediumLevelILSyscall_untyped_ssa return bad type for 'params_src_memory'" + return inst.src_memory + + @property + def stack(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILLoad_struct_ssa(Load, SSA): + operand_names = tuple(["src", "offset", "src_memory"]) + + @property + def src(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def src_memory(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_field(SetVar): + operand_names = tuple(["dest", "offset", "src"]) + + @property + def dest(self): + return self.get_var(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSet_var_split(SetVar): + operand_names = tuple(["high", "low", "src"]) + + @property + def high(self): + return self.get_var(0) + + @property + def low(self): + return self.get_var(1) + + @property + def src(self): + return self.get_expr(2) + + @property + def vars_written(self) -> List[variable.Variable]: + return [self.high, self.low] + + +@dataclass(frozen=True, repr=False) +class MediumLevelILStore_struct(Store): + operand_names = tuple(["dest", "offset", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def src(self): + return self.get_expr(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILAdc(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILSbb(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRlc(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILRrc(Carry): + pass + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall(Call): + operand_names = tuple(["output", "dest", "params"]) + + @property + def output(self): + return self.get_var_list(0, 1) + + @property + def dest(self): + return self.get_expr(2) + + @property + def params(self): + return self.get_expr_list(3, 4) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILIf(Terminal): + operand_names = tuple(["condition", "true", "false"]) + + @property + def condition(self): + return self.get_expr(0) + + @property + def true(self): + return self.get_int(1) + + @property + def false(self): + return self.get_int(2) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTailcall_untyped(Tailcall): + operand_names = tuple(["output", "dest", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output), "MediumLevelILTailcall_untyped return bad type for 'output'" + return inst.dest + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + inst = self.get_expr(2) + assert isinstance(inst, MediumLevelILCall_param), "MediumLevelILTailcall_untyped return bad type for 'params'" + return inst.src + + @property + def stack(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_ssa(Call, SSA): + operand_names = tuple(["output", "dest", "params", "src_memory"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILCall_ssa return bad type for output" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILCall_ssa return bad type for output" + return inst.dest_memory + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + return self.get_expr_list(2, 3) + + @property + def src_memory(self): + return self.get_int(4) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_untyped_ssa(Call, SSA): + operand_names = tuple(["output", "dest", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILCall_untyped_ssa return bad type for output" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILCall_untyped_ssa return bad type for output" + return inst.dest_memory + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + inst = self.get_expr(2) + assert isinstance(inst, MediumLevelILCall_param_ssa), "MediumLevelILCall_untyped_ssa return bad type for 'params'" + return inst.src + + @property + def params_src_memory(self): + inst = self.get_expr(2) + assert isinstance(inst, MediumLevelILCall_param_ssa), "MediumLevelILCall_untyped_ssa return bad type for 'params_src_memory'" + return inst.src_memory + + @property + def stack(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTailcall(Tailcall): + operand_names = tuple(["output", "dest", "params"]) + + @property + def output(self): + return self.get_var_list(0, 1) + + @property + def dest(self): + return self.get_expr(2) + + @property + def params(self): + return self.get_expr_list(3, 4) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTailcall_ssa(Tailcall, SSA): + operand_names = tuple(["output", "dest", "params", "src_memory"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILTailcall_ssa return bad type for output" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILTailcall_ssa return bad type for output" + return inst.dest_memory + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + return self.get_expr_list(2, 3) + + @property + def src_memory(self): + return self.get_int(4) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILTailcall_untyped_ssa(Tailcall, SSA): + operand_names = tuple(["output", "dest", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILTailcall_untyped_ssa return bad type for 'output'" + return inst.dest + + @property + def output_dest_memory(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output_ssa), "MediumLevelILTailcall_untyped_ssa return bad type for 'output'" + return inst.dest_memory + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + return self.get_expr(2) + + @property + def stack(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILStore_ssa(Store, SSA): + operand_names = tuple(["dest", "dest_memory", "src_memory", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def dest_memory(self): + return self.get_int(1) + + @property + def src_memory(self): + return self.get_int(2) + + @property + def src(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILCall_untyped(Call): + operand_names = tuple(["output", "dest", "params", "stack"]) + + @property + def output(self): + inst = self.get_expr(0) + assert isinstance(inst, MediumLevelILCall_output), "MediumLevelILCall_untyped return bad type for 'output'" + return inst.dest + + @property + def dest(self): + return self.get_expr(1) + + @property + def params(self): + inst = self.get_expr(2) + assert isinstance(inst, MediumLevelILCall_param), "MediumLevelILCall_untyped return bad type for 'params'" + return inst.src + + @property + def stack(self): + return self.get_expr(3) + + +@dataclass(frozen=True, repr=False) +class MediumLevelILStore_struct_ssa(Store, SSA): + operand_names = tuple(["dest", "offset", "dest_memory", "src_memory", "src"]) + + @property + def dest(self): + return self.get_expr(0) + + @property + def offset(self): + return self.get_int(1) + + @property + def dest_memory(self): + return self.get_int(2) + + @property + def src_memory(self): + return self.get_int(3) @property - def operands(self) -> List[Any]: - return self._operands + def src(self): + return self.get_expr(4) +ILInstruction = { + MediumLevelILOperation.MLIL_NOP:MediumLevelILNop, # [], + MediumLevelILOperation.MLIL_NORET:MediumLevelILNoret, # [], + MediumLevelILOperation.MLIL_BP:MediumLevelILBp, # [], + MediumLevelILOperation.MLIL_UNDEF:MediumLevelILUndef, # [], + MediumLevelILOperation.MLIL_UNIMPL:MediumLevelILUnimpl, # [], + MediumLevelILOperation.MLIL_LOAD:MediumLevelILLoad, # [("src", "expr")], + MediumLevelILOperation.MLIL_VAR:MediumLevelILVar, # [("src", "var")], + MediumLevelILOperation.MLIL_ADDRESS_OF:MediumLevelILAddress_of, # [("src", "var")], + MediumLevelILOperation.MLIL_CONST:MediumLevelILConst, # [("constant", "int")], + MediumLevelILOperation.MLIL_CONST_PTR:MediumLevelILConst_ptr, # [("constant", "int")], + MediumLevelILOperation.MLIL_FLOAT_CONST:MediumLevelILFloat_const, # [("constant", "float")], + MediumLevelILOperation.MLIL_IMPORT:MediumLevelILImport, # [("constant", "int")], + MediumLevelILOperation.MLIL_SET_VAR:MediumLevelILSet_var, # [("dest", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_LOAD_STRUCT:MediumLevelILLoad_struct, # [("src", "expr"), ("offset", "int")], + MediumLevelILOperation.MLIL_STORE:MediumLevelILStore, # [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_FIELD:MediumLevelILVar_field, # [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_SPLIT:MediumLevelILVar_split, # [("high", "var"), ("low", "var")], + MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD:MediumLevelILAddress_of_field, # [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_EXTERN_PTR:MediumLevelILExtern_ptr, # [("constant", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_ADD:MediumLevelILAdd, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SUB:MediumLevelILSub, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_AND:MediumLevelILAnd, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_OR:MediumLevelILOr, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_XOR:MediumLevelILXor, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSL:MediumLevelILLsl, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSR:MediumLevelILLsr, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ASR:MediumLevelILAsr, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROL:MediumLevelILRol, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROR:MediumLevelILRor, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MUL:MediumLevelILMul, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULU_DP:MediumLevelILMulu_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULS_DP:MediumLevelILMuls_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU:MediumLevelILDivu, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU_DP:MediumLevelILDivu_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS:MediumLevelILDivs, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS_DP:MediumLevelILDivs_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU:MediumLevelILModu, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU_DP:MediumLevelILModu_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS:MediumLevelILMods, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS_DP:MediumLevelILMods_dp, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_NEG:MediumLevelILNeg, # [("src", "expr")], + MediumLevelILOperation.MLIL_NOT:MediumLevelILNot, # [("src", "expr")], + MediumLevelILOperation.MLIL_SX:MediumLevelILSx, # [("src", "expr")], + MediumLevelILOperation.MLIL_ZX:MediumLevelILZx, # [("src", "expr")], + MediumLevelILOperation.MLIL_LOW_PART:MediumLevelILLow_part, # [("src", "expr")], + MediumLevelILOperation.MLIL_JUMP:MediumLevelILJump, # [("dest", "expr")], + MediumLevelILOperation.MLIL_RET_HINT:MediumLevelILRet_hint, # [("dest", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT:MediumLevelILCall_output, # [("dest", "var_list")], + MediumLevelILOperation.MLIL_CALL_PARAM:MediumLevelILCall_param, # [("src", "var_list")], + MediumLevelILOperation.MLIL_RET:MediumLevelILRet, # [("src", "expr_list")], + MediumLevelILOperation.MLIL_GOTO:MediumLevelILGoto, # [("dest", "int")], + MediumLevelILOperation.MLIL_BOOL_TO_INT:MediumLevelILBool_to_int, # [("src", "expr")], + MediumLevelILOperation.MLIL_FREE_VAR_SLOT:MediumLevelILFree_var_slot, # [("dest", "var")], + MediumLevelILOperation.MLIL_TRAP:MediumLevelILTrap, # [("vector", "int")], + MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA:MediumLevelILFree_var_slot_ssa, # [("prev", "var_ssa_dest_and_src")], + MediumLevelILOperation.MLIL_UNIMPL_MEM:MediumLevelILUnimpl_mem, # [("src", "expr")], + MediumLevelILOperation.MLIL_FSQRT:MediumLevelILFsqrt, # [("src", "expr")], + MediumLevelILOperation.MLIL_FNEG:MediumLevelILFneg, # [("src", "expr")], + MediumLevelILOperation.MLIL_FABS:MediumLevelILFabs, # [("src", "expr")], + MediumLevelILOperation.MLIL_FLOAT_TO_INT:MediumLevelILFloat_to_int, # [("src", "expr")], + MediumLevelILOperation.MLIL_INT_TO_FLOAT:MediumLevelILInt_to_float, # [("src", "expr")], + MediumLevelILOperation.MLIL_FLOAT_CONV:MediumLevelILFloat_conv, # [("src", "expr")], + MediumLevelILOperation.MLIL_ROUND_TO_INT:MediumLevelILRound_to_int, # [("src", "expr")], + MediumLevelILOperation.MLIL_FLOOR:MediumLevelILFloor, # [("src", "expr")], + MediumLevelILOperation.MLIL_CEIL:MediumLevelILCeil, # [("src", "expr")], + MediumLevelILOperation.MLIL_FTRUNC:MediumLevelILFtrunc, # [("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SSA:MediumLevelILVar_ssa, # [("src", "var_ssa")], + MediumLevelILOperation.MLIL_VAR_ALIASED:MediumLevelILVar_aliased, # [("src", "var_ssa")], + MediumLevelILOperation.MLIL_CMP_E:MediumLevelILCmp_e, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_NE:MediumLevelILCmp_ne, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLT:MediumLevelILCmp_slt, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULT:MediumLevelILCmp_ult, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLE:MediumLevelILCmp_sle, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULE:MediumLevelILCmp_ule, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGE:MediumLevelILCmp_sge, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGE:MediumLevelILCmp_uge, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGT:MediumLevelILCmp_sgt, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGT:MediumLevelILCmp_ugt, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_TEST_BIT:MediumLevelILTest_bit, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADD_OVERFLOW:MediumLevelILAdd_overflow, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SYSCALL:MediumLevelILSyscall, # [("output", "var_list"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_VAR_SSA_FIELD:MediumLevelILVar_ssa_field, # [("src", "var_ssa"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD:MediumLevelILVar_aliased_field, # [("src", "var_ssa"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_SPLIT_SSA:MediumLevelILVar_split_ssa, # [("high", "var_ssa"), ("low", "var_ssa")], + MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA:MediumLevelILCall_output_ssa, # [("dest_memory", "int"), ("dest", "var_ssa_list")], + MediumLevelILOperation.MLIL_CALL_PARAM_SSA:MediumLevelILCall_param_ssa, # [("src_memory", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_LOAD_SSA:MediumLevelILLoad_ssa, # [("src", "expr"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_VAR_PHI:MediumLevelILVar_phi, # [("dest", "var_ssa"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_MEM_PHI:MediumLevelILMem_phi, # [("dest_memory", "int"), ("src_memory", "int_list")], + MediumLevelILOperation.MLIL_SET_VAR_SSA:MediumLevelILSet_var_ssa, # [("dest", "var_ssa"), ("src", "expr")], + MediumLevelILOperation.MLIL_FCMP_E:MediumLevelILFcmp_e, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_NE:MediumLevelILFcmp_ne, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_LT:MediumLevelILFcmp_lt, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_LE:MediumLevelILFcmp_le, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_GE:MediumLevelILFcmp_ge, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_GT:MediumLevelILFcmp_gt, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_O:MediumLevelILFcmp_o, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_UO:MediumLevelILFcmp_uo, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FADD:MediumLevelILFadd, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FSUB:MediumLevelILFsub, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FMUL:MediumLevelILFmul, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FDIV:MediumLevelILFdiv, # [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_JUMP_TO:MediumLevelILJump_to, # [("dest", "expr"), ("targets", "target_map")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED:MediumLevelILSet_var_aliased, # [("prev", "var_ssa_dest_and_src"), ("src", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED:MediumLevelILSyscall_untyped, # [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_TAILCALL:MediumLevelILTailcall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_INTRINSIC:MediumLevelILIntrinsic, # [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_INTRINSIC_SSA:MediumLevelILIntrinsic_ssa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD:MediumLevelILSet_var_ssa_field, # [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA:MediumLevelILSet_var_split_ssa, # [("high", "var_ssa"), ("low", "var_ssa"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD:MediumLevelILSet_var_aliased_field, # [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_SSA:MediumLevelILSyscall_ssa, # [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA:MediumLevelILSyscall_untyped_ssa, # [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_LOAD_STRUCT_SSA:MediumLevelILLoad_struct_ssa, # [("src", "expr"), ("offset", "int"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_SET_VAR_FIELD:MediumLevelILSet_var_field, # [("dest", "var"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT:MediumLevelILSet_var_split, # [("high", "var"), ("low", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT:MediumLevelILStore_struct, # [("dest", "expr"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_ADC:MediumLevelILAdc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + MediumLevelILOperation.MLIL_SBB:MediumLevelILSbb, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + MediumLevelILOperation.MLIL_RLC:MediumLevelILRlc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + MediumLevelILOperation.MLIL_RRC:MediumLevelILRrc, # [("left", "expr"), ("right", "expr"), ("carry", "expr")], + MediumLevelILOperation.MLIL_TAILCALL_UNTYPED:MediumLevelILTailcall_untyped, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_CALL_SSA:MediumLevelILCall_ssa, # [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA:MediumLevelILCall_untyped_ssa, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_TAILCALL_SSA:MediumLevelILTailcall_ssa, # [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_TAILCALL_UNTYPED_SSA:MediumLevelILTailcall_untyped_ssa, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_CALL:MediumLevelILCall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_IF:MediumLevelILIf, # [("condition", "expr"), ("true", "int"), ("false", "int")], + MediumLevelILOperation.MLIL_STORE_SSA:MediumLevelILStore_ssa, # [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_CALL_UNTYPED:MediumLevelILCall_untyped, # [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_STORE_STRUCT_SSA:MediumLevelILStore_struct_ssa, # [("dest", "expr"), ("offset", "int"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], +} class MediumLevelILExpr: """ @@ -887,11 +2349,11 @@ class MediumLevelILFunction: def __hash__(self): return hash(('MLIL', self._source_function)) - def __getitem__(self, i): + def __getitem__(self, i) -> 'MediumLevelILInstruction': if isinstance(i, slice) or isinstance(i, tuple): raise IndexError("expected integer instruction index") if isinstance(i, MediumLevelILExpr): - return MediumLevelILInstruction(self, i.index) + return MediumLevelILInstruction.create(self, i.index) # for backwards compatibility if isinstance(i, MediumLevelILInstruction): return i @@ -899,7 +2361,7 @@ class MediumLevelILFunction: raise IndexError("index out of range") if i < 0: i = len(self) + i - return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + return MediumLevelILInstruction.create(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) def __setitem__(self, i, j): raise IndexError("instruction modification not implemented") |
