Skip to content

Commit

Permalink
Inline uc_tracecode when there is only exactly one hook
Browse files Browse the repository at this point in the history
  • Loading branch information
wtdcode committed Nov 21, 2021
1 parent 18d7f09 commit 87a391d
Show file tree
Hide file tree
Showing 31 changed files with 173 additions and 6 deletions.
10 changes: 10 additions & 0 deletions include/uc_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ struct hook {
void *user_data;
};

// Add an inline hook to helper_table
typedef void (*uc_add_inline_hook_t)(struct uc_struct *uc, struct hook *hk,
void **args, int args_len);

// Delete a hook from helper_table
typedef void (*uc_del_inline_hook_t)(struct uc_struct *uc, struct hook *hk);

// hook list offsets
//
// The lowest 6 bits are used for hook type index while the others
Expand Down Expand Up @@ -254,6 +261,8 @@ struct uc_struct {
uc_tcg_flush_tlb tcg_flush_tlb;
uc_invalidate_tb_t uc_invalidate_tb;
uc_gen_tb_t uc_gen_tb;
uc_add_inline_hook_t add_inline_hook;
uc_del_inline_hook_t del_inline_hook;

/* only 1 cpu in unicorn,
do not need current_cpu to handle current running cpu. */
Expand Down Expand Up @@ -296,6 +305,7 @@ struct uc_struct {
// linked lists containing hooks per type
struct list hook[UC_HOOK_MAX];
struct list hooks_to_del;
int hooks_count[UC_HOOK_MAX];

// hook to count number of instructions for uc_emu_start()
uc_hook count_hook;
Expand Down
2 changes: 2 additions & 0 deletions qemu/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _aarch64
#endif
#define uc_add_inline_hook uc_add_inline_hook_aarch64
#define uc_del_inline_hook uc_del_inline_hook_aarch64
#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64
#define use_idiv_instructions use_idiv_instructions_aarch64
#define arm_arch arm_arch_aarch64
Expand Down
2 changes: 2 additions & 0 deletions qemu/aarch64eb.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _aarch64eb
#endif
#define uc_add_inline_hook uc_add_inline_hook_aarch64eb
#define uc_del_inline_hook uc_del_inline_hook_aarch64eb
#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64eb
#define use_idiv_instructions use_idiv_instructions_aarch64eb
#define arm_arch arm_arch_aarch64eb
Expand Down
4 changes: 4 additions & 0 deletions qemu/accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,10 @@ void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size)
/* Invalidate / Cache TBs */
uc->uc_invalidate_tb = uc_invalidate_tb;
uc->uc_gen_tb = uc_gen_tb;

/* Inline hooks optimization */
uc->add_inline_hook = uc_add_inline_hook;
uc->del_inline_hook = uc_del_inline_hook;
}

/* call with @p->lock held */
Expand Down
2 changes: 2 additions & 0 deletions qemu/arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _arm
#endif
#define uc_add_inline_hook uc_add_inline_hook_arm
#define uc_del_inline_hook uc_del_inline_hook_arm
#define tb_invalidate_phys_range tb_invalidate_phys_range_arm
#define use_idiv_instructions use_idiv_instructions_arm
#define arm_arch arm_arch_arm
Expand Down
2 changes: 2 additions & 0 deletions qemu/armeb.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _armeb
#endif
#define uc_add_inline_hook uc_add_inline_hook_armeb
#define uc_del_inline_hook uc_del_inline_hook_armeb
#define tb_invalidate_phys_range tb_invalidate_phys_range_armeb
#define use_idiv_instructions use_idiv_instructions_armeb
#define arm_arch arm_arch_armeb
Expand Down
34 changes: 31 additions & 3 deletions qemu/include/tcg/tcg-op.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,41 @@
static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc)
{
TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size);
TCGv_i32 ttype = tcg_const_i32(tcg_ctx, type);
TCGv_i32 ttype;
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc);
TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc);
gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc);
TCGv_ptr tdata;
uc_engine* puc = uc;
struct list_item *cur;
struct hook* hk;
TCGTemp* args[] = {
tcgv_ptr_temp(tcg_ctx, tuc),
tcgv_i64_temp(tcg_ctx, tpc),
tcgv_i32_temp(tcg_ctx, tsize),
0
};

if (puc->hooks_count[type] == 1) {
cur = puc->hook[type].head;

while (cur) {
hk = cur->data;
if (!hk->to_delete) {
tdata = tcg_const_ptr(tcg_ctx, hk->user_data);
args[3] = tcgv_ptr_temp(tcg_ctx, tdata);
puc->add_inline_hook(uc, hk, (void**)args, 4);
tcg_temp_free_ptr(tcg_ctx, tdata);
}
cur = cur->next;
}

} else {
ttype = tcg_const_i32(tcg_ctx, type);
gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc);
tcg_temp_free_i32(tcg_ctx, ttype);
}
tcg_temp_free_i64(tcg_ctx, tpc);
tcg_temp_free_ptr(tcg_ctx, tuc);
tcg_temp_free_i32(tcg_ctx, ttype);
tcg_temp_free_i32(tcg_ctx, tsize);
}

Expand Down
3 changes: 3 additions & 0 deletions qemu/include/tcg/tcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1561,4 +1561,7 @@ struct jit_code_entry {
uint64_t symfile_size;
};

void uc_del_inline_hook(uc_engine *uc, struct hook *hk);
void uc_add_inline_hook(uc_engine *uc, struct hook *hk, void** args, int args_len);

#endif /* TCG_H */
2 changes: 2 additions & 0 deletions qemu/m68k.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _m68k
#endif
#define uc_add_inline_hook uc_add_inline_hook_m68k
#define uc_del_inline_hook uc_del_inline_hook_m68k
#define tb_invalidate_phys_range tb_invalidate_phys_range_m68k
#define use_idiv_instructions use_idiv_instructions_m68k
#define arm_arch arm_arch_m68k
Expand Down
2 changes: 2 additions & 0 deletions qemu/mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _mips
#endif
#define uc_add_inline_hook uc_add_inline_hook_mips
#define uc_del_inline_hook uc_del_inline_hook_mips
#define tb_invalidate_phys_range tb_invalidate_phys_range_mips
#define use_idiv_instructions use_idiv_instructions_mips
#define arm_arch arm_arch_mips
Expand Down
2 changes: 2 additions & 0 deletions qemu/mips64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _mips64
#endif
#define uc_add_inline_hook uc_add_inline_hook_mips64
#define uc_del_inline_hook uc_del_inline_hook_mips64
#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64
#define use_idiv_instructions use_idiv_instructions_mips64
#define arm_arch arm_arch_mips64
Expand Down
2 changes: 2 additions & 0 deletions qemu/mips64el.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _mips64el
#endif
#define uc_add_inline_hook uc_add_inline_hook_mips64el
#define uc_del_inline_hook uc_del_inline_hook_mips64el
#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64el
#define use_idiv_instructions use_idiv_instructions_mips64el
#define arm_arch arm_arch_mips64el
Expand Down
2 changes: 2 additions & 0 deletions qemu/mipsel.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _mipsel
#endif
#define uc_add_inline_hook uc_add_inline_hook_mipsel
#define uc_del_inline_hook uc_del_inline_hook_mipsel
#define tb_invalidate_phys_range tb_invalidate_phys_range_mipsel
#define use_idiv_instructions use_idiv_instructions_mipsel
#define arm_arch arm_arch_mipsel
Expand Down
2 changes: 2 additions & 0 deletions qemu/ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _ppc
#endif
#define uc_add_inline_hook uc_add_inline_hook_ppc
#define uc_del_inline_hook uc_del_inline_hook_ppc
#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc
#define use_idiv_instructions use_idiv_instructions_ppc
#define arm_arch arm_arch_ppc
Expand Down
2 changes: 2 additions & 0 deletions qemu/ppc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _ppc64
#endif
#define uc_add_inline_hook uc_add_inline_hook_ppc64
#define uc_del_inline_hook uc_del_inline_hook_ppc64
#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc64
#define use_idiv_instructions use_idiv_instructions_ppc64
#define arm_arch arm_arch_ppc64
Expand Down
2 changes: 2 additions & 0 deletions qemu/riscv32.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _riscv32
#endif
#define uc_add_inline_hook uc_add_inline_hook_riscv32
#define uc_del_inline_hook uc_del_inline_hook_riscv32
#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv32
#define use_idiv_instructions use_idiv_instructions_riscv32
#define arm_arch arm_arch_riscv32
Expand Down
2 changes: 2 additions & 0 deletions qemu/riscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _riscv64
#endif
#define uc_add_inline_hook uc_add_inline_hook_riscv64
#define uc_del_inline_hook uc_del_inline_hook_riscv64
#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv64
#define use_idiv_instructions use_idiv_instructions_riscv64
#define arm_arch arm_arch_riscv64
Expand Down
2 changes: 2 additions & 0 deletions qemu/sparc.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _sparc
#endif
#define uc_add_inline_hook uc_add_inline_hook_sparc
#define uc_del_inline_hook uc_del_inline_hook_sparc
#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc
#define use_idiv_instructions use_idiv_instructions_sparc
#define arm_arch arm_arch_sparc
Expand Down
2 changes: 2 additions & 0 deletions qemu/sparc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _sparc64
#endif
#define uc_add_inline_hook uc_add_inline_hook_sparc64
#define uc_del_inline_hook uc_del_inline_hook_sparc64
#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc64
#define use_idiv_instructions use_idiv_instructions_sparc64
#define arm_arch arm_arch_sparc64
Expand Down
3 changes: 3 additions & 0 deletions qemu/target/arm/translate-a64.c
Original file line number Diff line number Diff line change
Expand Up @@ -14420,7 +14420,10 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc_curr)) {

// Sync PC in advance
TCGContext *tcg_ctx = env->uc->tcg_ctx;
gen_a64_set_pc_im(tcg_ctx, s->pc_curr);

gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, env->uc, s->pc_curr);
// the callback might want to stop emulation immediately
Expand Down
8 changes: 8 additions & 0 deletions qemu/target/arm/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -10910,6 +10910,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc_curr)) {

// Sync PC in advance
gen_set_pc_im(s, s->pc_curr);

gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, s->uc, s->pc_curr);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
Expand Down Expand Up @@ -11538,6 +11542,10 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
// Unicorn: trace this instruction on request
insn_size = is_16bit ? 2 : 4;
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, dc->base.pc_next - insn_size)) {

// Sync PC in advance
gen_set_pc_im(dc, dc->base.pc_next - insn_size);

if (uc->no_exit_request) {
gen_uc_tracecode(tcg_ctx, insn_size, UC_HOOK_CODE_IDX | UC_HOOK_FLAG_NO_STOP, uc, dc->base.pc_next - insn_size);
} else {
Expand Down
3 changes: 3 additions & 0 deletions qemu/target/i386/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -4811,6 +4811,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
s->last_cc_op = s->cc_op;
}

// Sync PC in advance
gen_jmp_im(s, pc_start);

// save the last operand
prev_op = tcg_last_op(tcg_ctx);
insn_hook = true;
Expand Down
4 changes: 4 additions & 0 deletions qemu/target/m68k/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -6333,6 +6333,10 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, dc->pc)) {

// Sync PC in advance
tcg_gen_movi_i32(tcg_ctx, QREG_PC, dc->pc);

gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, uc, dc->pc);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
Expand Down
4 changes: 4 additions & 0 deletions qemu/target/mips/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -30941,6 +30941,10 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, ctx->base.pc_next)) {

// Sync PC in advance
gen_save_pc(tcg_ctx, ctx->base.pc_next);

// save the last operand
prev_op = tcg_last_op(tcg_ctx);
hook_insn = true;
Expand Down
4 changes: 4 additions & 0 deletions qemu/target/ppc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -7633,6 +7633,10 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, ctx->base.pc_next)) {

// Sypc PC in advance
gen_update_nip(ctx, ctx->base.pc_next);

gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, uc, ctx->base.pc_next);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
Expand Down
4 changes: 4 additions & 0 deletions qemu/target/riscv/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,10 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
} else {
// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, ctx->base.pc_next)) {

// Sync PC in advance
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc, ctx->base.pc_next);

// save the last operand
prev_op = tcg_last_op(tcg_ctx);
insn_hook = true;
Expand Down
4 changes: 4 additions & 0 deletions qemu/target/sparc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -5961,6 +5961,10 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)

// Unicorn: trace this instruction on request
if (HOOK_EXISTS_BOUNDED(uc, UC_HOOK_CODE, dc->pc)) {

// Sync PC in advance
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc, dc->pc);

gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, uc, dc->pc);
// the callback might want to stop emulation immediately
check_exit_request(tcg_ctx);
Expand Down
48 changes: 48 additions & 0 deletions qemu/tcg/tcg.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,54 @@ static void process_op_defs(TCGContext *s);
static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
TCGReg reg, const char *name);

void uc_add_inline_hook(uc_engine *uc, struct hook *hk, void** args, int args_len)
{
TCGHelperInfo* info = g_malloc(sizeof(TCGHelperInfo));
char *name = g_malloc(64);
unsigned sizemask = 0xFFFFFFFF;
TCGContext *tcg_ctx = uc->tcg_ctx;
GHashTable *helper_table = uc->tcg_ctx->helper_table;

info->func = hk->callback;
info->name = name;
info->flags = 0; // From helper-head.h

// Only UC_HOOK_BLOCK and UC_HOOK_CODE is generated into tcg code and can be inlined.
switch (hk->type) {
case UC_HOOK_BLOCK:
case UC_HOOK_CODE:
// (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, void *user_data);
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1) | dh_sizemask(i32, 2) | dh_sizemask(void, 3);
snprintf(name, 63, "hookcode_%d_%" PRIx64 , hk->type, (uint64_t)hk->callback);
break;

default:
break;
}

name[63] = 0;
info->name = name;
info->sizemask = sizemask;

g_hash_table_insert(helper_table, (gpointer)info->func, (gpointer)info);

tcg_gen_callN(tcg_ctx, info->func, NULL, args_len, (TCGTemp**)args);
}

void uc_del_inline_hook(uc_engine *uc, struct hook *hk)
{
GHashTable *helper_table = uc->tcg_ctx->helper_table;
TCGHelperInfo* info = g_hash_table_lookup(helper_table, hk->callback);

if (info) {
g_hash_table_remove(helper_table, info);

g_free((gpointer)info->name);
g_free(info);
}
}


void tcg_context_init(TCGContext *s)
{
int op, total_args, n, i;
Expand Down
2 changes: 2 additions & 0 deletions qemu/x86_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#ifndef UNICORN_ARCH_POSTFIX
#define UNICORN_ARCH_POSTFIX _x86_64
#endif
#define uc_add_inline_hook uc_add_inline_hook_x86_64
#define uc_del_inline_hook uc_del_inline_hook_x86_64
#define tb_invalidate_phys_range tb_invalidate_phys_range_x86_64
#define use_idiv_instructions use_idiv_instructions_x86_64
#define arm_arch arm_arch_x86_64
Expand Down
Loading

0 comments on commit 87a391d

Please sign in to comment.