summaryrefslogtreecommitdiff
path: root/python
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
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')
-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