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
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
|
#include "uc_priv.h"
|
||||||
|
|
||||||
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
|
#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
|
||||||
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
|
#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);
|
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 */
|
/* 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)
|
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);
|
TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
|
||||||
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
|
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);
|
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 */
|
/* 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)
|
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;
|
TCGv_i32 tmp;
|
||||||
tcg_gen_sub_i32(tcg_ctx, tcg_ctx->cpu_NF, t0, t1);
|
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);
|
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_ZF, tcg_ctx->cpu_NF);
|
||||||
|
|||||||
@@ -861,6 +861,74 @@ static void test_arm_mem_hook_read_write(void)
|
|||||||
OK(uc_close(uc));
|
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_LIST = {{"test_arm_nop", test_arm_nop},
|
||||||
{"test_arm_thumb_sub", test_arm_thumb_sub},
|
{"test_arm_thumb_sub", test_arm_thumb_sub},
|
||||||
{"test_armeb_sub", test_armeb_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_arm_thumb2", test_arm_thumb2},
|
||||||
{"test_armeb_be32_thumb2", test_armeb_be32_thumb2},
|
{"test_armeb_be32_thumb2", test_armeb_be32_thumb2},
|
||||||
{"test_arm_mem_hook_read_write", test_arm_mem_hook_read_write},
|
{"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}};
|
{NULL, NULL}};
|
||||||
|
|||||||
Reference in New Issue
Block a user