mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-24 06:28:12 +00:00
Merge branch 'master' of https://github.com/NUko32/unicorn into NUko32-master
This commit is contained in:
commit
fdcdaa3639
2 changed files with 104 additions and 1 deletions
|
@ -13,7 +13,7 @@ endif
|
|||
|
||||
ALL_TESTS = test_sanity test_x86 test_mem_map test_mem_high test_mem_map_ptr \
|
||||
test_tb_x86 test_multihook test_pc_change test_x86_soft_paging \
|
||||
test_hookcounts
|
||||
test_hookcounts test_hang
|
||||
|
||||
.PHONY: all
|
||||
all: ${ALL_TESTS}
|
||||
|
@ -35,6 +35,7 @@ test: ${ALL_TESTS}
|
|||
./test_pc_change
|
||||
./test_x86_soft_paging
|
||||
./test_hookcounts
|
||||
./test_hang
|
||||
|
||||
test_sanity: test_sanity.c
|
||||
test_x86: test_x86.c
|
||||
|
@ -46,6 +47,7 @@ test_multihook: test_multihook.c
|
|||
test_pc_change: test_pc_change.c
|
||||
test_x86_soft_paging: test_x86_soft_paging.c
|
||||
test_hookcounts: test_hookcounts.c
|
||||
test_hang: test_hang.c
|
||||
|
||||
${ALL_TESTS}:
|
||||
${CC} ${CFLAGS} -o $@ $^
|
||||
|
|
101
tests/unit/test_hang.c
Normal file
101
tests/unit/test_hang.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
refer to issue #575.
|
||||
to run correctly unicorn needs to be compiled for AArch64.
|
||||
*/
|
||||
|
||||
#include "unicorn_test.h"
|
||||
#include <stdio.h>
|
||||
|
||||
uint64_t trunc_page(uint64_t addr)
|
||||
{
|
||||
return (addr & ~(4095));
|
||||
}
|
||||
|
||||
/* Called before every test to set up a new instance */
|
||||
static int init(void **state)
|
||||
{
|
||||
printf("[+] Initializing Unicorn...\n");
|
||||
uc_engine *uc;
|
||||
|
||||
if (uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc) != UC_ERR_OK) {
|
||||
printf("Error on open. Be sure that your unicorn library supports AArch64.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*state = uc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called after every test to clean up */
|
||||
static int teardown(void **state)
|
||||
{
|
||||
printf("[+] Exiting...\n");
|
||||
uc_engine *uc = *state;
|
||||
|
||||
uc_close(uc);
|
||||
|
||||
*state = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_hang(void **state)
|
||||
{
|
||||
uint32_t code[] = {
|
||||
0xd503201f, /* NOP */
|
||||
0xd503201f, /* NOP */
|
||||
0xd503201f, /* NOP */
|
||||
0xaa0103e0 /* MOV X0, X1 */
|
||||
};
|
||||
|
||||
uc_engine *uc = *state;
|
||||
|
||||
uint64_t x0 = 0;
|
||||
uint64_t x1 = 1;
|
||||
|
||||
/*
|
||||
* emulation will hang if some instruction hits every quarter of a page,
|
||||
* i.e. these offsets:
|
||||
* 0x1400, 0x1800, 0x1c00, 0x2000
|
||||
*
|
||||
* in this test, the code to be emulated is mapped just before the 0x1400
|
||||
* offset, so that the final instruction emulated (MOV X0, X1) hits the offset,
|
||||
* causing the hang.
|
||||
* If you try to write the code just four bytes behind, the hang doesn't occur.
|
||||
*
|
||||
* So far, this strange behaviour has only been observed with AArch64 Unicorn APIs.
|
||||
*/
|
||||
|
||||
uint64_t addr = 0x13f0; // try to map at (0x13f0 - 0x4) and the hang doesn't occur
|
||||
uint64_t trunc_addr = trunc_page(addr); // round down to nearest page
|
||||
|
||||
uc_mem_map(uc, trunc_addr, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
if (uc_mem_write(uc, addr, &code, sizeof(code))) {
|
||||
printf("error on write\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uc_reg_write(uc, UC_ARM64_REG_X0, &x0);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X1, &x1);
|
||||
|
||||
if (uc_emu_start(uc, addr, addr + sizeof(code), 0, 0)) {
|
||||
printf("error on start\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uc_reg_read(uc, UC_ARM64_REG_X0, &x0);
|
||||
uc_reg_read(uc, UC_ARM64_REG_X1, &x1);
|
||||
|
||||
printf("x0: %#llx\n", x0);
|
||||
printf("x1: %#llx\n", x1);
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(test_hang, init, teardown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);;
|
||||
}
|
Loading…
Reference in a new issue