Timeout error (#1173)

* Implement timeout state and new error for such case

* Adjust test_i386_loop sample

* Adjust test_i386_loop test
This commit is contained in:
ζeh Matt 2019-12-28 17:16:54 +01:00 committed by Nguyen Anh Quynh
parent 95890d593f
commit 3a3bc0c22d
5 changed files with 13 additions and 4 deletions

View File

@ -227,6 +227,7 @@ struct uc_struct {
bool stop_request; // request to immediately stop emulation - for uc_emu_stop()
bool quit_request; // request to quit the current TB, but continue to emulate - for uc_mem_protect()
bool emulation_done; // emulation is done by uc_emu_start()
bool timed_out; // emulation timed out, uc_emu_start() will result in EC_ERR_TIMEOUT
QemuThread timer; // timer for emulation timeout
uint64_t timeout; // timeout for uc_emu_start()

View File

@ -163,7 +163,8 @@ typedef enum uc_err {
UC_ERR_FETCH_UNALIGNED, // Unaligned fetch
UC_ERR_HOOK_EXIST, // hook for this event already existed
UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start()
UC_ERR_EXCEPTION // Unhandled CPU exception
UC_ERR_EXCEPTION, // Unhandled CPU exception
UC_ERR_TIMEOUT // Emulation timed out
} uc_err;

View File

@ -382,8 +382,8 @@ static void test_i386_loop(void)
// emulate machine code in 2 seconds, so we can quit even
// if the code loops
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
if (err != UC_ERR_TIMEOUT) {
printf("Failed on uc_emu_start() with error returned %u: %s, expected UC_ERR_TIMEOUT\n",
err, uc_strerror(err));
}

View File

@ -379,7 +379,7 @@ static void test_i386_loop(void **state)
// emulate machine code in 2 seconds, so we can quit even
// if the code loops
err = uc_emu_start(uc, address, address+sizeof(code), 2*UC_SECOND_SCALE, 0);
uc_assert_success(err);
uc_assert_err(err, UC_ERR_TIMEOUT);
// verify register values
uc_assert_success(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx));

7
uc.c
View File

@ -101,6 +101,8 @@ const char *uc_strerror(uc_err code)
return "Insufficient resource (UC_ERR_RESOURCE)";
case UC_ERR_EXCEPTION:
return "Unhandled CPU exception (UC_ERR_EXCEPTION)";
case UC_ERR_TIMEOUT:
return "Emulation timed out (UC_ERR_TIMEOUT)";
}
}
@ -504,6 +506,7 @@ static void *_timeout_fn(void *arg)
// timeout before emulation is done?
if (!uc->emulation_done) {
uc->timed_out = true;
// force emulation to stop
uc_emu_stop(uc);
}
@ -535,6 +538,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time
uc->invalid_error = UC_ERR_OK;
uc->block_full = false;
uc->emulation_done = false;
uc->timed_out = false;
switch(uc->arch) {
default:
@ -632,6 +636,9 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time
qemu_thread_join(&uc->timer);
}
if(uc->timed_out)
return UC_ERR_TIMEOUT;
return uc->invalid_error;
}