Make special regs definitions generic
This commit is contained in:
parent
0e63841628
commit
647832b01b
@ -9,13 +9,12 @@ import ctypes
|
||||
from .. import Uc
|
||||
from .. import arm_const as const
|
||||
|
||||
from .types import UcReg128
|
||||
from .types import UcTupledReg, UcReg128
|
||||
|
||||
ARMCPReg = Tuple[int, int, int, int, int, int, int]
|
||||
ARMCPRegValue = Tuple[int, int, int, int, int, int, int, int]
|
||||
ARMCPReg = Tuple[int, int, int, int, int, int, int, int]
|
||||
|
||||
|
||||
class UcRegCP(ctypes.Structure):
|
||||
class UcRegCP(UcTupledReg[ARMCPReg]):
|
||||
"""ARM coprocessors registers for instructions MRC, MCR, MRRC, MCRR
|
||||
"""
|
||||
|
||||
@ -34,12 +33,6 @@ class UcRegCP(ctypes.Structure):
|
||||
def value(self) -> int:
|
||||
return self.val
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: ARMCPRegValue):
|
||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
||||
|
||||
return cls(*param)
|
||||
|
||||
|
||||
class UcAArch32(Uc):
|
||||
"""Unicorn subclass for ARM architecture.
|
||||
|
@ -11,15 +11,14 @@ from .. import arm64_const as const
|
||||
|
||||
from ..unicorn import uccallback
|
||||
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
|
||||
from .types import uc_engine, UcReg128
|
||||
from .types import uc_engine, UcTupledReg, UcReg128
|
||||
|
||||
ARM64CPReg = Tuple[int, int, int, int, int]
|
||||
ARM64CPRegValue = Tuple[int, int, int, int, int, int]
|
||||
ARM64CPReg = Tuple[int, int, int, int, int, int]
|
||||
|
||||
HOOK_INSN_SYS_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p)
|
||||
|
||||
|
||||
class UcRegCP(ctypes.Structure):
|
||||
class UcRegCP(UcTupledReg[ARM64CPReg]):
|
||||
"""ARM64 coprocessors registers for instructions MRS, MSR
|
||||
"""
|
||||
|
||||
@ -36,12 +35,6 @@ class UcRegCP(ctypes.Structure):
|
||||
def value(self) -> int:
|
||||
return self.val
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: ARM64CPRegValue):
|
||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
||||
|
||||
return cls(*param)
|
||||
|
||||
|
||||
class UcAArch64(Uc):
|
||||
"""Unicorn subclass for ARM64 architecture.
|
||||
|
@ -11,9 +11,10 @@ from .. import x86_const as const
|
||||
|
||||
from ..unicorn import uccallback
|
||||
from ..unicorn_const import UC_ERR_ARG, UC_HOOK_INSN
|
||||
from .types import uc_engine, UcReg128, UcReg256, UcReg512
|
||||
from .types import uc_engine, UcTupledReg, UcReg128, UcReg256, UcReg512
|
||||
|
||||
X86MMRReg = Tuple[int, int, int, int]
|
||||
X86MSRReg = Tuple[int, int]
|
||||
X86FPReg = Tuple[int, int]
|
||||
|
||||
HOOK_INSN_IN_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_int, ctypes.c_void_p)
|
||||
@ -22,7 +23,7 @@ HOOK_INSN_SYSCALL_CFUNC = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
||||
HOOK_INSN_CPUID_CFUNC = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_void_p)
|
||||
|
||||
|
||||
class UcRegMMR(ctypes.Structure):
|
||||
class UcRegMMR(UcTupledReg[X86MMRReg]):
|
||||
"""Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.
|
||||
"""
|
||||
|
||||
@ -33,18 +34,8 @@ class UcRegMMR(ctypes.Structure):
|
||||
('flags', ctypes.c_uint32) # not used by GDTR and IDTR
|
||||
)
|
||||
|
||||
@property
|
||||
def value(self) -> X86MMRReg:
|
||||
return tuple(getattr(self, fname) for fname, _ in self._fields_)
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: X86MMRReg):
|
||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
||||
|
||||
return cls(*param)
|
||||
|
||||
|
||||
class UcRegMSR(ctypes.Structure):
|
||||
class UcRegMSR(UcTupledReg[X86MSRReg]):
|
||||
_fields_ = (
|
||||
('rid', ctypes.c_uint32),
|
||||
('val', ctypes.c_uint64)
|
||||
@ -54,29 +45,13 @@ class UcRegMSR(ctypes.Structure):
|
||||
def value(self) -> int:
|
||||
return self.val
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: Tuple[int, int]):
|
||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
||||
|
||||
return cls(*param)
|
||||
|
||||
|
||||
class UcRegFPR(ctypes.Structure):
|
||||
class UcRegFPR(UcTupledReg[X86FPReg]):
|
||||
_fields_ = (
|
||||
('mantissa', ctypes.c_uint64),
|
||||
('exponent', ctypes.c_uint16)
|
||||
)
|
||||
|
||||
@property
|
||||
def value(self) -> X86FPReg:
|
||||
return tuple(getattr(self, fname) for fname, _ in self._fields_)
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: X86FPReg):
|
||||
assert type(param) is tuple and len(param) == len(cls._fields_)
|
||||
|
||||
return cls(*param)
|
||||
|
||||
|
||||
class UcIntel(Uc):
|
||||
"""Unicorn subclass for Intel architecture.
|
||||
|
@ -2,6 +2,9 @@
|
||||
#
|
||||
# @author elicn
|
||||
|
||||
from abc import abstractmethod
|
||||
from typing import Generic, Tuple, TypeVar
|
||||
|
||||
import ctypes
|
||||
|
||||
uc_err = ctypes.c_int
|
||||
@ -12,7 +15,51 @@ uc_context = ctypes.c_void_p
|
||||
uc_hook_h = ctypes.c_size_t
|
||||
|
||||
|
||||
class UcLargeReg(ctypes.Structure):
|
||||
VT = TypeVar('VT', bound=Tuple[int, ...])
|
||||
|
||||
|
||||
class UcReg(ctypes.Structure):
|
||||
"""A base class for composite registers.
|
||||
|
||||
This class is meant to be inherited, not instantiated directly.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def value(self):
|
||||
"""Get register value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def from_value(cls, value):
|
||||
"""Create a register instance from a given value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class UcTupledReg(UcReg, Generic[VT]):
|
||||
"""A base class for registers whose values are represented as a set
|
||||
of fields.
|
||||
|
||||
This class is meant to be inherited, not instantiated directly.
|
||||
"""
|
||||
|
||||
@property
|
||||
def value(self) -> VT:
|
||||
return tuple(getattr(self, fname) for fname, *_ in self.__class__._fields_) # type: ignore
|
||||
|
||||
@classmethod
|
||||
def from_value(cls, value: VT):
|
||||
assert type(value) is tuple and len(value) == len(cls._fields_)
|
||||
|
||||
return cls(*value)
|
||||
|
||||
|
||||
class UcLargeReg(UcReg):
|
||||
"""A base class for large registers that are internally represented as
|
||||
an array of multiple qwords.
|
||||
|
||||
@ -26,13 +73,13 @@ class UcLargeReg(ctypes.Structure):
|
||||
return sum(qword << (64 * i) for i, qword in enumerate(self.qwords))
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param: int):
|
||||
assert type(param) is int
|
||||
def from_value(cls, value: int):
|
||||
assert type(value) is int
|
||||
|
||||
mask = (1 << 64) - 1
|
||||
size = cls._fields_[0][1]._length_
|
||||
|
||||
return cls(tuple((param >> (64 * i)) & mask for i in range(size)))
|
||||
return cls(tuple((value >> (64 * i)) & mask for i in range(size)))
|
||||
|
||||
|
||||
class UcReg128(UcLargeReg):
|
||||
|
@ -338,7 +338,7 @@ class RegStateManager:
|
||||
"""Register write helper method.
|
||||
"""
|
||||
|
||||
reg = regtype.from_param(value) if issubclass(regtype, ctypes.Structure) else regtype(value)
|
||||
reg = regtype.from_value(value) if issubclass(regtype, UcReg) else regtype(value)
|
||||
status = self._do_reg_write(reg_id, ctypes.byref(reg))
|
||||
|
||||
if status != uc.UC_ERR_OK:
|
||||
|
Loading…
Reference in New Issue
Block a user