2016-01-22 07:58:21 +03:00
|
|
|
#include "unicorn_test.h"
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
|
|
|
#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];
|
|
|
|
|
|
|
|
printf("block hook 1: %d == %zu\n", size, bb->size);
|
|
|
|
assert_int_equal(address, bb->addr);
|
|
|
|
assert_int_equal((size_t)size, bb->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_basic_blocks_hook2(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++];
|
|
|
|
|
|
|
|
printf("block hook 2: %d == %zu\n", size, bb->size);
|
|
|
|
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, trace2;
|
|
|
|
|
|
|
|
#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
|
2016-02-11 03:02:13 +03:00
|
|
|
OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, 1, 0));
|
|
|
|
OK(uc_hook_add(uc, &trace2, UC_HOOK_BLOCK, test_basic_blocks_hook2, &bbtest, 1, 0));
|
2016-01-22 07:58:21 +03:00
|
|
|
|
|
|
|
OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
const struct CMUnitTest tests[] = {
|
|
|
|
cmocka_unit_test_setup_teardown(test_basic_blocks, setup32, teardown),
|
|
|
|
};
|
|
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
|
|
}
|