Skip to content

Commit dc1f7a8

Browse files
authored
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
1 parent ada8091 commit dc1f7a8

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

qemu/target/arm/translate.c

+23
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "exec/helper-proto.h"
3333
#include "exec/helper-gen.h"
34+
#include "uc_priv.h"
3435

3536
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
3637
#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_
451452
tcg_gen_subi_i32(tcg_ctx, dest, dest, 1);
452453
}
453454

455+
static inline void mb_tcg_opcode_cmp_hook(TCGContext *tcg_ctx, TCGv_i64 v0, TCGv_i64 v1, uint32_t size)
456+
{
457+
CPUARMState *cpuarm = (CPUARMState *)(tcg_ctx->cpu->env_ptr);
458+
uint64_t pc = cpuarm->regs[15] + (cpuarm->thumb ? 1 : 0);
459+
uc_engine *uc = tcg_ctx->uc;
460+
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, pc)) {
461+
struct hook *hook;
462+
HOOK_FOREACH_VAR_DECLARE;
463+
HOOK_FOREACH(uc, hook, UC_HOOK_TCG_OPCODE) {
464+
if (hook->to_delete)
465+
continue;
466+
if (hook->op == UC_TCG_OP_SUB && (hook->op_flags & UC_TCG_OP_FLAG_CMP)) {
467+
gen_uc_traceopcode(tcg_ctx, hook, v0, v1, size, uc, pc);
468+
}
469+
}
470+
}
471+
}
472+
454473
/* dest = T0 + T1. Compute C, N, V and Z flags */
455474
static void gen_add_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
456475
{
476+
mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32);
477+
457478
TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
458479
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
459480
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
496517
/* dest = T0 - T1. Compute C, N, V and Z flags */
497518
static void gen_sub_CC(TCGContext *tcg_ctx, TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
498519
{
520+
mb_tcg_opcode_cmp_hook(tcg_ctx, (TCGv_i64)t0, (TCGv_i64)t1, 32);
521+
499522
TCGv_i32 tmp;
500523
tcg_gen_sub_i32(tcg_ctx, tcg_ctx->cpu_NF, t0, t1);
501524
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_ZF, tcg_ctx->cpu_NF);

tests/unit/test_arm.c

+70
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,74 @@ static void test_arm_mem_hook_read_write(void)
861861
OK(uc_close(uc));
862862
}
863863

864+
typedef struct {
865+
uint64_t v0;
866+
uint64_t v1;
867+
uint64_t size;
868+
uint64_t pc;
869+
} _last_cmp_info;
870+
871+
static void _uc_hook_sub_cmp(uc_engine *uc, uint64_t address, uint64_t arg1,
872+
uint64_t arg2, uint32_t size,
873+
_last_cmp_info *user_data)
874+
{
875+
user_data->pc = address;
876+
user_data->size = size;
877+
user_data->v0 = arg1;
878+
user_data->v1 = arg2;
879+
}
880+
881+
static void test_arm_tcg_opcode_cmp(void)
882+
{
883+
uc_engine *uc;
884+
const char code[] = "\x04\x00\x9f\xe5" // ldr r0, [pc, #4]
885+
"\x04\x10\x9f\xe5" // ldr r1, [pc, #4]
886+
"\x01\x00\x50\xe1" // cmp r0, r1
887+
"\x05\x00\x00\x00" // (5)
888+
"\x03\x00\x00\x00" // (3)
889+
;
890+
891+
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1,
892+
UC_CPU_ARM_CORTEX_A15);
893+
894+
uc_hook hook;
895+
_last_cmp_info cmp_info = {0};
896+
897+
OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp,
898+
(void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP));
899+
900+
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3));
901+
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
902+
TEST_CHECK(cmp_info.pc == code_start);
903+
TEST_CHECK(cmp_info.size == 32);
904+
}
905+
906+
static void test_arm_thumb_tcg_opcode_cmn(void)
907+
{
908+
uc_engine *uc;
909+
const char code[] = "\x01\x48" // ldr r0, [pc, #4]
910+
"\x02\x49" // ldr r1, [pc, #8]
911+
"\x00\xbf" // nop
912+
"\xc8\x42" // cmn r0, r1
913+
"\x05\x00\x00\x00" // (5)
914+
"\x03\x00\x00\x00" // (3)
915+
;
916+
917+
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1,
918+
UC_CPU_ARM_CORTEX_A15);
919+
920+
uc_hook hook;
921+
_last_cmp_info cmp_info = {0};
922+
923+
OK(uc_hook_add(uc, &hook, UC_HOOK_TCG_OPCODE, (void *)_uc_hook_sub_cmp,
924+
(void *)&cmp_info, 1, 0, UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP));
925+
926+
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 4));
927+
TEST_CHECK(cmp_info.v0 == 5 && cmp_info.v1 == 3);
928+
TEST_CHECK(cmp_info.pc == (code_start | 1));
929+
TEST_CHECK(cmp_info.size == 32);
930+
}
931+
864932
TEST_LIST = {{"test_arm_nop", test_arm_nop},
865933
{"test_arm_thumb_sub", test_arm_thumb_sub},
866934
{"test_armeb_sub", test_armeb_sub},
@@ -887,4 +955,6 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop},
887955
{"test_arm_thumb2", test_arm_thumb2},
888956
{"test_armeb_be32_thumb2", test_armeb_be32_thumb2},
889957
{"test_arm_mem_hook_read_write", test_arm_mem_hook_read_write},
958+
{"test_arm_tcg_opcode_cmp", test_arm_tcg_opcode_cmp},
959+
{"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn},
890960
{NULL, NULL}};

0 commit comments

Comments
 (0)