diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 5fe65e57b0..d55d5e7d5b 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -398,6 +398,37 @@ static void test_noexec(void) OK(uc_close(uc)); } +static void test_add_block_hook_syscall_cb(uc_engine *uc, void *userdata) +{ + OK(uc_emu_stop(uc)); +} + +static void test_add_block_hook_block_cb(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + uint64_t *block_counter = user_data; + *block_counter += 1; +} + +static void test_add_block_hook(void) +{ + uc_engine *uc; + uint64_t block_counter = 0; + uc_hook syscall_hook; + uc_hook block_hook; + /* nop + * syscall + */ + char code[] = "\x90\x0F\x05"; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); + OK(uc_hook_add(uc, &syscall_hook, UC_HOOK_INSN, &test_add_block_hook_syscall_cb, NULL, 1, 0, UC_X86_INS_SYSCALL)); + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + OK(uc_hook_add(uc, &block_hook, UC_HOOK_BLOCK, &test_add_block_hook_block_cb, &block_counter, code_start, code_start+0x1000)); + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + TEST_CHECK(block_counter == 1); + OK(uc_close(uc)); +} + TEST_LIST = { {"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, @@ -416,4 +447,5 @@ TEST_LIST = { {"test_uc_emu_stop_set_ip", test_uc_emu_stop_set_ip}, {"test_tlb_clear", test_tlb_clear}, {"test_noexec", test_noexec}, + {"test_add_block_hook", test_add_block_hook}, {NULL, NULL}}; diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 081cbad97f..233b16e347 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -582,7 +582,7 @@ static void test_virtual_write(void) OK(uc_vmem_write(uc, 0x1000, UC_PROT_EXEC, code, sizeof(code))); OK(uc_vmem_write(uc, 0x2000, UC_PROT_READ, &rax, sizeof(rax))); - OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 1)); + OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code), 0, 1)); OK(uc_reg_read(uc, UC_X86_REG_RAX, &res)); TEST_CHECK(rax == res); diff --git a/uc.c b/uc.c index 1de8a5b98f..b5c6d5bb58 100644 --- a/uc.c +++ b/uc.c @@ -1999,6 +1999,18 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, return UC_ERR_OK; } + if (type & UC_HOOK_CODE || type & UC_HOOK_BLOCK) { + if (end <= begin) { + uc->tb_flush(uc); + } else { + uc->uc_invalidate_tb(uc, begin, end-begin); + } + if (uc->nested_level) { + uc->quit_request = true; + break_translation_loop(uc); + } + } + while ((type >> i) > 0) { if ((type >> i) & 1) { // TODO: invalid hook error? @@ -2047,8 +2059,10 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) // and store the type mask in the hook pointer. for (i = 0; i < UC_HOOK_MAX; i++) { if (list_exists(&uc->hook[i], (void *)hook)) { - g_hash_table_foreach(hook->hooked_regions, hook_invalidate_region, - uc); + if (hook->type & UC_HOOK_CODE || hook->type & UC_HOOK_BLOCK) { + g_hash_table_foreach(hook->hooked_regions, + hook_invalidate_region, uc); + } g_hash_table_remove_all(hook->hooked_regions); hook->to_delete = true; uc->hooks_count[i]--;