summaryrefslogtreecommitdiff
path: root/python/variable.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/variable.py')
-rw-r--r--python/variable.py58
1 files changed, 58 insertions, 0 deletions
diff --git a/python/variable.py b/python/variable.py
index ee0d93a4..1cd703c9 100644
--- a/python/variable.py
+++ b/python/variable.py
@@ -25,6 +25,7 @@ from dataclasses import dataclass
import binaryninja
from . import _binaryninjacore as core
+from . import databuffer
from . import decorators
from .enums import RegisterValueType, VariableSourceType, DeadStoreElimination, FunctionGraphType
@@ -49,12 +50,14 @@ class RegisterValue:
offset: int
type: RegisterValueType = RegisterValueType.UndeterminedValue
confidence: int = core.max_confidence
+ size: int = 0
def _to_core_struct(self) -> core.BNRegisterValue:
result = core.BNRegisterValue()
result.state = self.type
result.value = self.value
result.offset = self.offset
+ result.size = self.size
return result
def _to_core_struct_with_confidence(self):
@@ -107,6 +110,8 @@ class RegisterValue:
return ReturnAddressRegisterValue(reg_value.value, confidence=confidence)
elif reg_value.state == RegisterValueType.ExternalPointerValue:
return ExternalPointerRegisterValue(reg_value.value, reg_value.offset, confidence=confidence)
+ elif reg_value.state & RegisterValueType.ConstantDataValue == RegisterValueType.ConstantDataValue:
+ return ConstantDataRegisterValue(reg_value.value, 0, reg_value.state, confidence=confidence, size=reg_value.size)
assert False, f"RegisterValueType {reg_value.state} not handled"
@@ -186,6 +191,41 @@ class ExternalPointerRegisterValue(RegisterValue):
return f"<external {self.value:#x} + offset {self.offset:#x}>"
+@dataclass(frozen=True, eq=False)
+class ConstantDataRegisterValue(RegisterValue):
+
+ def __repr__(self):
+ if self.type == RegisterValueType.ConstantDataZeroExtendValue:
+ return f"<const data {{zx.{self.size}({self.value:#x})}}>"
+ if self.type == RegisterValueType.ConstantDataSignExtendValue:
+ return f"<const data {{sx.{self.size}({self.value:#x})}}>"
+ if self.type == RegisterValueType.ConstantDataAggregateValue:
+ return f"<const data {{aggregate.{self.size}}} @ {self.value:#x}>"
+ return f"<const data {{invalid}} {self.type} {self.value:#x}>"
+
+
+@dataclass(frozen=True, eq=False)
+class ConstantData(RegisterValue):
+ function: '_function.Function' = None
+
+ def __repr__(self):
+ if self.type == RegisterValueType.ConstantDataZeroExtendValue:
+ return f"<const data {{zx.{self.size}({self.value:#x})}}>"
+ if self.type == RegisterValueType.ConstantDataSignExtendValue:
+ return f"<const data {{sx.{self.size}({self.value:#x})}}>"
+ if self.type == RegisterValueType.ConstantDataAggregateValue:
+ return f"<const data {{aggregate.{self.size}}} @ {self.value:#x}>"
+ return f"<const data {{invalid}} {self.type} {self.value:#x}>"
+
+ @property
+ def data(self) -> databuffer.DataBuffer:
+ if self.size <= 8:
+ raise ValueError(f"Invalid ConstantData with size: {self.size}")
+ if self.function is None:
+ raise ValueError(f"ConstantData requires a Function instance: {self.size}")
+ return self.function.get_constant_data(self.type, self.value, self.size)
+
+
@dataclass(frozen=True)
class ValueRange:
start: int
@@ -226,6 +266,9 @@ class PossibleValueSet:
self._value = value.value
elif value.state == RegisterValueType.StackFrameOffset:
self._offset = value.value
+ elif value.state & RegisterValueType.ConstantDataValue == RegisterValueType.ConstantDataValue:
+ self._value = value.value
+ self._size = value.size
elif value.state == RegisterValueType.SignedRangeValue:
self._offset = value.value
self._ranges = []
@@ -270,6 +313,12 @@ class PossibleValueSet:
return f"<const ptr {self.value:#x}>"
if self._type == RegisterValueType.StackFrameOffset:
return f"<stack frame offset {self._offset:#x}>"
+ if self._type == RegisterValueType.ConstantDataZeroExtendValue:
+ return f"<const data {{zx.{self._size}({self.value:#x})}}>"
+ if self._type == RegisterValueType.ConstantDataSignExtendValue:
+ return f"<const data {{sx.{self._size}({self.value:#x})}}>"
+ if self._type == RegisterValueType.ConstantDataAggregateValue:
+ return f"<const data {{aggregate.{self._size}}} @ {self.value:#x}>"
if self._type == RegisterValueType.SignedRangeValue:
return f"<signed ranges: {repr(self.ranges)}>"
if self._type == RegisterValueType.UnsignedRangeValue:
@@ -317,6 +366,8 @@ class PossibleValueSet:
return self.value == other.value
elif self.type == RegisterValueType.StackFrameOffset:
return self.offset == other.offset
+ elif self.type & RegisterValueType.ConstantDataValue == RegisterValueType.ConstantDataValue:
+ return self.value == other.value and self._size == other._size
elif self.type in [RegisterValueType.SignedRangeValue, RegisterValueType.UnsignedRangeValue]:
return self.ranges == other.ranges
elif self.type in [RegisterValueType.InSetOfValues, RegisterValueType.NotInSetOfValues]:
@@ -342,6 +393,9 @@ class PossibleValueSet:
result.value = self.value
elif self.type == RegisterValueType.StackFrameOffset:
result.offset = self.value
+ elif self.type & RegisterValueType.ConstantDataValue == RegisterValueType.ConstantDataValue:
+ result.value = self.value
+ result.size = self.size
elif self.type == RegisterValueType.SignedRangeValue:
result.offset = self.value
result.ranges = (core.BNValueRange * self.count)()
@@ -406,6 +460,10 @@ class PossibleValueSet:
return self._offset
@property
+ def size(self) -> int:
+ return self._size
+
+ @property
def ranges(self) -> List[ValueRange]:
return self._ranges