Add a new hook type UC_HOOK_TCG_OPCODE

This commit is contained in:
lazymio
2021-11-03 01:46:24 +01:00
parent eb75d459f0
commit bcf85be86d
15 changed files with 241 additions and 2 deletions

View File

@ -42,6 +42,24 @@ static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t t
tcg_temp_free_i32(tcg_ctx, tsize);
}
static inline void gen_uc_traceopcode(TCGContext *tcg_ctx, void* hook, TCGv_i64 arg1, TCGv_i64 arg2, void *uc, uint64_t pc)
{
TCGv_ptr thook = tcg_const_ptr(tcg_ctx, hook);
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc);
TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc);
// #if TARGET_LONG_BITS == 32
// TCGv_i64 targ1 = temp_tcgv_i64(tcg_ctx, tcgv_i32_temp(tcg_ctx, arg1));
// TCGv_i64 targ2 = temp_tcgv_i64(tcg_ctx, tcgv_i32_temp(tcg_ctx, arg2));
// #else
// TCGv_i64 targ1 = arg1;
// TCGv_i64 targ2 = arg2;
// #endif
gen_helper_uc_traceopcode(tcg_ctx, thook, arg1, arg2, tuc, tpc);
tcg_temp_free_i64(tcg_ctx, tpc);
tcg_temp_free_ptr(tcg_ctx, tuc);
tcg_temp_free_ptr(tcg_ctx, thook);
}
/* Basic output routines. Not for general consumption. */
void tcg_gen_op1(TCGContext *tcg_ctx, TCGOpcode, TCGArg);
@ -422,6 +440,20 @@ static inline void tcg_gen_add_i32(TCGContext *tcg_ctx, TCGv_i32 ret, TCGv_i32 a
static inline void tcg_gen_sub_i32(TCGContext *tcg_ctx, TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
uc_engine *uc = tcg_ctx->uc;
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, tcg_ctx->pc_start)) {
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 == 0) {
gen_uc_traceopcode(tcg_ctx, hook, (TCGv_i64)arg1, (TCGv_i64)arg2, uc, tcg_ctx->pc_start);
}
}
}
tcg_gen_op3_i32(tcg_ctx, INDEX_op_sub_i32, ret, arg1, arg2);
}
@ -641,6 +673,20 @@ static inline void tcg_gen_add_i64(TCGContext *tcg_ctx, TCGv_i64 ret, TCGv_i64 a
static inline void tcg_gen_sub_i64(TCGContext *tcg_ctx, TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
uc_engine *uc = tcg_ctx->uc;
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, tcg_ctx->pc_start)) {
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 == 0) {
gen_uc_traceopcode(tcg_ctx, hook, arg1, arg2, uc, tcg_ctx->pc_start);
}
}
}
tcg_gen_op3_i64(tcg_ctx, INDEX_op_sub_i64, ret, arg1, arg2);
}

View File

@ -791,6 +791,9 @@ struct TCGContext {
TCGv NULL_QREG;
/* Used to distinguish stores from bad addressing modes. */
TCGv store_dummy;
// Used to store the start of current instrution.
uint64_t pc_start;
};
static inline size_t temp_idx(TCGContext *tcg_ctx, TCGTemp *ts)

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_FLAGS_1(sxtb16, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_1(uxtb16, TCG_CALL_NO_RWG_SE, i32, i32)

View File

@ -477,6 +477,19 @@ static uc_err arm_query(struct uc_struct *uc, uc_query_type type,
}
}
static bool arm_opcode_hook_invalidate(uint32_t op, uint32_t flags)
{
if (op != UC_TCG_OP_SUB) {
return false;
}
if (flags == UC_TCG_OP_FLAG_CMP && op != UC_TCG_OP_SUB) {
return false;
}
return true;
}
static int arm_cpus_init(struct uc_struct *uc, const char *cpu_model)
{
ARMCPU *cpu;
@ -503,6 +516,7 @@ void arm_uc_init(struct uc_struct *uc)
uc->release = arm_release;
uc->query = arm_query;
uc->cpus_init = arm_cpus_init;
uc->opcode_hook_invalidate = arm_opcode_hook_invalidate;
uc->cpu_context_size = offsetof(CPUARMState, cpu_watchpoint);
uc_common_init(uc);
}

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)
DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int)

View File

@ -1479,6 +1479,7 @@ static void gen_illegal_opcode(DisasContext *s)
static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
{
TCGContext *tcg_ctx = s1->uc->tcg_ctx;
uc_engine *uc = s1->uc;
if (d != OR_TMP0) {
if (s1->prefix & PREFIX_LOCK) {
@ -1542,6 +1543,23 @@ static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
tcg_gen_sub_tl(tcg_ctx, s1->T0, s1->T0, s1->T1);
gen_op_st_rm_T0_A0(s1, ot, d);
}
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, s1->pc_start)) {
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_DIRECT) ) {
// TCGv is just an offset to tcg_ctx so it's safe to do so.
if ( (hook->op_flags & UC_TCG_OP_FLAG_IMM) && d != OR_EAX) {
continue;
}
gen_uc_traceopcode(tcg_ctx, hook, (TCGv_i64)s1->T0, (TCGv_i64)s1->T1, uc, s1->pc_start);
}
}
}
gen_op_update2_cc(s1);
set_cc_op(s1, CC_OP_SUBB + ot);
break;
@ -1583,6 +1601,23 @@ static void gen_op(DisasContext *s1, int op, MemOp ot, int d)
tcg_gen_mov_tl(tcg_ctx, tcg_ctx->cpu_cc_src, s1->T1);
tcg_gen_mov_tl(tcg_ctx, s1->cc_srcT, s1->T0);
tcg_gen_sub_tl(tcg_ctx, tcg_ctx->cpu_cc_dst, s1->T0, s1->T1);
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_TCG_OPCODE, s1->pc_start)) {
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) ) {
// TCGv is just an offset to tcg_ctx so it's safe to do so.
if ( (hook->op_flags & UC_TCG_OP_FLAG_IMM) && d != OR_EAX) {
continue;
}
gen_uc_traceopcode(tcg_ctx, hook, (TCGv_i64)s1->T0, (TCGv_i64)s1->T1, uc, s1->pc_start);
}
}
}
set_cc_op(s1, CC_OP_SUBB + ot);
break;
}
@ -4759,7 +4794,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
TCGOp *tcg_op, *prev_op = NULL;
bool insn_hook = false;
s->pc_start = s->pc = pc_start;
s->pc_start = tcg_ctx->pc_start = s->pc = pc_start;
s->prefix = 0;
s->uc = env->uc;

View File

@ -1569,6 +1569,32 @@ static bool x86_insn_hook_validate(uint32_t insn_enum)
return true;
}
static bool x86_opcode_hook_invalidate(uint32_t op, uint32_t flags)
{
if (op != UC_TCG_OP_SUB) {
return false;
}
switch (op) {
case UC_TCG_OP_SUB:
if (flags == UC_TCG_OP_FLAG_IMM) {
return false;
}
if ((flags & UC_TCG_OP_FLAG_CMP) && (flags & UC_TCG_OP_FLAG_DIRECT)) {
return false;
}
break;
default:
return false;
}
return true;
}
static int x86_cpus_init(struct uc_struct *uc, const char *cpu_model)
{
@ -1592,6 +1618,7 @@ void x86_uc_init(struct uc_struct *uc)
uc->set_pc = x86_set_pc;
uc->stop_interrupt = x86_stop_interrupt;
uc->insn_hook_validate = x86_insn_hook_validate;
uc->opcode_hook_invalidate = x86_opcode_hook_invalidate;
uc->cpus_init = x86_cpus_init;
uc->cpu_context_size = offsetof(CPUX86State, retaddr);
uc_common_init(uc);

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_1(bitrev, i32, i32)
DEF_HELPER_1(ff1, i32, i32)

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
DEF_HELPER_2(raise_exception, noreturn, env, i32)

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, void, env, i32, i32)
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, void, env, i32)

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
DEF_HELPER_1(uc_riscv_exit, void, env)
/* Exceptions */

View File

@ -1,4 +1,5 @@
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
DEF_HELPER_5(uc_traceopcode, void, ptr, i64, i64, ptr, i64)
#ifndef TARGET_SPARC64
DEF_HELPER_1(rett, void, env)