summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py257
-rw-r--r--python/basicblock.py79
-rw-r--r--python/lowlevelil.py427
-rw-r--r--python/mediumlevelil.py49
-rw-r--r--python/types.py435
-rw-r--r--python/variable.py228
6 files changed, 326 insertions, 1149 deletions
diff --git a/python/architecture.py b/python/architecture.py
index 7dd8ff91..2d6fde0f 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -21,6 +21,7 @@
import traceback
import ctypes
from typing import Generator, Union, List, Optional, Mapping, Tuple, NewType
+from dataclasses import dataclass
# Binary Ninja components
import binaryninja
@@ -61,258 +62,86 @@ SemanticGroupType = Union[SemanticGroupName, 'lowlevelil.ILSemanticFlagGroup', S
IntrinsicType = Union[IntrinsicName, 'lowlevelil.ILIntrinsic', IntrinsicIndex]
-
+@dataclass(frozen=False)
class RegisterInfo(object):
- def __init__(self, full_width_reg:RegisterName, size:int, offset:int=0,
- extend:ImplicitRegisterExtend=ImplicitRegisterExtend.NoExtend, index:RegisterIndex=None):
- self._full_width_reg = full_width_reg
- self._offset = offset
- self._size = size
- self._extend = extend
- self._index = index
+ full_width_reg:RegisterName
+ offset:int
+ size:int = 0
+ extend:ImplicitRegisterExtend = ImplicitRegisterExtend.NoExtend
+ index:Optional[RegisterIndex] = None
def __repr__(self):
- if self._extend == ImplicitRegisterExtend.ZeroExtendToFullWidth:
+ if self.extend == ImplicitRegisterExtend.ZeroExtendToFullWidth:
extend = ", zero extend"
- elif self._extend == ImplicitRegisterExtend.SignExtendToFullWidth:
+ elif self.extend == ImplicitRegisterExtend.SignExtendToFullWidth:
extend = ", sign extend"
else:
extend = ""
- return "<reg: size %d, offset %d in %s%s>" % (self._size, self._offset, self._full_width_reg, extend)
-
- @property
- def full_width_reg(self) -> RegisterName:
- return self._full_width_reg
-
- @full_width_reg.setter
- def full_width_reg(self, value:RegisterName) -> None:
- self._full_width_reg = value
-
- @property
- def offset(self) -> int:
- return self._offset
-
- @offset.setter
- def offset(self, value:int) -> None:
- self._offset = value
-
- @property
- def size(self) -> int:
- return self._size
-
- @size.setter
- def size(self, value:int) -> None:
- self._size = value
-
- @property
- def extend(self) -> ImplicitRegisterExtend:
- return self._extend
-
- @extend.setter
- def extend(self, value:ImplicitRegisterExtend) -> None:
- self._extend = value
-
- @property
- def index(self) -> Optional[RegisterIndex]:
- return self._index
-
- @index.setter
- def index(self, value:RegisterIndex) -> None:
- self._index = value
+ return "<reg: size %d, offset %d in %s%s>" % (self.size, self.offset, self.full_width_reg, extend)
+@dataclass(frozen=False)
class RegisterStackInfo(object):
- def __init__(self, storage_regs:List[RegisterName], top_relative_regs:List[RegisterName],
- stack_top_reg:RegisterName, index:RegisterStackIndex=None):
- self._storage_regs = storage_regs
- self._top_relative_regs = top_relative_regs
- self._stack_top_reg = stack_top_reg
- self._index = index
+ storage_regs:List[RegisterName]
+ top_relative_regs:List[RegisterName]
+ stack_top_reg:RegisterName
+ index:Optional[RegisterStackIndex] = None
def __repr__(self):
- return "<reg stack: %d regs, stack top in %s>" % (len(self._storage_regs), self._stack_top_reg)
-
- @property
- def storage_regs(self) -> List[RegisterName]:
- return self._storage_regs
-
- @storage_regs.setter
- def storage_regs(self, value:List[RegisterName]) -> None:
- self._storage_regs = value
-
- @property
- def top_relative_regs(self) -> List[RegisterName]:
- return self._top_relative_regs
-
- @top_relative_regs.setter
- def top_relative_regs(self, value:List[RegisterName]) -> None:
- self._top_relative_regs = value
-
- @property
- def stack_top_reg(self) -> RegisterName:
- return self._stack_top_reg
-
- @stack_top_reg.setter
- def stack_top_reg(self, value:RegisterName) -> None:
- self._stack_top_reg = value
-
- @property
- def index(self) -> Optional[RegisterStackIndex]:
- return self._index
-
- @index.setter
- def index(self, value:RegisterStackIndex) -> None:
- self._index = value
+ return "<reg stack: %d regs, stack top in %s>" % (len(self.storage_regs), self.stack_top_reg)
+@dataclass(frozen=True)
class IntrinsicInput(object):
- def __init__(self, type_obj, name=""):
- self._name = name
- self._type = type_obj
+ type:'types.Type'
+ name:str = ""
def __repr__(self):
- if len(self._name) == 0:
- return "<input: %s>" % str(self._type)
- return "<input: %s %s>" % (str(self._type), self._name)
-
- @property
- def name(self):
- return self._name
-
- @name.setter
- def name(self, value):
- self._name = value
-
- @property
- def type(self):
- return self._type
-
- @type.setter
- def type(self, value):
- self._type = value
+ if len(self.name) == 0:
+ return "<input: %s>" % str(self.type)
+ return "<input: %s %s>" % (str(self.type), self.name)
+@dataclass(frozen=True)
class IntrinsicInfo(object):
- def __init__(self, inputs, outputs, index=None):
- self._inputs = inputs
- self._outputs = outputs
- self._index = index
+ inputs:List[IntrinsicInput]
+ outputs:List['types.Type']
+ index:Optional[int] = None
def __repr__(self):
- return "<intrinsic: %s -> %s>" % (repr(self._inputs), repr(self._outputs))
-
- @property
- def inputs(self):
- return self._inputs
-
- @inputs.setter
- def inputs(self, value):
- self._inputs = value
-
- @property
- def outputs(self):
- return self._outputs
-
- @outputs.setter
- def outputs(self, value):
- self._outputs = value
-
- @property
- def index(self):
- return self._index
-
- @index.setter
- def index(self, value):
- self._index = value
+ return f"<intrinsic: {repr(self.inputs)} -> {repr(self.outputs)}>"
+@dataclass(frozen=True)
class InstructionBranch(object):
- def __init__(self, branch_type, target = 0, arch = None):
- self._type = branch_type
- self._target = target
- self._arch = arch
+ type:BranchType
+ target:int
+ arch:'Architecture'
def __repr__(self):
- branch_type = self._type
- if self._arch is not None:
- return "<%s: %s@%#x>" % (branch_type.name, self._arch.name, self._target)
- return "<%s: %#x>" % (branch_type, self._target)
-
- @property
- def type(self):
- return self._type
-
- @type.setter
- def type(self, value):
- self._type = value
-
- @property
- def target(self):
- return self._target
-
- @target.setter
- def target(self, value):
- self._target = value
-
- @property
- def arch(self):
- return self._arch
-
- @arch.setter
- def arch(self, value):
- self._arch = value
+ if self.arch is not None:
+ return f"<{self.type.name}: {self.arch.name}@{self.target:#x}>"
+ return f"<{self.type}: {self.target:#x}>"
+@dataclass(frozen=False)
class InstructionInfo(object):
- def __init__(self):
- self.length = 0
- self.arch_transition_by_target_addr = False
- self.branch_delay = False
- self.branches = []
+ length:int = 0
+ arch_transition_by_target_addr:bool = False
+ branch_delay:bool = False
+ branches:List[InstructionBranch] = []
def add_branch(self, branch_type, target = 0, arch = None):
- self._branches.append(InstructionBranch(branch_type, target, arch))
+ self.branches.append(InstructionBranch(branch_type, target, arch))
def __len__(self):
- return self._length
+ return self.length
def __repr__(self):
branch_delay = ""
- if self._branch_delay:
+ if self.branch_delay:
branch_delay = ", delay slot"
- return "<instr: %d bytes%s, %s>" % (self._length, branch_delay, repr(self._branches))
-
- @property
- def length(self):
- return self._length
-
- @length.setter
- def length(self, value):
- self._length = value
-
- @property
- def arch_transition_by_target_addr(self):
- return self._arch_transition_by_target_addr
-
- @arch_transition_by_target_addr.setter
- def arch_transition_by_target_addr(self, value):
- self._arch_transition_by_target_addr = value
-
- @property
- def branch_delay(self):
- return self._branch_delay
-
- @branch_delay.setter
- def branch_delay(self, value):
- self._branch_delay = value
-
- @property
- def branches(self):
- return self._branches
-
- @branches.setter
- def branches(self, value):
- self._branches = value
+ return f"<instr: {self.length} bytes{branch_delay}, {repr(self.branches)}>"
class _ArchitectureMetaClass(type):
diff --git a/python/basicblock.py b/python/basicblock.py
index 1bc29167..fa360a53 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -19,6 +19,7 @@
# IN THE SOFTWARE.
import ctypes
+from dataclasses import dataclass
from typing import Generator, Optional, List, Tuple
# Binary Ninja components
@@ -30,75 +31,21 @@ from .enums import BranchType, HighlightStandardColor
# from . import binaryview
# from . import architecture
-class BasicBlockEdge(object):
- def __init__(self, branch_type:BranchType, source:'BasicBlock', target:'BasicBlock', back_edge:bool, fall_through:bool):
- self._type = branch_type
- self._source = source
- self._target = target
- self._back_edge = back_edge
- self._fall_through = fall_through
+@dataclass
+class BasicBlockEdge:
+ type:BranchType
+ source:'BasicBlock'
+ target:'BasicBlock'
+ back_edge:bool
+ fall_through:bool
def __repr__(self):
- if self._type == BranchType.UnresolvedBranch:
- return "<%s>" % BranchType(self._type).name
- elif self._target.arch:
- return "<%s: %s@%#x>" % (BranchType(self._type).name, self._target.arch.name, self._target.start)
+ if self.type == BranchType.UnresolvedBranch:
+ return f"<{self.type.name}>"
+ elif self.target.arch:
+ return f"<{self.type.name}: {self.target.arch.name}@{self.target.start:#x}>"
else:
- return "<%s: %#x>" % (BranchType(self._type).name, self._target.start)
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return (self._type, self._source, self._target, self._back_edge, self._fall_through) == \
- (other._type, other._source, other._target, other._back_edge, other._fall_through)
-
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
-
- def __hash__(self):
- return hash((self._type, self._source, self._target, self.back_edge, self.fall_through))
-
- @property
- def type(self) -> BranchType:
- return self._type
-
- @type.setter
- def type(self, value:BranchType) -> None:
- self._type = value
-
- @property
- def source(self) -> 'BasicBlock':
- return self._source
-
- @source.setter
- def source(self, value:'BasicBlock') -> None:
- self._source = value
-
- @property
- def target(self) -> 'BasicBlock':
- return self._target
-
- @target.setter
- def target(self, value:'BasicBlock') -> None:
- self._target = value
-
- @property
- def back_edge(self) -> bool:
- return self._back_edge
-
- @back_edge.setter
- def back_edge(self, value:bool) -> None:
- self._back_edge = value
-
- @property
- def fall_through(self) -> bool:
- return self._fall_through
-
- @fall_through.setter
- def fall_through(self, value:bool) -> None:
- self._fall_through = value
+ return f"<{self.type.name}: {self.target.start:#x}>"
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):
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 61cc420f..fdc4c2e9 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -1265,6 +1265,55 @@ class MediumLevelILFunction(object):
def source_function(self) -> 'function.Function':
return self._source_function
+ @source_function.setter
+ def source_function(self, value):
+ self._source_function = value
+
+ @property
+ def il_form(self) -> "binaryninja.enums.FunctionGraphType":
+ if len(self.basic_blocks) < 1:
+ return FunctionGraphType.InvalidILViewType
+ return FunctionGraphType(core.BNGetBasicBlockFunctionGraphType(self.basic_blocks[0].handle))
+
+ @property
+ def vars(self) -> List["binaryninja.function.Variable"]:
+ """This gets just the MLIL variables - you may be interested in the union of `MediumLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form in [FunctionGraphType.MediumLevelILFunctionGraph, FunctionGraphType.MediumLevelILSSAFormFunctionGraph, FunctionGraphType.MappedMediumLevelILFunctionGraph, FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph]:
+ count = ctypes.c_ulonglong()
+ core_variables = core.BNGetMediumLevelILVariables(self.handle, count)
+ result = []
+ for var_i in range(count.value):
+ result.append(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage))
+ core.BNFreeVariableList(core_variables)
+ return result
+ return []
+
+ @property
+ def ssa_vars(self) -> List["binaryninja.mediumlevelil.SSAVariable"]:
+ """This gets just the MLIL SSA variables - you may be interested in the union of `MediumLevelIlFunction.source_function.param_vars` for all the variables used in the function"""
+ if self.source_function is None:
+ return []
+
+ if self.il_form in [FunctionGraphType.MediumLevelILSSAFormFunctionGraph, FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph]:
+ variable_count = ctypes.c_ulonglong()
+ core_variables = core.BNGetMediumLevelILVariables(self.handle, variable_count)
+ result = []
+ for var_i in range(variable_count.value):
+ version_count = ctypes.c_ulonglong()
+ versions = core.BNGetMediumLevelILVariableSSAVersions(self.handle, core_variables[var_i], version_count)
+
+ for version_i in range(version_count.value):
+ result.append(SSAVariable(function.Variable(self.source_function, core_variables[var_i].type, core_variables[var_i].index, core_variables[var_i].storage), versions[version_i]))
+ core.BNFreeILInstructionList(versions)
+
+ core.BNFreeVariableList(core_variables)
+ return result
+
+ return []
+
class MediumLevelILBasicBlock(basicblock.BasicBlock):
def __init__(self, handle:core.BNBasicBlock, owner:MediumLevelILFunction, view:Optional['binaryview.BinaryView']=None):
diff --git a/python/types.py b/python/types.py
index 87fa7ddb..a44be854 100644
--- a/python/types.py
+++ b/python/types.py
@@ -218,6 +218,7 @@ class TypeReferenceSource(object):
def __hash__(self):
return hash(str(self))
+
class NameSpace(QualifiedName):
def __str__(self):
return ":".join(self.name)
@@ -346,41 +347,16 @@ class Symbol(object):
def auto(self):
return core.BNIsSymbolAutoDefined(self.handle)
-
+@dataclass(frozen=True)
class FunctionParameter(object):
- def __init__(self, param_type, name = "", location = None):
- self._type = param_type
- self._name = name
- self._location = location
+ type:'types.Type'
+ name:str = ""
+ location:Optional['variable.VariableNameAndType'] = None
def __repr__(self):
- if (self._location is not None) and (self._location.name != self._name):
- return "%s %s%s @ %s" % (self._type.get_string_before_name(), self._name, self._type.get_string_after_name(), self._location.name)
- return "%s %s%s" % (self._type.get_string_before_name(), self._name, self._type.get_string_after_name())
-
- @property
- def type(self):
- return self._type
-
- @type.setter
- def type(self, value):
- self._type = value
-
- @property
- def name(self):
- return self._name
-
- @name.setter
- def name(self, value):
- self._name = value
-
- @property
- def location(self):
- return self._location
-
- @location.setter
- def location(self, value):
- self._location = value
+ if (self.location is not None) and (self.location.name != self.name):
+ return "%s %s%s @ %s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name(), self.location.name)
+ return "%s %s%s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name())
class Type(object):
@@ -997,166 +973,50 @@ class Type(object):
return Type(handle = core.BNTypeWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle))
+@dataclass(frozen=True)
class BoolWithConfidence(object):
- def __init__(self, value, confidence = core.max_confidence):
- self._value = value
- self._confidence = confidence
-
- def __str__(self):
- return str(self._value)
-
- def __repr__(self):
- return repr(self._value)
+ value:bool
+ confidence:int=core.max_confidence
def __bool__(self):
- return self._value
-
- def __nonzero__(self):
- return self._value
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = value
-
- @property
- def confidence(self):
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._confidence = value
+ return self.value
+@dataclass(frozen=True)
class SizeWithConfidence(object):
- def __init__(self, value:int, confidence:int=core.max_confidence):
- self._value = value
- self._confidence = confidence
-
- def __str__(self):
- return str(self._value)
-
- def __repr__(self):
- return repr(self._value)
+ value:int
+ confidence:int=core.max_confidence
def __int__(self):
- return self._value
-
- @property
- def value(self) -> int:
- return self._value
-
- @value.setter
- def value(self, value:int) -> None:
- self._value = value
-
- @property
- def confidence(self) -> int:
- return self._confidence
-
- @confidence.setter
- def confidence(self, value:int) -> None:
- self._confidence = value
+ return self.value
+@dataclass(frozen=True)
class RegisterStackAdjustmentWithConfidence(object):
- def __init__(self, value:int, confidence:int=core.max_confidence):
- self._value = value
- self._confidence = confidence
-
- def __str__(self):
- return str(self._value)
-
- def __repr__(self):
- return repr(self._value)
+ value:int
+ confidence:int=core.max_confidence
def __int__(self):
- return self._value
-
- @property
- def value(self) -> int:
- return self._value
-
- @value.setter
- def value(self, value:int) -> None:
- self._value = value
-
- @property
- def confidence(self) -> int:
- return self._confidence
-
- @confidence.setter
- def confidence(self, value:int) -> None:
- self._confidence = value
+ return self.value
+@dataclass(frozen=True)
class RegisterSet(object):
- def __init__(self, reg_list:List['architecture.RegisterName'], confidence:int=core.max_confidence):
- self._regs = reg_list
- self._confidence = confidence
-
- def __repr__(self):
- return repr(self._regs)
+ regs:List['architecture.RegisterName']
+ confidence:int=core.max_confidence
def __iter__(self) -> Generator['architecture.RegisterName', None, None]:
- for reg in self._regs:
+ for reg in self.regs:
yield reg
def __getitem__(self, idx):
- return self._regs[idx]
+ return self.regs[idx]
def __len__(self):
- return len(self._regs)
+ return len(self.regs)
def with_confidence(self, confidence):
- return RegisterSet(list(self._regs), confidence = confidence)
-
- @property
- def regs(self) -> List['architecture.RegisterName']:
- return self._regs
-
- @regs.setter
- def regs(self, value:List['architecture.RegisterName']) -> None:
- self._regs = value
-
- @property
- def confidence(self) -> int:
- return self._confidence
-
- @confidence.setter
- def confidence(self, value:int) -> None:
- self._confidence = value
-
-
-class ReferenceTypeWithConfidence(object):
- def __init__(self, value, confidence = core.max_confidence):
- self._value = value
- self._confidence = confidence
-
- def __str__(self):
- return str(self._value)
-
- def __repr__(self):
- return repr(self._value)
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = value
-
- @property
- def confidence(self):
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._confidence = value
+ return RegisterSet(list(self.regs), confidence=confidence)
class NamedTypeReference(object):
@@ -1223,75 +1083,17 @@ class NamedTypeReference(object):
return NamedTypeReference(type_class, type_id, name)
+@dataclass(frozen=True)
class StructureMember(object):
- def __init__(self, t, name, offset):
- self._type = t
- self._name = name
- self._offset = offset
+ type:'types.Type'
+ name:str
+ offset:int
def __repr__(self):
- if len(self._name) == 0:
- return "<member: %s, offset %#x>" % (str(self._type), self._offset)
- return "<%s %s%s, offset %#x>" % (self._type.get_string_before_name(), self._name,
- self._type.get_string_after_name(), self._offset)
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return (self._type, self._name, self._offset) == (other._type, other._name, other._offset)
-
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
-
- def __lt__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self._offset < other._offset
-
- def __gt__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self._offset > other._offset
-
- def __le__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self._offset <= other._offset
-
- def __ge__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self._offset >= other._offset
-
- def __hash__(self):
- return hash((self._type, self._name, self._offset))
-
- @property
- def type(self):
- return self._type
-
- @type.setter
- def type(self, value):
- self._type = value
-
- @property
- def name(self):
- return self._name
-
- @name.setter
- def name(self, value):
- self._name = value
-
- @property
- def offset(self):
- return self._offset
-
- @offset.setter
- def offset(self, value):
- self._offset = value
-
+ if len(self.name) == 0:
+ return f"<member: {self.type}, offset {self.offset:#x}>"
+ return f"<{self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}" + \
+ ", offset {self.offset:#x}>"
class Structure(object):
def __init__(self, handle=None):
@@ -1326,30 +1128,34 @@ class Structure(object):
def __hash__(self):
return hash(ctypes.addressof(self._handle.contents))
- def __getitem__(self, name):
+ def __getitem__(self, name:str) -> StructureMember:
member = None
try:
if self._mutable:
member = core.BNGetStructureBuilderMemberByName(self._handle, name)
- assert member is not None, "core.BNGetStructureBuilderMemberByName returned None"
+ if member is None:
+ raise ValueError(f"Member {name} is not part of structure")
else:
member = core.BNGetStructureMemberByName(self._handle, name)
- assert member is not None, "core.BNGetStructureMemberByName returned None"
+ if member is None:
+ raise ValueError(f"Member {name} is not part of structure")
return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
member.contents.name, member.contents.offset)
finally:
if member is not None:
core.BNFreeStructureMember(member)
- def member_at_offset(self, offset):
+ def member_at_offset(self, offset:int) -> StructureMember:
member = None
try:
if self._mutable:
member = core.BNGetStructureBuilderMemberAtOffset(self._handle, offset, None)
- assert member is not None, "core.BNGetStructureBuilderMemberAtOffset returned None"
+ if member is None:
+ raise ValueError(f"No member exists a offset {offset}")
else:
member = core.BNGetStructureMemberAtOffset(self._handle, offset, None)
- assert member is not None, "core.BNGetStructureMemberAtOffset returned None"
+ if member is None:
+ raise ValueError(f"No member exists a offset {offset}")
return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
member.contents.name, member.contents.offset)
finally:
@@ -1485,38 +1291,14 @@ class Structure(object):
return Structure(core.BNStructureWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle))
+@dataclass(frozen=True)
class EnumerationMember(object):
- def __init__(self, name, value, default):
- self.name = name
- self.value = value
- self.default = default
+ name:str
+ value:int
+ default:bool
def __repr__(self):
- return "<%s = %#x>" % (self.name, self.value)
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = value
-
- @property
- def name(self):
- return self._name
-
- @name.setter
- def name(self, value):
- self._name = value
-
- @property
- def default(self):
- return self._default
-
- @default.setter
- def default(self, value):
- self._default = value
+ return f"<{self.name} = {self.value:#x}>"
class Enumeration(object):
@@ -1603,18 +1385,15 @@ class Enumeration(object):
return Enumeration(core.BNCreateEnumerationBuilderFromEnumeration(self._handle))
+@dataclass(frozen=True)
class TypeParserResult(object):
- def __init__(self, types, variables, functions):
- self._types = types
- self._variables = variables
- self._functions = functions
+ types:Mapping[QualifiedName, Type]
+ variables:Mapping[QualifiedName, Type]
+ functions:Mapping[QualifiedName, Type]
def __repr__(self):
- return "<types: %s, variables: %s, functions: %s>" % (self._types, self._variables, self._functions)
+ return "<types: %s, variables: %s, functions: %s>" % (self.types, self.variables, self.functions)
- @property
- def types(self):
- return self._types
@types.setter
def types(self, value):
@@ -1673,102 +1452,16 @@ def preprocess_source(source, filename=None, include_dirs=[]):
return (None, error_str)
+@dataclass(frozen=True)
class TypeFieldReference(object):
- def __init__(self, func, arch, addr, size):
- self._function = func
- self._arch = arch
- self._address = addr
- self._size = size
+ func:Optional['function.Function']
+ arch:Optional['architecture.Architecture']
+ address:int
+ size:int
+ incomingType:Type
def __repr__(self):
- if self._arch:
- return "<ref: %s@%#x, size: %#x>" % (self._arch.name, self._address, self._size)
- else:
- return "<ref: %#x, size: %#x>" % (self._address, self._size)
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return (self.function, self.arch, self.address, self._size) ==\
- (other.address, other.function, other.arch, other.size)
-
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
-
- def __lt__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- if self.address < other.address:
- return True
- elif self.address > other.address:
- return False
- else:
- return self.size < other.size
-
- def __gt__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- if self.address > other.address:
- return True
- elif self.address < other.address:
- return False
- else:
- return self.size > other.size
-
- def __ge__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- if self.address > other.address:
- return True
- elif self.address < other.address:
- return False
+ if self.arch:
+ return "<ref: %s@%#x, size: %#x>" % (self.arch.name, self.address, self.size)
else:
- return self.size >= other.size
-
- def __le__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- if self.address < other.address:
- return True
- elif self.address > other.address:
- return False
- else:
- return self.size <= other.size
-
- def __hash__(self):
- return hash((self._function, self._arch, self._address, self._size))
-
- @property
- def function(self):
- return self._function
-
- @function.setter
- def function(self, value):
- self._function = value
-
- @property
- def arch(self):
- return self._arch
-
- @arch.setter
- def arch(self, value):
- self._arch = value
-
- @property
- def address(self):
- return self._address
-
- @address.setter
- def address(self, value):
- self._address = value
-
- @property
- def size(self):
- return self._size
-
- @size.setter
- def size(self, value):
- self._size = value
-
+ return "<ref: %#x, size: %#x>" % (self.address, self.size) \ No newline at end of file
diff --git a/python/variable.py b/python/variable.py
index 0b793c15..1e496797 100644
--- a/python/variable.py
+++ b/python/variable.py
@@ -21,7 +21,7 @@
import ctypes
from typing import List, Generator, Optional, Union, Set, Mapping
-from dataclasses import dataclass
+from dataclasses import dataclass, field
import binaryninja
from . import _binaryninjacore as core
@@ -39,9 +39,6 @@ class LookupTableEntry(object):
def type(self):
return RegisterValueType.LookupTableValue
-@dataclass(frozen=True)
-class Confidence:
- confidence:int=core.max_confidence
@dataclass(frozen=True)
class RegisterValue:
@@ -52,16 +49,14 @@ class RegisterValue:
def _to_api_object(self):
result = core.BNRegisterValue()
- result.type = self.type
- result._value = self.value
+ result.state = self.type
+ result.value = self.value
result.offset = self.offset
return result
def _to_api_object_with_confidence(self):
- result = core.BNRegisterValue()
- result.type = self.type
- result._value = self.value
- result.offset = self.offset
+ result = core.BNRegisterValueWithConfidence()
+ result.value = self._to_api_object()
result.confidence = self.confidence
return result
@@ -87,6 +82,7 @@ class RegisterValue:
confidence = core.max_confidence
if isinstance(reg_value, core.BNRegisterValueWithConfidence):
confidence = reg_value.confidence
+ reg_value = reg_value.value
if reg_value.state == RegisterValueType.EntryValue:
reg = None
if arch is not None:
@@ -94,14 +90,18 @@ class RegisterValue:
return EntryRegisterValue(reg_value.value, reg=reg, confidence=confidence)
elif reg_value.state == RegisterValueType.ConstantValue:
return ConstantRegisterValue(reg_value.value, confidence=confidence)
- elif reg_value.state == RegisterValueType.ConstantValue:
+ elif reg_value.state == RegisterValueType.ConstantPointerValue:
return ConstantPointerRegisterValue(reg_value.value, confidence=confidence)
elif reg_value.state == RegisterValueType.StackFrameOffset:
- return StackFrameOffsetRegisterValue(reg_value.value, reg_value.offset, confidence=confidence)
+ return StackFrameOffsetRegisterValue(reg_value.value, confidence=confidence)
elif reg_value.state == RegisterValueType.ImportedAddressValue:
return ImportedAddressRegisterValue(reg_value.value, confidence=confidence)
elif reg_value.state == RegisterValueType.UndeterminedValue:
return Undetermined()
+ elif reg_value.state == RegisterValueType.ReturnAddressValue:
+ return ReturnAddressRegisterValue(reg_value.value, confidence=confidence)
+ elif reg_value.state == RegisterValueType.ExternalPointerValue:
+ return ExternalPointerRegisterValue(reg_value.value, reg_value.offset, confidence=confidence)
assert False, f"RegisterValueType {reg_value.state} not handled"
@@ -111,6 +111,9 @@ class Undetermined(RegisterValue):
offset:int = 0
type:RegisterValueType = RegisterValueType.UndeterminedValue
+ def __repr__(self):
+ return "<undetermined>"
+
@dataclass(frozen=True, eq=False)
class ConstantRegisterValue(RegisterValue):
@@ -156,19 +159,18 @@ class EntryRegisterValue(RegisterValue):
reg:Optional['binaryninja.architecture.RegisterName'] = None
def __repr__(self):
+ if self.reg is not None:
+ return f"<entry {self.reg}>"
return f"<entry {self.value}>"
- @classmethod
- def from_BNRegisterValue(cls, value:core.BNRegisterValue):
- cls(value.state, value.value, value.offset)
-
@dataclass(frozen=True, eq=False)
class StackFrameOffsetRegisterValue(RegisterValue):
+ offset:int = 0
type:RegisterValueType = RegisterValueType.StackFrameOffset
def __repr__(self):
- return f"<stack frame offset {self.offset:#x}>"
+ return f"<stack frame offset {self.value:#x}>"
@dataclass(frozen=True, eq=False)
class ExternalPointerRegisterValue(RegisterValue):
@@ -177,39 +179,22 @@ class ExternalPointerRegisterValue(RegisterValue):
def __repr__(self):
return f"<external {self.value:#x} + offset {self.offset:#x}>"
-@decorators.passive
+
+@dataclass(frozen=True)
class ValueRange(object):
- def __init__(self, start, end, step):
- self._start = start
- self._end = end
- self._step = step
+ start:int
+ end:int
+ step:int
def __repr__(self):
if self.step == 1:
return f"<range: {self.start:#x} to {self.end:#x}>"
return f"<range: {self.start:#x} to {self.end:#x}, step {self.step:#x}>"
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.start == other.start and self.end == other.end and self.step == other.step
-
def __contains__(self, other):
if not isinstance(other, int):
return NotImplemented
- return other in range(self._start, self._end, self._step)
-
- @property
- def start(self):
- return self._start
-
- @property
- def end(self):
- return self._end
-
- @property
- def step(self):
- return self._step
+ return other in range(self.start, self.end, self.step)
@decorators.passive
@@ -390,7 +375,8 @@ class PossibleValueSet(object):
for value in self.values:
values[i] = value
i += 1
- result.valueSet = ctypes.cast(values, ctypes.POINTER(ctypes.c_longlong))
+ int_ptr = ctypes.POINTER(ctypes.c_longlong)
+ result.valueSet = ctypes.cast(values, int_ptr)
result.count = self.count
return result
@@ -566,67 +552,31 @@ class PossibleValueSet(object):
return result
-@decorators.passive
+@dataclass(frozen=True)
class StackVariableReference(object):
- def __init__(self, src_operand, t, name, var, ref_ofs, size):
- self._source_operand = src_operand
- self._type = t
- self._name = name
- self._var = var
- self._referenced_offset = ref_ofs
- self._size = size
- if self._source_operand == 0xffffffff:
- self._source_operand = None
+ _source_operand:Optional[int]
+ type:'binaryninja.types.Type'
+ name:str
+ var:'Variable'
+ referenced_offset:int
+ size:int
def __repr__(self):
- if self._source_operand is None:
- if self._referenced_offset != self._var.storage:
- return "<ref to %s%+#x>" % (self._name, self._referenced_offset - self._var.storage)
- return "<ref to %s>" % self._name
- if self._referenced_offset != self._var.storage:
- return "<operand %d ref to %s%+#x>" % (self._source_operand, self._name, self._var.storage)
- return "<operand %d ref to %s>" % (self._source_operand, self._name)
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return (self._source_operand, self._type, self._name, self._var, self._referenced_offset, self._size) == \
- (other._source_operand, other._type, other._name, other._var, other._referenced_offset, other._size)
-
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
-
- def __hash__(self):
- return hash((self._source_operand, self._type, self._name, self._var, self._referenced_offset, self._size))
+ if self.source_operand is None:
+ if self.referenced_offset != self.var.storage:
+ return f"<ref to {self.name}{self.referenced_offset - self.var.storage:+#x}>"
+ return f"<ref to {self.name}>"
+ if self.referenced_offset != self.var.storage:
+ return f"<operand {self.source_operand} ref to {self.var.storage}{self.var.storage:+#x}>"
+ return f"<operand {self.source_operand} ref to {self.name}>"
@property
def source_operand(self):
+ if self._source_operand == 0xffffffff:
+ return None
return self._source_operand
- @property
- def type(self):
- return self._type
-
- @property
- def name(self):
- return self._name
- @property
- def var(self):
- return self._var
-
- @property
- def referenced_offset(self):
- return self._referenced_offset
-
- @property
- def size(self):
- return self._size
-
-
-@decorators.passive
@dataclass(frozen=True, order=True)
class CoreVariable:
_source_type:int
@@ -657,7 +607,7 @@ class CoreVariable:
var = core.BNFromVariableIdentifier(identifier)
return cls(var.type, var.index, var.storage)
-@decorators.passive
+
@dataclass(frozen=True, order=True)
class VariableNameAndType(CoreVariable):
name:str
@@ -792,13 +742,12 @@ class Variable:
def to_BNVariable(self):
return self._var.to_BNVariable()
-@decorators.passive
+@dataclass(frozen=True)
class ConstantReference(object):
- def __init__(self, val, size, ptr, intermediate):
- self._value = val
- self._size = size
- self._pointer = ptr
- self._intermediate = intermediate
+ value:int
+ size:int
+ pointer:bool
+ intermediate:bool
def __repr__(self):
if self.pointer:
@@ -807,45 +756,17 @@ class ConstantReference(object):
return "<constant %#x>" % self.value
return "<constant %#x size %d>" % (self.value, self.size)
- @property
- def value(self):
- return self._value
-
- @property
- def size(self):
- return self._size
-
- @property
- def pointer(self):
- return self._pointer
-
- @property
- def intermediate(self):
- return self._intermediate
-
-
-@decorators.passive
-class UserVariableValueInfo(object):
- def __init__(self, var, def_site, value):
- self.var = var
- self.def_site = def_site
- self.value = value
-
- def __repr__(self):
- return "<user value for %s @ %s:%#x -> %s>" % (self.var, self.def_site.arch.name, self.def_site.addr, self.value)
-
-@decorators.passive
+@dataclass(frozen=True)
class IndirectBranchInfo(object):
- def __init__(self, source_arch, source_addr, dest_arch, dest_addr, auto_defined):
- self.source_arch = source_arch
- self.source_addr = source_addr
- self.dest_arch = dest_arch
- self.dest_addr = dest_addr
- self.auto_defined = auto_defined
+ source_arch:'binaryninja.architecture.Architecture'
+ source_addr:int
+ dest_arch:'binaryninja.architecture.Architecture'
+ dest_addr:int
+ auto_defined:bool
def __repr__(self):
- return "<branch %s:%#x -> %s:%#x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr)
+ return f"<branch {self.source_arch.name}:{self.source_addr:#x} -> {self.dest_arch.name}:{self.dest_addr:#x}>"
@decorators.passive
@@ -889,39 +810,10 @@ class ParameterVariables(object):
return self._func
-@decorators.passive
+@dataclass(frozen=True, order=True)
class AddressRange(object):
- def __init__(self, start:int, end:int):
- self._start = start
- self._end = end
+ start:int
+ end:int
def __repr__(self):
- return "<%#x-%#x>" % (self._start, self._end)
-
- def __len__(self):
- return self._end - self.start
-
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return (self._start, self._end) == (other._start, other._end)
-
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
-
- def __hash__(self):
- return hash((self._start, self._end))
-
- @property
- def length(self) -> int:
- return self._end - self._start
-
- @property
- def start(self) -> int:
- return self._start
-
- @property
- def end(self) -> int:
- return self._end \ No newline at end of file
+ return f"<{self.start:#x}-{self.end:#x}>" \ No newline at end of file