diff --git a/src/emulator/emulator.hpp b/src/emulator/emulator.hpp index 72f554d..2c54cd4 100644 --- a/src/emulator/emulator.hpp +++ b/src/emulator/emulator.hpp @@ -130,6 +130,8 @@ class emulator : public memory_manager this->perform_deserialization(deserializer, true); } + virtual bool has_violation() const = 0; + private: std::vector last_snapshot_data_{}; diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index 61378a2..769c75a 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -241,7 +241,7 @@ namespace unicorn uc_close(this->uc_); } - void start(uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, + void start(const uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, const size_t count) override { if (timeout.count() < 0) @@ -249,31 +249,26 @@ namespace unicorn timeout = {}; } - // TODO: Fix adjusting timeout and count - while (true) + this->has_violation_ = false; + const auto timeoutYs = std::chrono::duration_cast(timeout); + const auto res = uc_emu_start(*this, start, end, static_cast(timeoutYs.count()), + count); + if (res == UC_ERR_OK) { - this->retry_after_violation_ = false; - const auto timeoutYs = std::chrono::duration_cast(timeout); - const auto res = uc_emu_start(*this, start, end, static_cast(timeoutYs.count()), - count); - if (res == UC_ERR_OK) - { - return; - } - - const auto is_violation = res == UC_ERR_READ_UNMAPPED || // - res == UC_ERR_WRITE_UNMAPPED || // - res == UC_ERR_FETCH_UNMAPPED || // - res == UC_ERR_READ_PROT || // - res == UC_ERR_WRITE_PROT || // - res == UC_ERR_FETCH_PROT; + return; + } - if (!is_violation || !this->retry_after_violation_) - { - uce(res); - } + const auto is_violation = // + res == UC_ERR_READ_UNMAPPED || // + res == UC_ERR_WRITE_UNMAPPED || // + res == UC_ERR_FETCH_UNMAPPED || // + res == UC_ERR_READ_PROT || // + res == UC_ERR_WRITE_PROT || // + res == UC_ERR_FETCH_PROT; - start = this->read_instruction_pointer(); + if (!is_violation || !this->has_violation_) + { + uce(res); } } @@ -493,7 +488,7 @@ namespace unicorn return false; } - this->retry_after_violation_ = resume && has_ip_changed; + this->has_violation_ = resume && has_ip_changed; if (has_ip_changed) { @@ -609,10 +604,15 @@ namespace unicorn serializer.deserialize(buffer); } + bool has_violation() const override + { + return this->has_violation_; + } + private: mutable bool has_snapshots_{false}; uc_engine* uc_{}; - bool retry_after_violation_{false}; + bool has_violation_{false}; std::vector> hooks_{}; }; } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 8e4c0eb..3c83c06 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -964,7 +964,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count) this->emu().start_from_ip(timeout, count); - if (!this->switch_thread) + if (!this->switch_thread && !this->emu().has_violation()) { break; }