summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2024-03-02 14:38:47 -0500
committerBrian Potchik <brian@vector35.com>2024-03-02 14:38:47 -0500
commit2e3b9c925390cc8b1d72a41d0564bb2862d3dba2 (patch)
treef40495cd494b8c157a0298259019873a624dc7e2 /python
parentff2aa7435c3847f6969364f5d04d0943918429be (diff)
Add support for memory intrinsics.
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py24
-rw-r--r--python/lowlevelil.py75
-rw-r--r--python/mediumlevelil.py67
3 files changed, 161 insertions, 5 deletions
diff --git a/python/architecture.py b/python/architecture.py
index 677192e4..c979eacb 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -28,7 +28,7 @@ import binaryninja
from . import _binaryninjacore as core
from .enums import (
Endianness, ImplicitRegisterExtend, BranchType, LowLevelILFlagCondition, FlagRole, LowLevelILOperation,
- InstructionTextTokenType, InstructionTextTokenContext
+ InstructionTextTokenType, InstructionTextTokenContext, IntrinsicClass
)
from .log import log_error
from . import lowlevelil
@@ -300,6 +300,7 @@ class Architecture(metaclass=_ArchitectureMetaClass):
self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__(self._get_register_stack_name)
self._cb.getAllRegisterStacks = self._cb.getAllRegisterStacks.__class__(self._get_all_register_stacks)
self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__(self._get_register_stack_info)
+ self._cb.getIntrinsicClass = self._cb.getIntrinsicClass.__class__(self._get_intrinsic_class)
self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__(self._get_intrinsic_name)
self._cb.getAllIntrinsics = self._cb.getAllIntrinsics.__class__(self._get_all_intrinsics)
self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__(self._get_intrinsic_inputs)
@@ -481,6 +482,7 @@ class Architecture(metaclass=_ArchitectureMetaClass):
self.system_regs = self.__class__.system_regs
self._intrinsics: Dict[IntrinsicName, IntrinsicIndex] = {}
+ self._intrinsic_class_by_index: Dict[IntrinsicIndex, IntrinsicClass] = {}
self._intrinsics_by_index: Dict[IntrinsicIndex, Tuple[IntrinsicName, IntrinsicInfo]] = {}
intrinsic_index = IntrinsicIndex(0)
for intrinsic in self.__class__.intrinsics.keys():
@@ -1125,6 +1127,11 @@ class Architecture(metaclass=_ArchitectureMetaClass):
result[0].topRelativeCount = 0
result[0].stackTopReg = 0
+ def _get_intrinsic_class(self, ctxt, intrinsic):
+ if intrinsic in self._intrinsic_class_by_index:
+ return self._intrinsic_class_by_index[intrinsic]
+ return IntrinsicClass.GeneralIntrinsicClass
+
def _get_intrinsic_name(self, ctxt, intrinsic):
try:
if intrinsic in self._intrinsics_by_index:
@@ -1549,6 +1556,16 @@ class Architecture(metaclass=_ArchitectureMetaClass):
raise ValueError("argument 'group_index' must be an integer")
return self._semantic_flag_groups_by_index[group_index]
+ def get_intrinsic_class(self, intrinsic: IntrinsicIndex) -> IntrinsicClass:
+ """
+ ``get_intrinsic_class`` gets the intrinsic class from an intrinsic number.
+
+ :param int intrinsic: intrinsic number
+ :return: intrinsic class
+ :rtype: IntrinsicClass
+ """
+ return IntrinsicClass(core.BNGetArchitectureIntrinsicClass(self.handle, intrinsic))
+
def get_intrinsic_name(self, intrinsic: IntrinsicIndex) -> IntrinsicName:
"""
``get_intrinsic_name`` gets an intrinsic name from an intrinsic number.
@@ -2261,9 +2278,11 @@ class CoreArchitecture(Architecture):
intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count)
assert intrinsics is not None, "core.BNGetAllArchitectureIntrinsics returned None"
self._intrinsics: Dict[IntrinsicName, IntrinsicIndex] = {}
+ self._intrinsic_class_by_index: Dict[IntrinsicIndex, IntrinsicClass] = {}
self._intrinsics_by_index: Dict[IntrinsicIndex, Tuple[IntrinsicName, IntrinsicInfo]] = {}
self._intrinsics_info: Dict[IntrinsicName, IntrinsicInfo] = {}
for i in range(count.value):
+ intrinsic_class = IntrinsicClass(core.BNGetArchitectureIntrinsicClass(self.handle, intrinsics[i]))
name = IntrinsicName(core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i]))
input_count = ctypes.c_ulonglong()
inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count)
@@ -2285,6 +2304,8 @@ class CoreArchitecture(Architecture):
types.Type.create(core.BNNewTypeReference(outputs[j].type), confidence=outputs[j].confidence)
)
core.BNFreeOutputTypeList(outputs, output_count.value)
+ if intrinsic_class is not IntrinsicClass.GeneralIntrinsicClass:
+ self._intrinsic_class_by_index[intrinsics[i]] = intrinsic_class
self._intrinsics_info[name] = IntrinsicInfo(input_list, output_list)
self._intrinsics[name] = intrinsics[i]
self._intrinsics_by_index[intrinsics[i]] = (name, self._intrinsics_info[name])
@@ -2719,6 +2740,7 @@ class ArchitectureHook(CoreArchitecture):
self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__()
self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__()
if len(self.__class__.intrinsics) == 0:
+ self._cb.getIntrinsicClass = self._cb.getIntrinsicClass.__class__()
self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__()
self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__()
self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__()
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 9b2bd4ae..590cae83 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -385,6 +385,10 @@ class LowLevelILInstruction(BaseILInstruction):
("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")
], LowLevelILOperation.LLIL_INTRINSIC_SSA: [
("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")
+ ], LowLevelILOperation.LLIL_MEMORY_INTRINSIC_OUTPUT_SSA: [
+ ("dest_memory", "int"), ("output", "reg_ssa_list")
+ ], LowLevelILOperation.LLIL_MEMORY_INTRINSIC_SSA: [
+ ("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")
], LowLevelILOperation.LLIL_BP: [], LowLevelILOperation.LLIL_TRAP: [("vector", "int")],
LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [
("src", "expr")
@@ -550,7 +554,7 @@ class LowLevelILInstruction(BaseILInstruction):
def tokens(self) -> TokenList:
"""LLIL tokens (read-only)"""
# special case for those instructions that don't have tokens
- if isinstance(self, (LowLevelILCallOutputSsa, LowLevelILCallParam, LowLevelILCallStackSsa)):
+ if isinstance(self, (LowLevelILCallOutputSsa, LowLevelILCallParam, LowLevelILCallStackSsa, LowLevelILMemoryIntrinsicOutputSsa)):
return []
count = ctypes.c_ulonglong()
@@ -2625,6 +2629,71 @@ class LowLevelILIntrinsicSsa(LowLevelILInstruction, SSA):
@dataclass(frozen=True, repr=False, eq=False)
+class LowLevelILMemoryIntrinsicOutputSsa(LowLevelILInstruction, SSA):
+ def __repr__(self):
+ return f"<LowLevelILMemoryIntrinsicOutputSsa: {self.dest_memory} {self.output}>"
+
+ @property
+ def dest_memory(self) -> int:
+ return self._get_int(0)
+
+ @property
+ def output(self) -> List[SSARegisterOrFlag]:
+ return self._get_reg_or_flag_ssa_list(1)
+
+ @property
+ def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]:
+ return [
+ ("dest_memory", self.dest_memory, "int"),
+ ("output", self.output, "List[SSARegisterOrFlag]"),
+ ]
+
+
+@dataclass(frozen=True, repr=False, eq=False)
+class LowLevelILMemoryIntrinsicSsa(LowLevelILInstruction, SSA):
+ @property
+ def output(self) -> List[SSARegisterOrFlag]:
+ inst = self._get_expr(0)
+ assert isinstance(inst, LowLevelILMemoryIntrinsicOutputSsa), "LowLevelILMemoryIntrinsicSsa expected LowLevelILMemoryIntrinsicOutputSsa as first operand"
+ return inst.output
+
+ @property
+ def dest_memory(self) -> int:
+ inst = self._get_expr(0)
+ assert isinstance(inst, LowLevelILMemoryIntrinsicOutputSsa), "LowLevelILMemoryIntrinsicSsa expected LowLevelILMemoryIntrinsicOutputSsa as first operand"
+ return inst.dest_memory
+
+ @property
+ def intrinsic(self) -> ILIntrinsic:
+ return self._get_intrinsic(1)
+
+ @property
+ def param(self) -> LowLevelILCallParam:
+ # kept for backwards compatibility use 'params' instead
+ result = self._get_expr(2)
+ assert isinstance(result, LowLevelILCallParam)
+ return result
+
+ @property
+ def params(self) -> List[LowLevelILInstruction]:
+ return self.param.src
+
+ @property
+ def src_memory(self) -> int:
+ return self._get_int(3)
+
+ @property
+ def detailed_operands(self) -> List[Tuple[str, LowLevelILOperandType, str]]:
+ return [
+ ("output", self.output, "List[SSARegisterOrFlag]"),
+ ("intrinsic", self.intrinsic, "ILIntrinsic"),
+ ("params", self.params, "List[LowLevelILInstruction]"),
+ ("dest_memory", self.dest_memory, "int"),
+ ("src_memory", self.src_memory, "int"),
+ ]
+
+
+@dataclass(frozen=True, repr=False, eq=False)
class LowLevelILSetRegSsaPartial(LowLevelILInstruction, SetReg, SSA):
@property
def full_reg(self) -> SSARegister:
@@ -2991,7 +3060,9 @@ ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: igno
LowLevelILOperation.LLIL_ADD_OVERFLOW: LowLevelILAddOverflow, # [("left", "expr"), ("right", "expr")],
LowLevelILOperation.LLIL_SYSCALL: LowLevelILSyscall, # [],
LowLevelILOperation.LLIL_INTRINSIC: LowLevelILIntrinsic, # [("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")],
- LowLevelILOperation.LLIL_INTRINSIC_SSA: LowLevelILIntrinsicSsa, # [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")],
+ LowLevelILOperation.LLIL_INTRINSIC_SSA: LowLevelILIntrinsicSsa, # [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ LowLevelILOperation.LLIL_MEMORY_INTRINSIC_OUTPUT_SSA: LowLevelILMemoryIntrinsicOutputSsa, # [("dest_memory", "int"), ("output", "reg_or_flag_ssa_list")],
+ LowLevelILOperation.LLIL_MEMORY_INTRINSIC_SSA: LowLevelILMemoryIntrinsicSsa, # [("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")],
LowLevelILOperation.LLIL_BP: LowLevelILBp, # [],
LowLevelILOperation.LLIL_TRAP: LowLevelILTrap, # [("vector", "int")],
LowLevelILOperation.LLIL_UNDEF: LowLevelILUndef, # [],
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 05eeb449..53f87cdc 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -263,6 +263,10 @@ class MediumLevelILInstruction(BaseILInstruction):
("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")
], MediumLevelILOperation.MLIL_INTRINSIC_SSA: [
("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")
+ ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_OUTPUT_SSA: [
+ ("dest_memory", "int"), ("output", "var_ssa_list")
+ ], MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_SSA: [
+ ("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")
], MediumLevelILOperation.MLIL_FREE_VAR_SLOT: [
("dest", "var")
], MediumLevelILOperation.MLIL_FREE_VAR_SLOT_SSA: [
@@ -2222,6 +2226,64 @@ class MediumLevelILIntrinsicSsa(MediumLevelILInstruction, SSA):
@dataclass(frozen=True, repr=False, eq=False)
+class MediumLevelILMemoryIntrinsicOutputSsa(MediumLevelILInstruction, SSA):
+ def __repr__(self):
+ return f"<MediumLevelILMemoryIntrinsicOutputSsa: {self.dest_memory} {self.output}>"
+
+ @property
+ def dest_memory(self) -> int:
+ return self._get_int(0)
+
+ @property
+ def output(self) -> List[SSAVariable]:
+ return self._get_var_ssa_list(1, 2)
+
+ @property
+ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]:
+ return [
+ ("dest_memory", self.dest_memory, "int"),
+ ("output", self.output, "List[SSAVariable]"),
+ ]
+
+
+@dataclass(frozen=True, repr=False, eq=False)
+class MediumLevelILMemoryIntrinsicSsa(MediumLevelILInstruction, SSA):
+ @property
+ def output(self) -> List[SSAVariable]:
+ inst = self._get_expr(0)
+ assert isinstance(inst, MediumLevelILMemoryIntrinsicOutputSsa), "MediumLevelILMemoryIntrinsicSsa expected MediumLevelILMemoryIntrinsicOutputSsa as first operand"
+ return inst.output
+
+ @property
+ def dest_memory(self) -> int:
+ inst = self._get_expr(0)
+ assert isinstance(inst, MediumLevelILMemoryIntrinsicOutputSsa), "MediumLevelILMemoryIntrinsicSsa expected MediumLevelILMemoryIntrinsicOutputSsa as first operand"
+ return inst.dest_memory
+
+ @property
+ def intrinsic(self) -> 'lowlevelil.ILIntrinsic':
+ return self._get_intrinsic(1)
+
+ @property
+ def params(self) -> List[MediumLevelILInstruction]:
+ return self._get_expr_list(2, 3)
+
+ @property
+ def src_memory(self) -> int:
+ return self._get_int(4)
+
+ @property
+ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]:
+ return [
+ ("output", self.output, "List[SSAVariable]"),
+ ("dest_memory", self.dest_memory, "int"),
+ ("intrinsic", self.intrinsic, "ILIntrinsic"),
+ ("params", self.params, "List[MediumLevelILInstruction]"),
+ ("src_memory", self.src_memory, "int"),
+ ]
+
+
+@dataclass(frozen=True, repr=False, eq=False)
class MediumLevelILSetVarSsaField(MediumLevelILInstruction, SetVar, SSA):
@property
def dest(self) -> SSAVariable:
@@ -2996,8 +3058,9 @@ ILInstruction = {
MediumLevelILTailcall, # [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")],
MediumLevelILOperation.MLIL_INTRINSIC:
MediumLevelILIntrinsic, # [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
- MediumLevelILOperation.MLIL_INTRINSIC_SSA:
- MediumLevelILIntrinsicSsa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_INTRINSIC_SSA: MediumLevelILIntrinsicSsa, # [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")],
+ MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_OUTPUT_SSA: MediumLevelILMemoryIntrinsicOutputSsa, # [("dest_memory", "int"), ("output", "var_ssa_list")],
+ MediumLevelILOperation.MLIL_MEMORY_INTRINSIC_SSA: MediumLevelILMemoryIntrinsicSsa, # [("output", "expr"), ("intrinsic", "intrinsic"), ("params", "expr_list"), ("src_memory", "int")],
MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD:
MediumLevelILSetVarSsaField, # [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")],
MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: