From dc1f7a88d5a749653f56a4db07cb9c13bbb03700 Mon Sep 17 00:00:00 2001 From: dotcirill <33807714+dotCirill@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:01:21 +0300 Subject: [PATCH] Uc hook tcg improve (#2011) * Add handling UC_TCG_OP_FLAG_CMP for ARM Implementation is not well-tested and complete * Hook ARM32 CMP and CMN for cmplog --- qemu/target/arm/translate.c | 23 ++++++++++++ tests/unit/test_arm.c | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 079b727a..2db5ccd2 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -31,6 +31,7 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" +#include "uc_priv.h" #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T) #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5) @@ -451,9 +452,29 @@ static void gen_sub_carry(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_ tcg_gen_subi_i32(tcg_ctx, dest, dest, 1); } +static inline void mb_tcg_opcode_cmp_hook(TCGContext *tcg_ctx, TCGv_i64 v0, TCGv_i64 v1, uint32_t size) +{ + CPUARMState *cpuarm = (CPUARMState *)(tcg_ctx->cpu->env_ptr); + uint64_t pc = cpuarm->regs[15] + (cpuarm->thumb ? 1 : 0); + uc_engine *uc = tcg_ctx->uc; + if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, pc)) { + struct hook *hook; + HOOK_FOREACH_VAR_DECLARE; + HOOK_FOREACH(uc, hook, UC_HOOK_TCG_OPCODE) { + if (hook->to_delete) + continue; + if (hook->op == UC_TCG_OP_SUB && (hook->op_flags & UC_TCG_OP_FLAG_CMP)) { + gen_uc_traceopcode(tcg_ctx, hook, v0, v1, size, uc, pc); + } + } + } +} + /* dest = T0 + T1. Compute C, N, V and Z flags */ static void gen_add_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { + mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32); + TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx); tcg_gen_movi_i32(tcg_ctx, tmp, 0); tcg_gen_add2_i32(tcg_ctx, tcg_ctx->cpu_NF, tcg_ctx->cpu_CF, t0, tmp, t1, tmp); @@ -496,6 +517,8 @@ static void gen_adc_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 /* dest = T0 - T1. Compute C, N, V and Z flags */ static void gen_sub_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { + mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32); + TCGv_i32 tmp; tcg_gen_sub_i32(tcg_ctx, tcg_ctx->cpu_NF, t0, t1); tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_ZF, tcg_ctx->cpu_NF); diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 3b15950d..665b9a29 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -861,6 +861,74 @@ static void test_arm_mem_hook_read_write(void) OK(uc_close(uc)); } +typedef struct { + uint64_t v0; + uint64_t v1; + uint64_t size; + uint64_t pc; +} _last_cmp_info; + +static void _uc_hook_sub_cmp(uc_engine *uc, uint64_t address, uint64_t arg1, + uint64_t arg2, uint32_t size, + _last_cmp_info *user_data) +{ + user_data->pc = address; + user_data->size = size; + user_data->v0 = arg1; + user_data->v1 = arg2; +} + +static void test_arm_tcg_opcode_cmp(void) +{ + uc_engine *uc; + const char code[] = "\x04\x00\x9f\xe5" // ldr r0, [pc, #4] + "\x04\x10\x9f\xe5" // ldr r1, [pc, #4] + "\x01\x00\x50\xe1" // cmp r0, r1 + "\x05\x00\x00\x00" // (5) + "\x03\x00\x00\x00" // (3) + ; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1, + UC_CPU_ARM_CORTEX_A15); + + uc_hook hook; + _last_cmp_info cmp_info = {0}; + + OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp, + (void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); + TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3); + TEST_CHECK(cmp_info.pc == code_start); + TEST_CHECK(cmp_info.size == 32); +} + +static void test_arm_thumb_tcg_opcode_cmn(void) +{ + uc_engine *uc; + const char code[] = "\x01\x48" // ldr r0, [pc, #4] + "\x02\x49" // ldr r1, [pc, #8] + "\x00\xbf" // nop + "\xc8\x42" // cmn r0, r1 + "\x05\x00\x00\x00" // (5) + "\x03\x00\x00\x00" // (3) + ; + + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1, + UC_CPU_ARM_CORTEX_A15); + + uc_hook hook; + _last_cmp_info cmp_info = {0}; + + OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp, + (void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP)); + + OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 4)); + TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3); + TEST_CHECK(cmp_info.pc == (code_start | 1)); + TEST_CHECK(cmp_info.size == 32); +} + TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb_sub", test_arm_thumb_sub}, {"test_armeb_sub", test_armeb_sub}, @@ -887,4 +955,6 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb2", test_arm_thumb2}, {"test_armeb_be32_thumb2", test_armeb_be32_thumb2}, {"test_arm_mem_hook_read_write", test_arm_mem_hook_read_write}, + {"test_arm_tcg_opcode_cmp", test_arm_tcg_opcode_cmp}, + {"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn}, {NULL, NULL}};