From a998231a0ea2353b255c00d0a8912289d7509fe0 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Sat, 6 May 2023 01:42:15 -0700 Subject: [PATCH 1/3] Fix sample_ctl.py. Commit 640251e1aa added a size parameter to uc_hook_tcg_op_2, but this was not reflected in the Python bindings. Commit fbf4078d65 added a len parameter to ctl_remove_cache, but this was not reflected in sample_ctl.py. --- bindings/python/sample_ctl.py | 4 ++-- bindings/python/unicorn/unicorn.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/python/sample_ctl.py b/bindings/python/sample_ctl.py index 202a2094..1578a010 100755 --- a/bindings/python/sample_ctl.py +++ b/bindings/python/sample_ctl.py @@ -57,7 +57,7 @@ def test_uc_ctl_tb_cache(): # Now we clear cache for all TBs. for i in range(8): - uc.ctl_remove_cache(addr + i * 512) + uc.ctl_remove_cache(addr + i * 512, addr + i * 512 + 1) evicted = time_emulation(uc, addr, addr + len(code)) @@ -66,7 +66,7 @@ def test_uc_ctl_tb_cache(): def trace_new_edge(uc, cur, prev, data): print(f">>> Getting a new edge from {hex(prev.pc + prev.size - 1)} to {hex(cur.pc)}") -def trace_tcg_sub(uc, address, arg1, arg2, data): +def trace_tcg_sub(uc, address, arg1, arg2, size, data): print(f">>> Get a tcg sub opcode at {hex(address)} with args: {arg1} and {arg2}") def test_uc_ctl_exits(): diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index e893d6fe..bd266935 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -210,7 +210,7 @@ UC_HOOK_EDGE_GEN_CB = ctypes.CFUNCTYPE( None, uc_engine, ctypes.POINTER(uc_tb), ctypes.POINTER(uc_tb), ctypes.c_void_p ) UC_HOOK_TCG_OPCODE_CB = ctypes.CFUNCTYPE( - None, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p + None, uc_engine, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint32, ctypes.c_void_p ) # access to error code via @errno of UcError @@ -647,9 +647,9 @@ class Uc(object): return result.value @_catch_hook_exception - def _hook_tcg_op_cb(self, handle, address, arg1, arg2, user_data): + def _hook_tcg_op_cb(self, handle, address, arg1, arg2, size, user_data): (cb, data) = self._callbacks[user_data] - cb(self, address, arg1, arg2, user_data) + cb(self, address, arg1, arg2, size, user_data) @_catch_hook_exception def _hook_edge_gen_cb(self, handle, cur, prev, user_data): From d27ca4530b8bd776b92c0f0f31735a58e02b8605 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Sat, 6 May 2023 02:07:26 -0700 Subject: [PATCH 2/3] Minor Python fixes. - Match the types of UC_HOOK_CODE_CB and UC_HOOK_INSN_SYS_CB to C - Avoid building a new namedtuple class in every call to _hook_insn_sys_cb --- bindings/python/unicorn/unicorn.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index bd266935..b752d0b0 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -177,7 +177,7 @@ _setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes. _setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64) _setup_prototype(_uc, "uc_ctl", ucerr, uc_engine, ctypes.c_int) -UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) +UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_uint32, ctypes.c_void_p) UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p) UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE( ctypes.c_bool, uc_engine, ctypes.c_int, @@ -198,7 +198,7 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE( ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p ) UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p) -UC_HOOK_INSN_SYS_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p) +UC_HOOK_INSN_SYS_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) UC_HOOK_INSN_CPUID_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_void_p) UC_MMIO_READ_CB = ctypes.CFUNCTYPE( ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p @@ -424,6 +424,9 @@ class uc_arm64_cp_reg(ctypes.Structure): ("val", ctypes.c_uint64) ] + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, ", ".join("%s=%s" % (k, getattr(self, k)) for (k, _) in self._fields_)) + class uc_x86_mmr(ctypes.Structure): """Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.""" _fields_ = [ @@ -696,11 +699,9 @@ class Uc(object): def _hook_insn_sys_cb(self, handle, reg, pcp_reg, user_data): cp_reg = ctypes.cast(pcp_reg, ctypes.POINTER(uc_arm64_cp_reg)).contents - uc_arm64_cp_reg_tuple = namedtuple("uc_arm64_cp_reg_tuple", ["crn", "crm", "op0", "op1", "op2", "val"]) - (cb, data) = self._callbacks[user_data] - return cb(self, reg, uc_arm64_cp_reg_tuple(cp_reg.crn, cp_reg.crm, cp_reg.op0, cp_reg.op1, cp_reg.op2, cp_reg.val), data) + return cb(self, reg, cp_reg, data) @_catch_hook_exception def _hook_insn_out_cb(self, handle, port, size, value, user_data): From 06a76e98c482e9d886b60a7a020596f5f3843079 Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Wed, 10 May 2023 12:57:36 -0700 Subject: [PATCH 3/3] Add __repr__ to all ctypes.Structure subclasses --- bindings/python/unicorn/unicorn.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index b752d0b0..7313bd98 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -130,6 +130,9 @@ uc_engine = ctypes.c_void_p uc_context = ctypes.c_void_p uc_hook_h = ctypes.c_size_t +def _structure_repr(self): + return "%s(%s)" % (self.__class__.__name__, ", ".join("%s=%s" % (k, getattr(self, k)) for (k, _) in self._fields_)) + class _uc_mem_region(ctypes.Structure): _fields_ = [ ("begin", ctypes.c_uint64), @@ -137,6 +140,8 @@ class _uc_mem_region(ctypes.Structure): ("perms", ctypes.c_uint32), ] + __repr__ = _structure_repr + class uc_tb(ctypes.Structure): """"TranslationBlock""" _fields_ = [ @@ -145,6 +150,8 @@ class uc_tb(ctypes.Structure): ("size", ctypes.c_uint16) ] + __repr__ = _structure_repr + _setup_prototype(_uc, "uc_version", ctypes.c_uint, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) _setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) _setup_prototype(_uc, "uc_open", ucerr, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(uc_engine)) @@ -413,6 +420,8 @@ class uc_arm_cp_reg(ctypes.Structure): ("val", ctypes.c_uint64) ] + __repr__ = _structure_repr + class uc_arm64_cp_reg(ctypes.Structure): """ARM64 coprocessors registers for instructions MRS, MSR""" _fields_ = [ @@ -424,8 +433,7 @@ class uc_arm64_cp_reg(ctypes.Structure): ("val", ctypes.c_uint64) ] - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, ", ".join("%s=%s" % (k, getattr(self, k)) for (k, _) in self._fields_)) + __repr__ = _structure_repr class uc_x86_mmr(ctypes.Structure): """Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.""" @@ -436,12 +444,16 @@ class uc_x86_mmr(ctypes.Structure): ("flags", ctypes.c_uint32), # not used by GDTR and IDTR ] + __repr__ = _structure_repr + class uc_x86_msr(ctypes.Structure): _fields_ = [ ("rid", ctypes.c_uint32), ("value", ctypes.c_uint64), ] + __repr__ = _structure_repr + class uc_x86_float80(ctypes.Structure): """Float80""" _fields_ = [ @@ -449,6 +461,7 @@ class uc_x86_float80(ctypes.Structure): ("exponent", ctypes.c_uint16), ] + __repr__ = _structure_repr class uc_x86_xmm(ctypes.Structure): """128-bit xmm register""" @@ -457,6 +470,8 @@ class uc_x86_xmm(ctypes.Structure): ("high_qword", ctypes.c_uint64), ] + __repr__ = _structure_repr + class uc_x86_ymm(ctypes.Structure): """256-bit ymm register""" _fields_ = [ @@ -466,6 +481,8 @@ class uc_x86_ymm(ctypes.Structure): ("fourth_qword", ctypes.c_uint64), ] + __repr__ = _structure_repr + class uc_arm64_neon128(ctypes.Structure): """128-bit neon register""" _fields_ = [ @@ -473,6 +490,8 @@ class uc_arm64_neon128(ctypes.Structure): ("high_qword", ctypes.c_uint64), ] + __repr__ = _structure_repr + # Subclassing ref to allow property assignment. class UcRef(weakref.ref): pass