diff options
Diffstat (limited to 'python/variable.py')
| -rw-r--r-- | python/variable.py | 178 |
1 files changed, 104 insertions, 74 deletions
diff --git a/python/variable.py b/python/variable.py index 187d5e3d..011402d8 100644 --- a/python/variable.py +++ b/python/variable.py @@ -683,21 +683,76 @@ class StackVariableReference(object): @decorators.passive -class Variable(object): - def __init__(self, func, source_type, index, storage, name = None, var_type = None, identifier = None): +@dataclass(frozen=True, order=True) +class CoreVariable: + _source_type:int + index:int + storage:int + + @property + def identifier(self) -> int: + return core.BNToVariableIdentifier(self.to_BNVariable()) + + @property + def source_type(self) -> VariableSourceType: + return VariableSourceType(self._source_type) + + def to_BNVariable(self): + v = core.BNVariable() + v.type = self._source_type + v.index = self.index + v.storage = self.storage + return v + + @classmethod + def from_BNVariable(cls, var:core.BNVariable): + return cls(var.type, var.index, var.storage) + + @classmethod + def from_identifier(cls, identifier): + var = core.BNFromVariableIdentifier(identifier) + return cls(var.type, var.index, var.storage) + +@decorators.passive +@dataclass(frozen=True, order=True) +class VariableNameAndType(CoreVariable): + name:str + type:'binaryninja.types.Type' + + @classmethod + def from_identifier(cls, identifier, name, type): + var = core.BNFromVariableIdentifier(identifier) + return cls(name, type, var.type, var.index, var.storage) + + @classmethod + def from_core_variable(cls, var, name, type): + return cls(name, type, var.type, var.index, var.storage) + + +class Variable: + def __init__(self, func:'binaryninja.function.Function', source_type:VariableSourceType, index:int, storage:int): self._function = func - self._source_type = source_type - self._index = index - self._storage = storage - self._identifier = identifier - self._name = name - self._type = var_type + self._var = CoreVariable(source_type, index, storage) + + @classmethod + def from_variable_name_and_type(cls, func:'binaryninja.function.Function', var:VariableNameAndType): + return cls(func, VariableSourceType(var.type), var.index, var.storage) + + @classmethod + def from_core_variable(cls, func:'binaryninja.function.Function', var:CoreVariable): + return cls(func, var.source_type, var.index, var.storage) + + @classmethod + def from_BNVariable(cls, func:'binaryninja.function.Function', var:core.BNVariable): + return cls(func, var.type, var.index, var.storage) + + @classmethod + def from_identifier(cls, func:'binaryninja.function.Function', identifier:int): + var = core.BNFromVariableIdentifier(identifier) + return cls(func, VariableSourceType(var.type), var.index, var.storage) def __repr__(self): - if self.type is not None: - return f"<var {self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}>" - else: - return f"<var {self.name}>" + return f"<var {self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}>" def __str__(self): return self.name @@ -705,7 +760,7 @@ class Variable(object): def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return (self.identifier, self.function) == (other.identifier, other.function) + return (self.identifier, self._function) == (other.identifier, other._function) def __ne__(self, other): if not isinstance(other, self.__class__): @@ -715,108 +770,83 @@ class Variable(object): def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return (self.identifier, self.function) < (other.identifier, other.function) + return (self.identifier, self._function) < (other.identifier, other._function) def __gt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return (self.identifier, self.function) > (other.identifier, other.function) + return (self.identifier, self._function) > (other.identifier, other._function) def __le__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return (self.identifier, self.function) <= (other.identifier, other.function) + return (self.identifier, self._function) <= (other.identifier, other._function) def __ge__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return (self.identifier, self.function) >= (other.identifier, other.function) + return (self.identifier, self._function) >= (other.identifier, other._function) def __hash__(self): - return hash((self.identifier, self.function)) - - @property - def function(self) -> 'binaryninja.function.Function': - """Function where the variable is defined""" - return self._function - - @function.setter - def function(self, value:'binaryninja.function.Function'): - self._function = value + return hash((self.identifier)) @property def source_type(self) -> VariableSourceType: - """:class:`~enums.VariableSourceType`""" - if not isinstance(self._source_type, VariableSourceType): - self._source_type = VariableSourceType(self._source_type) - - return self._source_type - - @source_type.setter - def source_type(self, value:VariableSourceType) -> None: - self._source_type = value + return self._var.source_type @property def index(self) -> int: - return self._index - - @index.setter - def index(self, value:int) -> None: - self._index = value + return self._var.index @property def storage(self) -> int: """Stack offset for StackVariableSourceType, register index for RegisterVariableSourceType""" - return self._storage - - @storage.setter - def storage(self, value:int) -> None: - self._storage = value + return self._var.storage @property def identifier(self) -> int: - if self._identifier is None: - self._identifier = core.BNToVariableIdentifier(self.to_BNVariable()) - return self._identifier + return self._var.identifier + + @property + def core_var(self) -> CoreVariable: + return self._var + + @property + def var_name_and_type(self) -> VariableNameAndType: + return VariableNameAndType.from_core_variable(self._var, self.name, self.type) @property def name(self): """Name of the variable""" - if self._name is None: - if self._function is not None: - self._name = core.BNGetVariableName(self._function.handle, self.to_BNVariable()) - return self._name + return core.BNGetVariableName(self._function.handle, self._var.to_BNVariable()) + + @name.setter + def name(self, name:Optional[str]) -> None: + if name is None: + name = "" + self._function.create_user_var(self, self.type, name) @property - def type(self) -> Optional['binaryninja.types.Type']: - if self._type is None: - if self._function is not None: - var_type_conf = core.BNGetVariableType(self._function.handle, self.to_BNVariable()) - if var_type_conf.type: - self._type = binaryninja.types.Type(var_type_conf.type, platform = self._function.platform, confidence = var_type_conf.confidence) - return self._type + def type(self) -> 'binaryninja.types.Type': + var_type_conf = core.BNGetVariableType(self._function.handle, self._var.to_BNVariable()) + assert var_type_conf.type + _type = binaryninja.types.Type(var_type_conf.type, self._function.platform, var_type_conf.confidence) + return _type - def to_BNVariable(self): - v = core.BNVariable() - v.type = self.source_type - v.index = self._index - v.storage = self._storage - return v + @type.setter + def type(self, new_type:'binaryninja.types.Type') -> None: + self._function.create_user_var(self, new_type, self.name) @property def dead_store_elimination(self): - if self._function is not None and self._identifier is not None: - return DeadStoreElimination(core.BNGetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable())) - return None + return DeadStoreElimination(core.BNGetFunctionVariableDeadStoreElimination(self._function.handle, self._var.to_BNVariable())) @dead_store_elimination.setter def dead_store_elimination(self, value): - core.BNSetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable(), value) + core.BNSetFunctionVariableDeadStoreElimination(self._function.handle, self._var.to_BNVariable(), value) - @staticmethod - def from_identifier(func, identifier, name=None, var_type=None): - var = core.BNFromVariableIdentifier(identifier) - return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type, identifier) + def to_BNVariable(self): + return self._var.to_BNVariable() @decorators.passive class ConstantReference(object): |
