diff options
Diffstat (limited to 'python/highlevelil.py')
| -rw-r--r-- | python/highlevelil.py | 429 |
1 files changed, 235 insertions, 194 deletions
diff --git a/python/highlevelil.py b/python/highlevelil.py index 45f6def4..71c58920 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -20,21 +20,28 @@ import ctypes import struct -from typing import List +from typing import Optional, Generator, List, Union, Any, NewType # Binary Ninja components -import binaryninja -from binaryninja import _binaryninjacore as core -from binaryninja.enums import HighLevelILOperation, FunctionGraphType -from binaryninja import function -from binaryninja import lowlevelil -from binaryninja import mediumlevelil -from binaryninja import basicblock -from binaryninja import types - -# 2-3 compatibility -from binaryninja import range +from . import _binaryninjacore as core +from .enums import HighLevelILOperation, InstructionTextTokenType, DataFlowQueryOption, FunctionGraphType +from .variable import Variable +from . import function +from . import binaryview +from . import architecture +from . import lowlevelil +from . import mediumlevelil +from . import basicblock +from . import types +from . import highlight +from . import flowgraph +from . import variable +LinesType = Generator['function.DisassemblyTextLine', None, None] +ExpressionIndex = NewType('ExpressionIndex', int) +InstructionIndex = NewType('InstructionIndex', int) +HLILInstructionsType = Generator['HighLevelILInstruction', None, None] +HLILBasicBlocksType = Generator['HighLevelILBasicBlock', None, None] class HighLevelILOperationAndSize(object): def __init__(self, operation, size): @@ -63,7 +70,6 @@ class HighLevelILOperationAndSize(object): @property def operation(self): - """ """ return self._operation @operation.setter @@ -72,7 +78,6 @@ class HighLevelILOperationAndSize(object): @property def size(self): - """ """ return self._size @size.setter @@ -241,9 +246,12 @@ class HighLevelILInstruction(object): HighLevelILOperation.HLIL_FCMP_UO: [("left", "expr"), ("right", "expr")] } - def __init__(self, func, expr_index, as_ast = True, instr_index = None): + def __init__(self, func:'HighLevelILFunction', expr_index:ExpressionIndex, as_ast:bool = True, + instr_index:InstructionIndex = None): 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 if instr_index is None: self._instr_index = core.BNGetHighLevelILInstructionForExpr(func.handle, expr_index) @@ -260,6 +268,7 @@ class HighLevelILInstruction(object): 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)) @@ -275,15 +284,16 @@ class HighLevelILInstruction(object): elif operand_type == "intrinsic": value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) elif operand_type == "var": - value = function.Variable.from_identifier(self._function.source_function, instr.operands[i]) + value = variable.Variable.from_identifier(self._function.source_function, instr.operands[i]) elif operand_type == "var_ssa": - var = function.Variable.from_identifier(self._function.source_function, instr.operands[i]) + 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]) @@ -291,6 +301,7 @@ class HighLevelILInstruction(object): 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): @@ -299,12 +310,13 @@ class HighLevelILInstruction(object): 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(function.Variable.from_identifier(self._function.source_function, + 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": @@ -336,9 +348,9 @@ class HighLevelILInstruction(object): first_line = "<invalid>" else: first_line = "" - for token in lines[0].tokens: + for token in next(lines).tokens: first_line += token.text - if len(lines) > 1: + if len(list(lines)) > 1: continuation = "..." return "<%s: %s%s>" % (self._operation.name, first_line, continuation) @@ -376,25 +388,26 @@ class HighLevelILInstruction(object): return hash((self._function, self._expr_index)) @property - def lines(self): + 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) - result = [] - for i in range(0, count.value): - addr = lines[i].addr - if lines[i].instrIndex != 0xffffffffffffffff: - il_instr = self._function[lines[i].instrIndex] - else: - il_instr = None - color = binaryninja.highlight.HighlightColor._from_core_struct(lines[i].highlight) - tokens = binaryninja.function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count) - result.append(binaryninja.function.DisassemblyTextLine(tokens, addr, il_instr, color)) - core.BNFreeDisassemblyTextLines(lines, count.value) - return result + 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] + else: + il_instr = None + color = highlight.HighlightColor._from_core_struct(lines[i].highlight) + tokens = function.InstructionTextToken._from_core_struct(lines[i].tokens, lines[i].count) + yield function.DisassemblyTextLine(tokens, addr, il_instr, color) + finally: + core.BNFreeDisassemblyTextLines(lines, count.value) @property - def prefix_operands(self): + def prefix_operands(self) -> List[Any]: """All operands in the expression tree in prefix order""" result = [HighLevelILOperationAndSize(self._operation, self._size)] for operand in self._operands: @@ -405,7 +418,7 @@ class HighLevelILInstruction(object): return result @property - def postfix_operands(self): + def postfix_operands(self) -> List[Any]: """All operands in the expression tree in postfix order""" result = [] for operand in self._operands: @@ -417,141 +430,144 @@ class HighLevelILInstruction(object): return result @property - def function(self): - """ """ + def function(self) -> 'HighLevelILFunction': return self._function @property - def expr_index(self): - """ """ + def expr_index(self) -> ExpressionIndex: return self._expr_index @expr_index.setter - def expr_index(self, value): + def expr_index(self, value:ExpressionIndex) -> None: self._expr_index = value @property - def instr_index(self): + 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): + def instr(self) -> 'HighLevelILInstruction': """The statement that this expression belongs to (read-only)""" return self._function[self.instr_index] @property - def ast(self): + def ast(self) -> 'HighLevelILInstruction': """This expression with full AST printing (read-only)""" if self._as_ast: return self return HighLevelILInstruction(self._function, self._expr_index, True) @property - def non_ast(self): + def non_ast(self) -> 'HighLevelILInstruction': """This expression without full AST printing (read-only)""" if not self._as_ast: return self return HighLevelILInstruction(self._function, self._expr_index, False) @property - def operation(self): - """ """ + def operation(self) -> HighLevelILOperation: return self._operation @operation.setter - def operation(self, value): + def operation(self, value:HighLevelILOperation) -> None: self._operation = value @property - def size(self): - """ """ + def size(self) -> int: return self._size @size.setter - def size(self, value): + def size(self, value:int) -> None: self._size = value @property - def address(self): - """ """ + def address(self) -> int: return self._address @address.setter - def address(self, value): + def address(self, value:int) -> None: self._address = value @property def source_operand(self): - """ """ - return self._source_operand + return self._source_operand @source_operand.setter def source_operand(self, value): self._source_operand = value @property - def operands(self): - """ """ + def operands(self) -> Any: return self._operands @operands.setter - def operands(self, value): + def operands(self, value: Any): self._operands = value @property - def parent(self): + def parent(self) -> Optional['HighLevelILInstruction']: if self._parent >= core.BNGetHighLevelILExprCount(self._function.handle): return None return HighLevelILInstruction(self._function, self._parent, self._as_ast) @property - def ssa_form(self): + 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) @property - def non_ssa_form(self): + def non_ssa_form(self) -> Optional['HighLevelILInstruction']: """Non-SSA form of expression (read-only)""" + 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) @property - def medium_level_il(self): + 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) if expr is None: return None - return mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il.ssa_form, expr) + 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) @property - def mlil(self): + def mlil(self) -> Optional['mediumlevelil.MediumLevelILInstruction']: """Alias for medium_level_il""" return self.medium_level_il @property - def mlils(self): - exprs = self._function.get_medium_level_il_expr_indexes(self._expr_index) - result = [] - for expr in exprs: - result.append(mediumlevelil.MediumLevelILInstruction(self._function.medium_level_il.ssa_form, expr)) - return result + 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 + 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) @property - def low_level_il(self): + def low_level_il(self) -> Optional['lowlevelil.LowLevelILInstruction']: """Low level IL form of this expression""" if self.mlil is None: return None return self.mlil.llil @property - def llil(self): + def llil(self) -> Optional['lowlevelil.LowLevelILInstruction']: """Alias for low_level_il""" return self.low_level_il @property - def llils(self): + def llils(self) -> List['lowlevelil.LowLevelILExpr']: result = set() for mlil_expr in self.mlils: for llil_expr in mlil_expr.llils: @@ -559,34 +575,34 @@ class HighLevelILInstruction(object): return list(result) @property - def il_basic_block(self): + def il_basic_block(self) -> Optional['HighLevelILBasicBlock']: """ 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: + if not block or self._function.source_function is None: return None return HighLevelILBasicBlock(self._function.source_function.view, block, self._function) @property - def value(self): + def value(self) -> 'variable.RegisterValue': """Value of expression if constant or a known value (read-only)""" mlil = self.mlil if mlil is None: - return function.RegisterValue() + return variable.RegisterValue() return mlil.value @property - def possible_values(self): + def possible_values(self) -> 'variable.PossibleValueSet': """Possible values of expression using path-sensitive static data flow analysis (read-only)""" mlil = self.mlil if mlil is None: - return function.PossibleValueSet() + return variable.PossibleValueSet() return mlil.possible_values @property - def expr_type(self): + def expr_type(self) -> Optional['types.Type']: """Type of expression""" result = core.BNGetHighLevelILExprType(self._function.handle, self._expr_index) if result.type: @@ -596,18 +612,18 @@ class HighLevelILInstruction(object): return types.Type(result.type, platform = platform, confidence = result.confidence) return None - def get_possible_values(self, options = []): + def get_possible_values(self, options:List[DataFlowQueryOption]=[]) -> 'variable.PossibleValueSet': mlil = self.mlil if mlil is None: - return function.RegisterValue() + return variable.PossibleValueSet() return mlil.get_possible_values(options) @property - def ssa_memory_version(self): + 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) - def get_ssa_var_version(self, var): + def get_ssa_var_version(self, var:'variable.Variable') -> int: var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index @@ -622,31 +638,28 @@ class HighLevelILExpr(object): .. note:: This class shouldn't be instantiated directly. Rather the helper members of HighLevelILFunction should be \ used instead. """ - def __init__(self, index): + def __init__(self, index:ExpressionIndex): self._index = index @property - def index(self): - """ """ + def index(self) -> ExpressionIndex: return self._index - @index.setter - def index(self, value): - self._index = value class HighLevelILFunction(object): """ ``class HighLevelILFunction`` contains the a HighLevelILInstruction object that makes up the abstract syntax tree of - a binaryninja.function. + a function. """ - def __init__(self, arch = None, handle = None, source_func = None): + def __init__(self, arch:Optional['architecture.Architecture']=None, handle:core.BNHighLevelILFunction=None, + source_func:'function.Function'=None): self._arch = arch self._source_function = source_func if handle is not None: self.handle = core.handle_of_type(handle, core.BNHighLevelILFunction) if self._source_function is None: - self._source_function = binaryninja.function.Function(handle = core.BNGetHighLevelILOwnerFunction(self.handle)) + self._source_function = function.Function(handle = core.BNGetHighLevelILOwnerFunction(self.handle)) if self._arch is None: self._arch = self._source_function.arch else: @@ -655,8 +668,12 @@ class HighLevelILFunction(object): raise ValueError("IL functions must be created with an associated function") if self._arch is None: self._arch = self._source_function.arch + if self._arch is None: + raise ValueError("IL functions must be created with an associated Architecture") func_handle = self._source_function.handle - self.handle = core.BNCreateHighLevelILFunction(arch.handle, func_handle) + self.handle = core.BNCreateHighLevelILFunction(self._arch.handle, func_handle) + assert self._source_function is not None + assert self._arch is not None def __del__(self): if self.handle is not None: @@ -672,6 +689,8 @@ class HighLevelILFunction(object): def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented + assert self.handle is not None + assert other.handle is not None return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) def __ne__(self, other): @@ -682,22 +701,61 @@ class HighLevelILFunction(object): def __hash__(self): return hash(('HLIL', self._source_function)) + def __len__(self): + return int(core.BNGetHighLevelILInstructionCount(self.handle)) + + def __getitem__(self, i:Union[HighLevelILExpr, HighLevelILInstruction, 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 + 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, + InstructionIndex(i)) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self) -> Generator['HighLevelILBasicBlock', None, None]: + count = ctypes.c_ulonglong() + blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) + assert blocks is not None, "core.BNGetHighLevelILBasicBlockList returned None" + view = None + if self._source_function is not None: + view = self._source_function.view + try: + for i in range(0, count.value): + core_block = core.BNNewBasicBlockReference(blocks[i]) + assert core_block is not None + yield HighLevelILBasicBlock(view, core_block, self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + + def __str__(self) -> str: + return str(self.root) + @property - def current_address(self): + def current_address(self) -> int: """Current IL Address (read/write)""" return core.BNHighLevelILGetCurrentAddress(self.handle) @current_address.setter - def current_address(self, value): - core.BNHighLevelILSetCurrentAddress(self.handle, self._arch.handle, value) + def current_address(self, value:int) -> None: + core.BNHighLevelILSetCurrentAddress(self.handle, self.arch.handle, value) - def set_current_address(self, value, arch = None): + def set_current_address(self, value:int, arch:Optional['architecture.Architecture'] = None) -> None: if arch is None: - arch = self._arch + arch = self.arch core.BNHighLevelILSetCurrentAddress(self.handle, arch.handle, value) @property - def root(self): + def root(self) -> Optional[HighLevelILInstruction]: """Root of the abstract syntax tree""" expr_index = core.BNGetHighLevelILRootExpr(self.handle) if expr_index >= core.BNGetHighLevelILExprCount(self.handle): @@ -705,53 +763,80 @@ class HighLevelILFunction(object): return HighLevelILInstruction(self, expr_index) @root.setter - def root(self, value): + def root(self, value:HighLevelILInstruction) -> None: core.BNSetHighLevelILRootExpr(value.expr_index) @property - def basic_blocks(self): + def basic_blocks(self) -> Generator['HighLevelILBasicBlock', None, None]: """list of HighLevelILBasicBlock objects (read-only)""" count = ctypes.c_ulonglong() blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) - result = [] + assert blocks is not None, "core.BNGetHighLevelILBasicBlockList returned None" + view = None if self._source_function is not None: view = self._source_function.view - for i in range(0, count.value): - result.append(HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) - core.BNFreeBasicBlockList(blocks, count.value) - return result + + try: + for i in range(0, count.value): + core_block = core.BNNewBasicBlockReference(blocks[i]) + assert core_block is not None + yield HighLevelILBasicBlock(view, core_block, self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) @property - def instructions(self): + def instructions(self) -> Generator[HighLevelILInstruction, None, None]: """A generator of hlil instructions of the current function""" for block in self.basic_blocks: for i in block: yield i @property - def ssa_form(self): + def ssa_form(self) -> 'HighLevelILFunction': """High level IL in SSA form (read-only)""" result = core.BNGetHighLevelILSSAForm(self.handle) - if not result: - return None + assert result is not None return HighLevelILFunction(self._arch, result, self._source_function) @property - def non_ssa_form(self): + def non_ssa_form(self) -> Optional['HighLevelILFunction']: """High level IL in non-SSA (default) form (read-only)""" result = core.BNGetHighLevelILNonSSAForm(self.handle) if not result: return None return HighLevelILFunction(self._arch, result, self._source_function) - def get_ssa_instruction_index(self, instr): + @property + def arch(self) -> 'architecture.Architecture': + assert self._arch is not None + return self._arch + + @property + def source_function(self) -> 'function.Function': + assert self._source_function is not None + return self._source_function + + @property + def medium_level_il(self) -> Optional['mediumlevelil.MediumLevelILFunction']: + """Medium level IL for this function""" + result = core.BNGetMediumLevelILForHighLevelILFunction(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self._arch, result, self._source_function) + + @property + def mlil(self) -> Optional['mediumlevelil.MediumLevelILFunction']: + """Alias for medium_level_il""" + return self.medium_level_il + + def get_ssa_instruction_index(self, instr:int) -> int: return core.BNGetHighLevelILSSAInstructionIndex(self.handle, instr) - def get_non_ssa_instruction_index(self, instr): + def get_non_ssa_instruction_index(self, instr:int) -> int: return core.BNGetHighLevelILNonSSAInstructionIndex(self.handle, instr) - def get_ssa_var_definition(self, ssa_var): + def get_ssa_var_definition(self, ssa_var:'mediumlevelil.SSAVariable') -> Optional[HighLevelILInstruction]: var_data = core.BNVariable() var_data.type = ssa_var.var.source_type var_data.index = ssa_var.var.index @@ -761,35 +846,37 @@ class HighLevelILFunction(object): return None return HighLevelILInstruction(self, result) - def get_ssa_memory_definition(self, version): + 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) - def get_ssa_var_uses(self, ssa_var): + def get_ssa_var_uses(self, ssa_var:'mediumlevelil.SSAVariable') -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() var_data = core.BNVariable() var_data.type = ssa_var.var.source_type var_data.index = ssa_var.var.index var_data.storage = ssa_var.var.storage instrs = core.BNGetHighLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count) + assert instrs is not None, "core.BNGetHighLevelILSSAVarUses returned None" result = [] for i in range(0, count.value): result.append(HighLevelILInstruction(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result - def get_ssa_memory_uses(self, version): + def get_ssa_memory_uses(self, version:int) -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() instrs = core.BNGetHighLevelILSSAMemoryUses(self.handle, version, count) + assert instrs is not None, "core.BNGetHighLevelILSSAMemoryUses returned None" result = [] for i in range(0, count.value): result.append(HighLevelILInstruction(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result - def is_ssa_var_live(self, ssa_var): + def is_ssa_var_live(self, ssa_var:'mediumlevelil.SSAVariable') -> bool: """ ``is_ssa_var_live`` determines if ``ssa_var`` is live at any point in the function @@ -803,81 +890,43 @@ class HighLevelILFunction(object): var_data.storage = ssa_var.var.storage return core.BNIsHighLevelILSSAVarLive(self.handle, var_data, ssa_var.version) - def get_var_definitions(self, var): + def get_var_definitions(self, var:'variable.Variable') -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage instrs = core.BNGetHighLevelILVariableDefinitions(self.handle, var_data, count) + assert instrs is not None, "core.BNGetHighLevelILVariableDefinitions returned None" result = [] for i in range(0, count.value): result.append(HighLevelILInstruction(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result - def get_var_uses(self, var): + def get_var_uses(self, var:'variable.Variable') -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage instrs = core.BNGetHighLevelILVariableUses(self.handle, var_data, count) + assert instrs is not None, "core.BNGetHighLevelILVariableUses returned None" result = [] for i in range(0, count.value): result.append(HighLevelILInstruction(self, instrs[i])) core.BNFreeILInstructionList(instrs) return result - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __len__(self): - return int(core.BNGetHighLevelILInstructionCount(self.handle)) - - def __getitem__(self, i): - 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 - 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, i) - - def __setitem__(self, i, j): - raise IndexError("instruction modification not implemented") - - def __iter__(self): - count = ctypes.c_ulonglong() - blocks = core.BNGetHighLevelILBasicBlockList(self.handle, count) - view = None - if self._source_function is not None: - view = self._source_function.view - try: - for i in range(0, count.value): - yield HighLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) - finally: - core.BNFreeBasicBlockList(blocks, count.value) - - def __str__(self): - return str(self.root) - - def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0): + def expr(self, operation:Union[str, HighLevelILOperation], a:int = 0, b:int = 0, c:int = 0, + d:int = 0, e:int = 0, size:int = 0) -> HighLevelILExpr: if isinstance(operation, str): - operation = HighLevelILOperation[operation] + operation_value = HighLevelILOperation[operation] elif isinstance(operation, HighLevelILOperation): - operation = operation.value - return HighLevelILExpr(core.BNHighLevelILAddExpr(self.handle, operation, size, a, b, c, d, e)) + operation_value = operation.value + return HighLevelILExpr(core.BNHighLevelILAddExpr(self.handle, operation_value, size, a, b, c, d, e)) - def add_operand_list(self, operands): + def add_operand_list(self, operands:List[int]) -> HighLevelILExpr: """ ``add_operand_list`` returns an operand list expression for the given list of integer operands. @@ -890,7 +939,7 @@ class HighLevelILFunction(object): operand_list[i] = operands[i] return HighLevelILExpr(core.BNHighLevelILAddOperandList(self.handle, operand_list, len(operands))) - def finalize(self): + def finalize(self) -> None: """ ``finalize`` ends the function and computes the list of basic blocks. @@ -898,21 +947,12 @@ class HighLevelILFunction(object): """ core.BNFinalizeHighLevelILFunction(self.handle) - def create_graph(self, settings = None): + def create_graph(self, settings:'function.DisassemblySettings'=None) -> 'flowgraph.CoreFlowGraph': if settings is not None: settings_obj = settings.handle else: settings_obj = None - return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateHighLevelILFunctionGraph(self.handle, settings_obj)) - - @property - def arch(self): - """ """ - return self._arch - - @arch.setter - def arch(self, value): - self._arch = value + return flowgraph.CoreFlowGraph(core.BNCreateHighLevelILFunctionGraph(self.handle, settings_obj)) @property def source_function(self): @@ -981,7 +1021,7 @@ class HighLevelILFunction(object): """Alias for medium_level_il""" return self.medium_level_il - def get_medium_level_il_expr_index(self, expr): + def get_medium_level_il_expr_index(self, expr:ExpressionIndex) -> Optional['mediumlevelil.ExpressionIndex']: medium_il = self.medium_level_il if medium_il is None: return None @@ -993,24 +1033,26 @@ class HighLevelILFunction(object): return None return result - def get_medium_level_il_expr_indexes(self, expr): + def get_medium_level_il_expr_indexes(self, expr:ExpressionIndex) -> List['mediumlevelil.ExpressionIndex']: count = ctypes.c_ulonglong() exprs = core.BNGetMediumLevelILExprIndexesFromHighLevelIL(self.handle, expr, count) + assert exprs is not None, "core.BNGetMediumLevelILExprIndexesFromHighLevelIL returned None" result = [] for i in range(0, count.value): result.append(exprs[i]) core.BNFreeILInstructionList(exprs) return result - def get_label(self, label_idx): + def get_label(self, label_idx:int) -> Optional[HighLevelILInstruction]: result = core.BNGetHighLevelILExprIndexForLabel(self.handle, label_idx) if result >= core.BNGetHighLevelILExprCount(self.handle): return None return HighLevelILInstruction(self, result) - def get_label_uses(self, label_idx): + def get_label_uses(self, label_idx:int) -> List[HighLevelILInstruction]: count = ctypes.c_ulonglong() uses = core.BNGetHighLevelILUsesForLabel(self.handle, label_idx, count) + assert uses is not None, "core.BNGetHighLevelILUsesForLabel returned None" result = [] for i in range(0, count.value): result.append(HighLevelILInstruction(self, uses[i])) @@ -1019,15 +1061,15 @@ class HighLevelILFunction(object): class HighLevelILBasicBlock(basicblock.BasicBlock): - def __init__(self, view, handle, owner): + def __init__(self, view:Optional['binaryview.BinaryView'], handle:core.BNBasicBlock, owner:HighLevelILFunction): super(HighLevelILBasicBlock, self).__init__(handle, view) - self.il_function = owner + self._il_function = owner - def __iter__(self): + def __iter__(self) -> Generator[HighLevelILInstruction, None, None]: for idx in range(self.start, self.end): yield self.il_function[idx] - def __getitem__(self, idx): + def __getitem__(self, idx) -> HighLevelILInstruction: size = self.end - self.start if isinstance(idx, slice): return [self[index] for index in range(*idx.indices(size))] @@ -1038,7 +1080,7 @@ class HighLevelILBasicBlock(basicblock.BasicBlock): else: return self.il_function[self.end + idx] - def _create_instance(self, handle, view): + def _create_instance(self, handle:core.BNBasicBlock, view:'binaryview.BinaryView'): """Internal method by super to instantiate child instances""" return HighLevelILBasicBlock(view, handle, self.il_function) @@ -1054,10 +1096,9 @@ class HighLevelILBasicBlock(basicblock.BasicBlock): return False @property - def il_function(self): - """ """ - return self._il_function + def instruction_count(self) -> int: + return self.end - self.start - @il_function.setter - def il_function(self, value): - self._il_function = value + @property + def il_function(self) -> HighLevelILFunction: + return self._il_function |
