summaryrefslogtreecommitdiff
path: root/python/lowlevelil.py
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2021-06-23 11:03:34 -0400
committerPeter LaFosse <peter@vector35.com>2021-09-05 10:08:09 -0400
commit920da93a153ff0e6cff405c76f6d5175a9cbcfa4 (patch)
treeb505cc6be0bd61a9399135aa2d516e995e5f7467 /python/lowlevelil.py
parent3be2c0f9d4574f84869e5dcc61a91b4356391207 (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.py427
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):