difference between stop_request and quit_request
quit_request is for internal use. This means the IP register was updated and qemu needs to rebuild the translation blocks. stop_request is set by the user (uc_emu_stop) to indecate that unicorn sould stop emulating.
This commit is contained in:
parent
ca7e0e7f42
commit
b7b1a4d6b4
@ -486,6 +486,28 @@ static inline void hooked_regions_check(uc_engine *uc, uint64_t start,
|
||||
length);
|
||||
}
|
||||
|
||||
/*
|
||||
break translation loop:
|
||||
This is done in two cases:
|
||||
1. the user wants to stop the emulation.
|
||||
2. the user has set it IP. This requires to restart the internal
|
||||
CPU emulation and rebuild some translation blocks
|
||||
*/
|
||||
static inline uc_err break_translation_loop(uc_engine *uc)
|
||||
{
|
||||
if (uc->emulation_done) {
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
// TODO: make this atomic somehow?
|
||||
if (uc->cpu) {
|
||||
// exit the current TB
|
||||
cpu_exit(uc->cpu);
|
||||
}
|
||||
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
#ifdef UNICORN_TRACER
|
||||
#define UC_TRACE_START(loc) trace_start(get_tracer(), loc)
|
||||
#define UC_TRACE_END(loc, fmt, ...) \
|
||||
|
@ -96,7 +96,7 @@ static int tcg_cpu_exec(struct uc_struct *uc)
|
||||
r = cpu_exec(uc, cpu);
|
||||
|
||||
// quit current TB but continue emulating?
|
||||
if (uc->quit_request) {
|
||||
if (uc->quit_request && !uc->stop_request) {
|
||||
// reset stop_request
|
||||
uc->stop_request = false;
|
||||
|
||||
|
@ -372,7 +372,7 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_ARM64_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,7 +515,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_ARM_REG_R15) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1521,7 +1521,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
case UC_X86_REG_IP:
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1535,7 +1535,7 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
case UC_X86_REG_IP:
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -117,7 +117,7 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_M68K_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_MIPS_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,7 +361,7 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_PPC_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,7 +560,7 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals,
|
||||
if (regid == UC_RISCV_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ static int s390_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
if (regid == UC_S390X_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,7 @@ int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
if (regid == UC_TRICORE_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
break_translation_loop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,41 @@ static void test_uc_hook_cached_uaf(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_uc_emu_stop_set_ip_callback(uc_engine *uc, uint64_t address, uint32_t size, void *userdata)
|
||||
{
|
||||
uint64_t rip = code_start + 0xb;
|
||||
|
||||
if (address == code_start + 0x7) {
|
||||
printf("stoping\n");
|
||||
uc_emu_stop(uc);
|
||||
uc_reg_write(uc, UC_X86_REG_RIP, &rip);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_uc_emu_stop_set_ip(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_hook h;
|
||||
uint64_t rip;
|
||||
|
||||
char code[] = "\x48\x31\xc0" // 0x0 xor rax, rax : rax = 0
|
||||
"\x90" // 0x3 nop :
|
||||
"\x48\xff\xc0" // 0x4 inc rax : rax++
|
||||
"\x90" // 0x7 nop : <-- going to stop here
|
||||
"\x48\xff\xc0" // 0x8 inc rax : rax++
|
||||
"\x90" // 0xb nop :
|
||||
"\x0f\x0b" // 0xc ud2 : <-- will raise UC_ERR_INSN_INVALID, but should not never be reached
|
||||
"\x90" // 0xe nop :
|
||||
"\x90"; // 0xf nop :
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1);
|
||||
OK(uc_hook_add(uc, &h, UC_HOOK_CODE, test_uc_emu_stop_set_ip_callback, NULL, 1, 0));
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RIP, &rip));
|
||||
TEST_CHECK(rip == code_start + 0xb);
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_page_size", test_uc_ctl_page_size},
|
||||
{"test_uc_ctl_arch", test_uc_ctl_arch},
|
||||
@ -315,4 +350,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu},
|
||||
#endif
|
||||
{"test_uc_hook_cached_uaf", test_uc_hook_cached_uaf},
|
||||
{"test_uc_emu_stop_set_ip", test_uc_emu_stop_set_ip},
|
||||
{NULL, NULL}};
|
||||
|
13
uc.c
13
uc.c
@ -907,19 +907,8 @@ UNICORN_EXPORT
|
||||
uc_err uc_emu_stop(uc_engine *uc)
|
||||
{
|
||||
UC_INIT(uc);
|
||||
|
||||
if (uc->emulation_done) {
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
uc->stop_request = true;
|
||||
// TODO: make this atomic somehow?
|
||||
if (uc->cpu) {
|
||||
// exit the current TB
|
||||
cpu_exit(uc->cpu);
|
||||
}
|
||||
|
||||
return UC_ERR_OK;
|
||||
return break_translation_loop(uc);
|
||||
}
|
||||
|
||||
// return target index where a memory region at the address exists, or could be
|
||||
|
Loading…
Reference in New Issue
Block a user