Timeout error (#1173)

* Implement timeout state and new error for such case

* Adjust test_i386_loop sample

* Adjust test_i386_loop test

Backports commit 3a3bc0c22de5453335dfb597a95dbda07c9f47a2 from unicorn
This commit is contained in:
ζeh Matt 2020-01-14 09:42:50 -05:00 committed by Lioncash
parent 2a47d652a6
commit c206e37963
5 changed files with 15 additions and 5 deletions

View file

@ -262,6 +262,7 @@ struct uc_struct {
bool stop_request; // request to immediately stop emulation - for uc_emu_stop() 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 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 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 QemuThread timer; // timer for emulation timeout
uint64_t timeout; // timeout for uc_emu_start() uint64_t timeout; // timeout for uc_emu_start()

View file

@ -170,7 +170,8 @@ typedef enum uc_err {
UC_ERR_FETCH_UNALIGNED, // Unaligned fetch UC_ERR_FETCH_UNALIGNED, // Unaligned fetch
UC_ERR_HOOK_EXIST, // hook for this event already existed UC_ERR_HOOK_EXIST, // hook for this event already existed
UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() 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; } uc_err;

View file

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

View file

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

8
uc.c
View file

@ -103,6 +103,8 @@ const char *uc_strerror(uc_err code)
return "Insufficient resource (UC_ERR_RESOURCE)"; return "Insufficient resource (UC_ERR_RESOURCE)";
case UC_ERR_EXCEPTION: case UC_ERR_EXCEPTION:
return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; return "Unhandled CPU exception (UC_ERR_EXCEPTION)";
case UC_ERR_TIMEOUT:
return "Emulation timed out (UC_ERR_TIMEOUT)";
} }
} }
@ -530,6 +532,7 @@ static void *_timeout_fn(void *arg)
// timeout before emulation is done? // timeout before emulation is done?
if (!uc->emulation_done) { if (!uc->emulation_done) {
uc->timed_out = true;
// force emulation to stop // force emulation to stop
uc_emu_stop(uc); uc_emu_stop(uc);
} }
@ -561,6 +564,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->invalid_error = UC_ERR_OK;
uc->block_full = false; uc->block_full = false;
uc->emulation_done = false; uc->emulation_done = false;
uc->timed_out = false;
switch(uc->arch) { switch(uc->arch) {
default: default:
@ -663,6 +667,10 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time
qemu_thread_join(&uc->timer); qemu_thread_join(&uc->timer);
} }
if (uc->timed_out) {
return UC_ERR_TIMEOUT;
}
return uc->invalid_error; return uc->invalid_error;
} }