diff --git a/list.c b/list.c
index 695f5a24..6dbe4782 100644
--- a/list.c
+++ b/list.c
@@ -18,6 +18,8 @@ void list_clear(struct list *list)
         free(cur);
         cur = next;
     }
+    list->head = NULL;
+    list->tail = NULL;
 }
 
 // returns generated linked list node, or NULL on failure
diff --git a/qemu/target-arm/helper.h b/qemu/target-arm/helper.h
index d2de58d6..6427c18c 100644
--- a/qemu/target-arm/helper.h
+++ b/qemu/target-arm/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
+DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
 
 DEF_HELPER_FLAGS_1(clz_arm, TCG_CALL_NO_RWG_SE, i32, i32)
 
diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c
index 28d57681..06378453 100644
--- a/qemu/target-arm/translate-a64.c
+++ b/qemu/target-arm/translate-a64.c
@@ -10970,7 +10970,6 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
 {
     uint32_t insn;
-    struct hook *hook;
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
 
     // Unicorn: end address tells us to stop emulation
@@ -10985,10 +10984,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     s->pc += 4;
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, s->pc - 4))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 4, hook->callback, env->uc, s->pc - 4, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc - 4)) {
+        gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, env->uc, s->pc - 4);
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
     }
@@ -11044,7 +11041,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
     int max_insns;
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     bool block_full = false;
-    struct hook *hook;
 
     pc_start = tb->pc;
 
@@ -11116,14 +11112,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (! env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // save block address to see if we need to patch block size later
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        // save block address to see if we need to patch block size later
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c
index bf190452..d097c236 100644
--- a/qemu/target-arm/translate.c
+++ b/qemu/target-arm/translate.c
@@ -7680,7 +7680,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)  // qq
     TCGv_i32 tmp3;
     TCGv_i32 addr;
     TCGv_i64 tmp64;
-    struct hook *hook;
 
     /* M variants do not implement ARM mode.  */
     if (arm_dc_feature(s, ARM_FEATURE_M)) {
@@ -7688,10 +7687,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)  // qq
     }
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(s->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, s->pc - 4))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 4, hook->callback, s->uc, s->pc - 4, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc - 4)) {
+        gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, s->uc, s->pc - 4);
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
     }
@@ -10391,7 +10388,6 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
     TCGv_i32 tmp;
     TCGv_i32 tmp2;
     TCGv_i32 addr;
-    struct hook *hook;
 
     // Unicorn: end address tells us to stop emulation
     if (s->pc == s->uc->addr_end) {
@@ -10410,11 +10406,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
     }
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, s->pc))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data);
-        // check to see if we need to exit immediately
+    if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc)) {
+        gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, s->uc, s->pc);
+        // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
     }
 
@@ -11147,7 +11141,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     int max_insns;
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     bool block_full = false;
-    struct hook *hook;
 
     /* generate intermediate code */
 
@@ -11237,14 +11230,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (!env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // save block address to see if we need to patch block size later
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        // save block address to see if we need to patch block size later
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/target-i386/helper.h b/qemu/target-i386/helper.h
index 8ab196ac..d3b52d1f 100644
--- a/qemu/target-i386/helper.h
+++ b/qemu/target-i386/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
+DEF_HELPER_4(uc_tracecode, void, i32, i32, 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)
diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c
index 0d83f4bd..d68cb516 100644
--- a/qemu/target-i386/translate.c
+++ b/qemu/target-i386/translate.c
@@ -4745,7 +4745,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     TCGv cpu_tmp4 = *(TCGv *)tcg_ctx->cpu_tmp4;
     TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T;
     TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs;
-    struct hook *hook = NULL;
     TCGArg *save_opparam_ptr = tcg_ctx->gen_opparam_ptr;
     bool cc_op_dirty = s->cc_op_dirty;
     bool changed_cc_op = false;
@@ -4773,14 +4772,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             s->last_cc_op = s->cc_op;
             changed_cc_op = true;
         }
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // generate code to call callback
-            gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, hook->callback, env->uc, pc_start, hook->user_data);
-            // the callback might want to stop emulation immediately
-            check_exit_request(tcg_ctx);
-        }
+        gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, UC_HOOK_CODE_IDX, env->uc, pc_start);
+        // the callback might want to stop emulation immediately
+        check_exit_request(tcg_ctx);
     }
 
     prefixes = 0;
@@ -8173,7 +8167,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_helper_unlock(tcg_ctx, cpu_env);
 
     // Unicorn: patch the callback for the instruction size
-    if (hook) {
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, pc_start)) {
         // int i;
         // for(i = 0; i < 20; i++)
         //     printf("=== [%u] = %x\n", i, *(save_opparam_ptr + i));
@@ -8282,7 +8276,6 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
     int num_insns = 0;
     int max_insns;
     bool block_full = false;
-    struct hook *hook;
 
     /* generate intermediate code */
     pc_start = tb->pc;
@@ -8388,13 +8381,9 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (!env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/target-m68k/helper.h b/qemu/target-m68k/helper.h
index 865cf95d..caaadb3a 100644
--- a/qemu/target-m68k/helper.h
+++ b/qemu/target-m68k/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
+DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
 
 DEF_HELPER_1(bitrev, i32, i32)
 DEF_HELPER_1(ff1, i32, i32)
diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c
index 0f685d8e..bf45a66a 100644
--- a/qemu/target-m68k/translate.c
+++ b/qemu/target-m68k/translate.c
@@ -3031,7 +3031,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
 {
     TCGContext *tcg_ctx = s->uc->tcg_ctx;
     uint16_t insn;
-    struct hook *hook;
 
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
         tcg_gen_debug_insn_start(tcg_ctx, s->pc);
@@ -3044,10 +3043,8 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
     }
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, s->pc))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc)) {
+        gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, env->uc, s->pc);
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
     }
@@ -3075,7 +3072,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
     int max_insns;
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     bool block_full = false;
-    struct hook *hook;
 
     /* generate intermediate code */
     pc_start = tb->pc;
@@ -3110,14 +3106,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (!env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // save block address to see if we need to patch block size later
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        // save block address to see if we need to patch block size later
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h
index 81f733c2..1924bf6f 100644
--- a/qemu/target-mips/helper.h
+++ b/qemu/target-mips/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
+DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
 
 DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c
index fadbaeb0..8802c221 100644
--- a/qemu/target-mips/translate.c
+++ b/qemu/target-mips/translate.c
@@ -11331,7 +11331,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n
     int op, cnvt_op, op1, offset;
     int funct;
     int n_bytes;
-    struct hook *hook;
 
     op = (ctx->opcode >> 11) & 0x1f;
     sa = (ctx->opcode >> 2) & 0x7;
@@ -11344,10 +11343,8 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n
     n_bytes = 2;
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, ctx->pc))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
         *insn_need_patch = true;
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
@@ -13932,7 +13929,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
     uint32_t op;
-    struct hook *hook;
 
     /* make sure instructions are on a halfword boundary */
     if (ctx->pc & 0x1) {
@@ -13943,10 +13939,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
     }
 
     // Unicorn: trace this instruction on request
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, ctx->pc))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
         *insn_need_patch = true;
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
@@ -18505,11 +18499,8 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
 static void hook_insn(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_patch, int *insn_patch_offset, int offset_value)
 {
     TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
-    struct hook *hook;
-    HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) {
-        if (! HOOK_BOUND_CHECK(hook, ctx->pc))
-            continue;
-        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data);
+    if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) {
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc);
         *insn_need_patch = true;
         // the callback might want to stop emulation immediately
         check_exit_request(tcg_ctx);
@@ -19178,7 +19169,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     TCGArg *save_opparam_ptr = NULL;
     bool block_full = false;
-    struct hook *hook;
 
     if (search_pc)
         qemu_log("search pc %d\n", search_pc);
@@ -19224,14 +19214,10 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (! env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // save block address to see if we need to patch block size later
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        // save block address to see if we need to patch block size later
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/target-sparc/helper.h b/qemu/target-sparc/helper.h
index 2557dd08..503e1e5c 100644
--- a/qemu/target-sparc/helper.h
+++ b/qemu/target-sparc/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr)
+DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
 DEF_HELPER_1(power_down, void, env)
 
 #ifndef TARGET_SPARC64
diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c
index 8caba2b7..a7f067cf 100644
--- a/qemu/target-sparc/translate.c
+++ b/qemu/target-sparc/translate.c
@@ -2625,7 +2625,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
     TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
     TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
     target_long simm;
-    struct hook *hook;
 
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
         tcg_gen_debug_insn_start(tcg_ctx, dc->pc);
@@ -2638,14 +2637,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
     }
 
     // Unicorn: trace this instruction on request
-    if (hook_insn) {
-        HOOK_FOREACH(dc->uc, hook, UC_HOOK_CODE) {
-            if (! HOOK_BOUND_CHECK(hook, dc->pc))
-                continue;
-            gen_uc_tracecode(tcg_ctx, 4, hook->callback, dc->uc, dc->pc, hook->user_data);
-            // the callback might want to stop emulation immediately
-            check_exit_request(tcg_ctx);
-        }
+    if (hook_insn && HOOK_EXISTS_BOUNDED(dc->uc, UC_HOOK_CODE, dc->pc)) {
+        gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, dc->uc, dc->pc);
+        // the callback might want to stop emulation immediately
+        check_exit_request(tcg_ctx);
     }
 
     opc = GET_FIELD(insn, 0, 1);
@@ -5390,7 +5385,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
     unsigned int insn;
     TCGContext *tcg_ctx = env->uc->tcg_ctx;
     bool block_full = false;
-    struct hook *hook;
 
     memset(dc, 0, sizeof(DisasContext));
     dc->uc = env->uc;
@@ -5431,14 +5425,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
     // Unicorn: trace this block on request
     // Only hook this block if it is not broken from previous translation due to
     // full translation cache
-    if (!env->uc->block_full) {
-        HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) {
-            if (! HOOK_BOUND_CHECK(hook, pc_start))
-                continue;
-            // save block address to see if we need to patch block size later
-            env->uc->block_addr = pc_start;
-            gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data);
-        }
+    if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
+        // save block address to see if we need to patch block size later
+        env->uc->block_addr = pc_start;
+        gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
     }
 
     gen_tb_start(tcg_ctx);
diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h
index 9f096a3d..87358240 100644
--- a/qemu/tcg/tcg-op.h
+++ b/qemu/tcg/tcg-op.h
@@ -27,14 +27,13 @@
 
 int gen_new_label(TCGContext *);
 
-static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, void *callback, void *uc, uint64_t pc, void *data)
+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_ptr tcallback = tcg_const_ptr(tcg_ctx, callback);
+    TCGv_i32 ttype = tcg_const_i32(tcg_ctx, type);
     TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc);
     TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc);
-    TCGv_ptr tdata = tcg_const_ptr(tcg_ctx, data);
-    gen_helper_uc_tracecode(tcg_ctx, tsize, tcallback, tuc, tpc, tdata);
+    gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc);
 }
 
 static inline void tcg_gen_op0(TCGContext *s, TCGOpcode opc)
diff --git a/qemu/translate-all.c b/qemu/translate-all.c
index 72e1b60f..aec38c7c 100644
--- a/qemu/translate-all.c
+++ b/qemu/translate-all.c
@@ -179,7 +179,7 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s
     gen_intermediate_code(env, tb);
 
     // Unicorn: when tracing block, patch 1st operand for block size
-    if (HOOK_EXISTS(env->uc, UC_HOOK_BLOCK) && env->uc->block_addr == tb->pc) {
+    if (env->uc->block_addr == tb->pc && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) {
         if (env->uc->block_full)    // block size is unknown
             *(s->gen_opparam_buf + 1) = 0;
         else
diff --git a/uc.c b/uc.c
index f7f40853..b0f8a976 100644
--- a/uc.c
+++ b/uc.c
@@ -1009,17 +1009,23 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh)
 }
 
 // TCG helper
-void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data);
-void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data)
+void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address);
+void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address)
 {
     struct uc_struct *uc = handle;
+    struct list_item *cur = uc->hook[type].head;
+    struct hook *hook;
 
     // sync PC in CPUArchState with address
     if (uc->set_pc) {
         uc->set_pc(uc, address);
     }
 
-    ((uc_cb_hookcode_t)callback)(uc, address, size, user_data);
+    while (cur != NULL && !uc->stop_request) {
+        hook = (struct hook *)cur->data;
+        ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data);
+        cur = cur->next;
+    }
 }
 
 UNICORN_EXPORT