diff options
| author | Peter LaFosse <peter@vector35.com> | 2021-06-23 11:03:34 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2021-09-05 10:08:09 -0400 |
| commit | 920da93a153ff0e6cff405c76f6d5175a9cbcfa4 (patch) | |
| tree | b505cc6be0bd61a9399135aa2d516e995e5f7467 /python/lowlevelil.py | |
| parent | 3be2c0f9d4574f84869e5dcc61a91b4356391207 (diff) | |
Convert the following to dataclasses:
AddressRange
BoolWithConfidence
ConstantReference
EnumerationMember
FunctionParameter
ILFlag
ILIntrinsic
ILRegister
ILRegisterStack
ILSemanticFlagClass
ILSemanticFlagGroup
IndirectBranchInfo
InstructionBranch
InstructionInfo
IntrinsicInfo
IntrinsicInput
LowLevelILExpr
LowLevelILOperationAndSize
PossibleValueSet
RegisterInfo
RegisterSet
RegisterStackAdjustmentWithConfidence
RegisterStackInfo
SSAFlag
SSARegister
SSARegisterOrFlag
SSARegisterStack
SizeWithConfidence
StackVariableReference
StructureMember
TypeFieldReference
TypeParserResult
ValueRange
BasicBlockEdge
Diffstat (limited to 'python/lowlevelil.py')
| -rw-r--r-- | python/lowlevelil.py | 427 |
1 files changed, 97 insertions, 330 deletions
diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 483f88e5..55da5993 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -22,6 +22,7 @@ import ctypes from enum import Flag import struct from typing import Generator, List, Optional, Any, Mapping, Union, Tuple, NewType +from dataclasses import dataclass # Binary Ninja components from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType, DataFlowQueryOption, FunctionGraphType @@ -45,6 +46,7 @@ ILRegisterType = Union[str, 'ILRegister', int] LLILInstructionsType = Generator['LowLevelILInstruction', None, None] LLILBasicBlocksType = Generator['LowLevelILBasicBlock', None, None] + class LowLevelILLabel(object): def __init__(self, handle:core.BNLowLevelILLabel=None): if handle is None: @@ -53,434 +55,203 @@ class LowLevelILLabel(object): else: self.handle = handle - -# TODO : It would be nice to add a `.versions` to IL vars (regs, stack regs, flags) to see all the SSA versions of the given variable. Would need to associate the source function +@dataclass(frozen=True) class ILRegister(object): - def __init__(self, arch:'architecture.Architecture', reg:'architecture.RegisterIndex'): - self._arch = arch - self._index = reg - self._temp = (self._index & 0x80000000) != 0 - if self._temp: - self._name = architecture.RegisterName("temp%d" % (self._index & 0x7fffffff)) - else: - self._name = architecture.RegisterName(self._arch.get_reg_name(self._index)) - - @property - def info(self) -> 'architecture.RegisterInfo': - return self._arch.regs[self._name] + arch:'architecture.Architecture' + index:'architecture.RegisterIndex' def __repr__(self): - return f"<reg {self._name}>" + return f"<reg {self.name}>" def __str__(self): - return self._name + return self.name + + def __int__(self): + return self.index def __eq__(self, other): - if isinstance(other, architecture.RegisterName) and other in self._arch.regs: - index = self._arch.regs[other].index + if isinstance(other, architecture.RegisterName) and other in self.arch.regs: + index = self.arch.regs[other].index assert index is not None - other = ILRegister(self._arch, index) + other = ILRegister(self.arch, index) elif not isinstance(other, self.__class__): return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, (self.__class__, str)): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) - - @property - def arch(self) -> 'architecture.Architecture': - return self._arch + return (self.arch, self.index) == (other.arch, other.index) @property - def index(self) -> 'architecture.RegisterIndex': - return self._index + def info(self) -> 'architecture.RegisterInfo': + return self.arch.regs[self.name] @property def temp(self) -> bool: - return self._temp + return (self.index & 0x80000000) != 0 @property - def name(self) -> str: - return self._name + def name(self) -> architecture.RegisterName: + if self.temp: + return architecture.RegisterName(f"temp{self.index & 0x7fffffff}") + else: + return architecture.RegisterName(self.arch.get_reg_name(self.index)) +@dataclass(frozen=True) class ILRegisterStack(object): - def __init__(self, arch:'architecture.Architecture', reg_stack:'architecture.RegisterStackIndex'): - self._arch = arch - self._index = reg_stack - self._name = self._arch.get_reg_stack_name(self._index) - - @property - def info(self): - return self._arch.reg_stacks[self._name] + arch:'architecture.Architecture' + index:'architecture.RegisterStackIndex' def __repr__(self): - return f"<reg-stack {self._name}>" + return f"<reg-stack {self.name}>" def __str__(self): - return self._name + return self.name - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) - - @property - def arch(self) -> 'architecture.Architecture': - return self._arch + def __int__(self): + return self.index @property - def index(self) -> 'architecture.RegisterStackIndex': - return self._index + def info(self) -> 'architecture.RegisterStackInfo': + return self.arch.reg_stacks[self.name] @property - def name(self) -> str: - return self._name + def name(self) -> 'architecture.RegisterStackName': + return self.arch.get_reg_stack_name(self.index) +@dataclass(frozen=True) class ILFlag(object): - def __init__(self, arch:'architecture.Architecture', flag:'architecture.FlagIndex'): - self._arch = arch - self._index = flag - self._temp = (self._index & 0x80000000) != 0 - if self._temp: - self._name = "cond:%d" % (self._index & 0x7fffffff) - else: - self._name = self._arch.get_flag_name(self._index) + arch:'architecture.Architecture' + index:'architecture.FlagIndex' def __repr__(self): - return f"<flag {self._name}>" + return f"<flag {self.name}>" def __str__(self): - return self._name - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) + return self.name def __int__(self): - return self._index - - @property - def arch(self) -> 'architecture.Architecture': - return self._arch - - @property - def index(self) -> 'architecture.FlagIndex': - return self._index + return self.index @property def temp(self): - return self._temp + return (self.index & 0x80000000) != 0 @property - def name(self) -> str: - return self._name + def name(self) -> 'architecture.FlagName': + if self.temp: + return architecture.FlagName(f"cond:{(self.index & 0x7fffffff)}") + else: + return architecture.FlagName(self.arch.get_flag_name(self.index)) +@dataclass(frozen=True) class ILSemanticFlagClass(object): - def __init__(self, arch:'architecture.Architecture', sem_class:'architecture.SemanticClassIndex'): - self._arch = arch - self._index = sem_class - self._name = self._arch.get_semantic_flag_class_name(self._index) + arch:'architecture.Architecture' + index:'architecture.SemanticClassIndex' def __repr__(self): - return self._name + return self.name def __str__(self): - return self._name - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) - - @property - def arch(self) -> 'architecture.Architecture': - return self._arch + return self.name - @property - def index(self) -> 'architecture.SemanticClassIndex': - return self._index + def __int__(self): + return self.index @property - def name(self) -> str: - return self._name + def name(self) -> 'architecture.SemanticClassName': + return self.arch.get_semantic_flag_class_name(self.index) +@dataclass(frozen=True) class ILSemanticFlagGroup(object): - def __init__(self, arch:'architecture.Architecture', sem_group:'architecture.SemanticGroupIndex'): - self._arch = arch - self._index = sem_group - self._name = self._arch.get_semantic_flag_group_name(self._index) + arch:'architecture.Architecture' + index:'architecture.SemanticGroupIndex' def __repr__(self): - return self._name + return self.name def __str__(self): - return self._name - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) - - @property - def arch(self) -> 'architecture.Architecture': - return self._arch + return self.name - @property - def index(self) -> 'architecture.SemanticGroupIndex': - return self._index + def __int__(self): + return self.index @property def name(self) -> 'architecture.SemanticGroupName': - return self._name + return self.arch.get_semantic_flag_group_name(self.index) +@dataclass(frozen=True) class ILIntrinsic(object): - def __init__(self, arch:'architecture.Architecture', intrinsic:'architecture.IntrinsicIndex'): - self._arch = arch - self._index = intrinsic - self._name = self._arch.get_intrinsic_name(self._index) - if self._name in self._arch.intrinsics: - self._inputs = self._arch.intrinsics[self._name].inputs - self._outputs = self._arch.intrinsics[self._name].outputs + arch:'architecture.Architecture' + index:'architecture.IntrinsicIndex' def __repr__(self): - return self._name + return self.name def __str__(self): - return self._name - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._arch, self._index, self._name)) + return self.name @property - def arch(self) -> 'architecture.Architecture': - return self._arch - - @property - def index(self) -> 'architecture.IntrinsicIndex': - return self._index - - @property - def name(self) -> str: - return self._name + def name(self) -> 'architecture.IntrinsicName': + return self.arch.get_intrinsic_name(self.index) @property def inputs(self) -> List['architecture.IntrinsicInput']: """``inputs`` is only available if the IL intrinsic is an Architecture intrinsic """ - return self._inputs + return self.arch.intrinsics[self.name].inputs @property def outputs(self) -> List['types.Type']: """``outputs`` is only available if the IL intrinsic is an Architecture intrinsic """ - return self._outputs + return self.arch.intrinsics[self.name].outputs +@dataclass(frozen=True) class SSARegister(object): - def __init__(self, reg:ILRegister, version:int): - self._reg = reg - self._version = version + reg:ILRegister + version:int def __repr__(self): - return "<ssa %s version %d>" % (repr(self._reg), self._version) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._reg, self._version) == (other._reg, other._version) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._reg, self._version)) - - @property - def reg(self) -> ILRegister: - return self._reg - - @property - def version(self) -> int: - return self._version - - @version.setter - def version(self, value): - self._version = value + return f"<ssa {self.reg} version {self.version}>" +@dataclass(frozen=True) class SSARegisterStack(object): - def __init__(self, reg_stack:ILRegisterStack, version:int): - self._reg_stack = reg_stack - self._version = version + reg_stack:ILRegisterStack + version:int def __repr__(self): - return "<ssa %s version %d>" % (repr(self._reg_stack), self._version) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._reg_stack, self._version) == (other._reg_stack, other._version) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._reg_stack, self._version)) - - @property - def reg_stack(self) -> ILRegisterStack: - return self._reg_stack - - @property - def version(self) -> int: - return self._version + return f"<ssa {self.reg_stack} version {self.version}>" +@dataclass(frozen=True) class SSAFlag(object): - def __init__(self, flag:ILFlag, version:int): - self._flag = flag - self._version = version + flag:ILFlag + version:int def __repr__(self): - return "<ssa %s version %d>" % (repr(self._flag), self._version) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._flag, self._version) == (other._flag, other._version) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._flag, self._version)) - - @property - def flag(self) -> ILFlag: - return self._flag - - @property - def version(self) -> int: - return self._version + return f"<ssa {self.flag} version {self.version}>" +@dataclass(frozen=True) class SSARegisterOrFlag(object): - def __init__(self, reg_or_flag:Union[ILRegister, ILFlag], version:int): - self._reg_or_flag = reg_or_flag - self._version = version + reg_or_flag:Union[ILRegister, ILFlag] + version:int def __repr__(self): - return "<ssa %s version %d>" % (repr(self._reg_or_flag), self._version) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return (self._reg_or_flag == other._reg_or_flag) and (self._version == other._version) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._reg_or_flag, self._version)) - - @property - def reg_or_flag(self) -> Union[ILRegister, ILFlag]: - return self._reg_or_flag - - @property - def version(self) -> int: - return self._version + return f"<ssa {self.reg_or_flag} version {self.version}>" +@dataclass(frozen=True) class LowLevelILOperationAndSize(object): - def __init__(self, operation:'LowLevelILOperation', size:int): - self._operation = operation - self._size = size + operation:'LowLevelILOperation' + 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 not isinstance(other, self.__class__): - return NotImplemented - return (self._operation, self._size) == (other._operation, other._size) - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return not (self == other) - - def __hash__(self): - return hash((self._operation, self._size)) - - @property - def operation(self) -> 'LowLevelILOperation': - return self._operation - - @property - def size(self) -> int: - return self._size + if self.size == 0: + return f"<{self.operation.name}>" + return "<{self.operation.name} {self.size}>" class LowLevelILInstruction(object): @@ -876,7 +647,7 @@ class LowLevelILInstruction(object): """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._instr_index) + core_block = core.BNGetLowLevelILBasicBlockForInstruction(self._function.handle, self._insstr_index) assert core_block is not None, "BNGetLowLevelILBasicBlockForInstruction returned None" return LowLevelILBasicBlock(view, core_block, self._function) @@ -1161,6 +932,7 @@ class LowLevelILInstruction(object): return self._operands +@dataclass(frozen=True) class LowLevelILExpr(object): """ ``class LowLevelILExpr`` hold the index of IL Expressions. @@ -1168,15 +940,10 @@ class LowLevelILExpr(object): .. note:: This class shouldn't be instantiated directly. Rather the helper members of LowLevelILFunction should be \ used instead. """ - def __init__(self, index:ExpressionIndex): - self._index = index + index:ExpressionIndex def __int__(self) -> int: - return self._index - - @property - def index(self): - return self._index + return self.index class LowLevelILFunction(object): |
