diff --git a/test/unit/test_x86.c b/test/unit/test_x86.c index 1a31e432..634201dc 100644 --- a/test/unit/test_x86.c +++ b/test/unit/test_x86.c @@ -1,6 +1,97 @@ #include "unicorn_test.h" #include +#define OK(x) uc_assert_success(x) + +/* Called before every test to set up a new instance */ +static int setup32(void **state) +{ + uc_engine *uc; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + + *state = uc; + return 0; +} + +/* Called after every test to clean up */ +static int teardown(void **state) +{ + uc_engine *uc = *state; + + OK(uc_close(uc)); + + *state = NULL; + return 0; +} + +/******************************************************************************/ + +struct bb { + uint64_t addr; + size_t size; +}; + +struct bbtest { + const struct bb *blocks; + unsigned int blocknum; +}; + + +static void test_basic_blocks_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + struct bbtest *bbtest = user_data; + const struct bb *bb = &bbtest->blocks[bbtest->blocknum++]; + + assert_int_equal(address, bb->addr); + assert_int_equal((size_t)size, bb->size); +} + +static void test_basic_blocks(void **state) +{ + uc_engine *uc = *state; + uc_hook trace1; + +#define BASEADDR 0x1000000 + + uint64_t address = BASEADDR; + const uint8_t code[] = { + 0x33, 0xC0, // xor eax, eax + 0x90, // nop + 0x90, // nop + 0xEB, 0x00, // jmp $+2 + 0x90, // nop + 0x90, // nop + 0x90, // nop + }; + + static const struct bb blocks[] = { + {BASEADDR, 6}, + {BASEADDR+ 6, 3}, + }; + + struct bbtest bbtest = { + .blocks = blocks, + .blocknum = 0, + }; + + +#undef BASEADDR + + // map 2MB memory for this emulation + OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL)); + + // write machine code to be emulated to memory + OK(uc_mem_write(uc, address, code, sizeof(code))); + + // trace all basic blocks + OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, (uint64_t)1, (uint64_t)0)); + + OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); +} + +/******************************************************************************/ + // callback for tracing basic blocks static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { @@ -654,6 +745,8 @@ int main(void) { cmocka_unit_test(test_x86_64_syscall), cmocka_unit_test(test_x86_16), + + cmocka_unit_test_setup_teardown(test_basic_blocks, setup32, teardown), }; return cmocka_run_group_tests(tests, NULL, NULL); }