diff --git a/src/emulator/cpu_interface.hpp b/src/emulator/cpu_interface.hpp index 83dce7e8..155682aa 100644 --- a/src/emulator/cpu_interface.hpp +++ b/src/emulator/cpu_interface.hpp @@ -9,13 +9,13 @@ struct cpu_interface { virtual ~cpu_interface() = default; - virtual void start(uint64_t start, uint64_t end = 0, std::chrono::nanoseconds timeout = {}, size_t count = 0) = 0; + virtual void start(size_t count = 0) = 0; virtual void stop() = 0; virtual size_t read_raw_register(int reg, void* value, size_t size) = 0; virtual size_t write_raw_register(int reg, const void* value, size_t size) = 0; - virtual std::vector save_registers() = 0; + virtual std::vector save_registers() const = 0; virtual void restore_registers(const std::vector& register_data) = 0; // TODO: Remove this diff --git a/src/emulator/typed_emulator.hpp b/src/emulator/typed_emulator.hpp index 63516cba..1a67b038 100644 --- a/src/emulator/typed_emulator.hpp +++ b/src/emulator/typed_emulator.hpp @@ -15,11 +15,6 @@ class typed_emulator : public emulator static constexpr registers stack_pointer = StackPointer; static constexpr registers instruction_pointer = InstructionPointer; - void start_from_ip(const std::chrono::nanoseconds timeout = {}, const size_t count = 0) - { - this->start(this->read_instruction_pointer(), 0, timeout, count); - } - size_t write_register(registers reg, const void* value, const size_t size) { return this->write_raw_register(static_cast(reg), value, size); diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 53b45139..31b62ce6 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -7,11 +7,14 @@ using icicle_emulator = struct icicle_emulator_; extern "C" { + using raw_func = void(void*); + using ptr_func = void(void*, uint64_t); + using violation_func = int32_t(void*, uint64_t address, uint8_t operation, int32_t unmapped); + using data_accessor_func = void(void* user, const void* data, size_t length); + using icicle_mmio_read_func = void(void* user, uint64_t address, size_t length, void* data); using icicle_mmio_write_func = void(void* user, uint64_t address, size_t length, const void* data); - using data_accessor_func = void(void* user, const void* data, size_t length); - icicle_emulator* icicle_create_emulator(); int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); @@ -22,11 +25,14 @@ extern "C" int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length); - uint32_t icicle_add_syscall_hook(icicle_emulator*, void (*callback)(void*), void* data); + uint32_t icicle_add_syscall_hook(icicle_emulator*, raw_func* callback, void* data); + uint32_t icicle_add_execution_hook(icicle_emulator*, ptr_func* callback, void* data); + uint32_t icicle_add_violation_hook(icicle_emulator*, violation_func* callback, void* data); void icicle_remove_syscall_hook(icicle_emulator*, uint32_t id); size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length); size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length); - void icicle_start(icicle_emulator*); + void icicle_start(icicle_emulator*, size_t count); + void icicle_stop(icicle_emulator*); void icicle_destroy_emulator(icicle_emulator*); } @@ -41,6 +47,51 @@ namespace icicle throw std::runtime_error(std::string(error)); } } + + emulator_hook* wrap_hook(const uint32_t id) + { + return reinterpret_cast(static_cast(id)); + } + + template + struct function_object : utils::object + { + std::function func{}; + + function_object(std::function f = {}) + : func(std::move(f)) + { + } + + template + auto operator()(Args&&... args) const + { + return this->func.operator()(std::forward(args)...); + } + + ~function_object() override = default; + }; + + template + std::unique_ptr> make_function_object(std::function func) + { + return std::make_unique>(std::move(func)); + } + + template + std::unique_ptr wrap_shared(std::shared_ptr shared_ptr) + { + struct shard_wrapper : utils::object + { + std::shared_ptr ptr{}; + ~shard_wrapper() override = default; + }; + + auto wrapper = std::make_unique(); + wrapper->ptr = std::move(shared_ptr); + + return wrapper; + } } class icicle_x64_emulator : public x64_emulator @@ -64,22 +115,14 @@ namespace icicle } } - void start(const uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, - const size_t count) override + void start(const size_t count) override { - if (timeout.count() < 0) - { - timeout = {}; - } - - (void)start; - (void)end; - (void)count; - icicle_start(this->emu_); + icicle_start(this->emu_, count); } void stop() override { + icicle_stop(this->emu_); } void load_gdt(const pointer_type address, const uint32_t limit) override @@ -142,28 +185,30 @@ namespace icicle auto* ptr = wrapper.get(); this->storage_.push_back(std::move(wrapper)); - auto* read_wrapper = +[](void* user, const uint64_t address, const size_t length, void* data) { + auto* read_wrapper = +[](void* user, const uint64_t addr, const size_t length, void* data) { constexpr auto limit = sizeof(uint64_t); const auto* w = static_cast(user); + // TODO: Change interface to get rid of loop for (size_t offset = 0; offset < length; offset += limit) { const auto max_read = std::min(limit, length - offset); - const auto value = w->read_cb(address + offset - w->base, max_read); + const auto value = w->read_cb(addr + offset - w->base, max_read); memcpy(static_cast(data) + offset, &value, max_read); } }; - auto* write_wrapper = +[](void* user, const uint64_t address, const size_t length, const void* data) { + auto* write_wrapper = +[](void* user, const uint64_t addr, const size_t length, const void* data) { constexpr auto limit = sizeof(uint64_t); const auto* w = static_cast(user); + // TODO: Change interface to get rid of loop for (size_t offset = 0; offset < length; offset += limit) { uint64_t value{}; const auto max_read = std::min(limit, length - offset); memcpy(&value, static_cast(data) + offset, max_read); - w->write_cb(address + offset - w->base, max_read, value); + w->write_cb(addr + offset - w->base, max_read, value); } }; @@ -209,50 +254,69 @@ namespace icicle { if (static_cast(instruction_type) != x64_hookable_instructions::syscall) { + // TODO return nullptr; } - auto callback_store = std::make_unique>([c = std::move(callback)] { - (void)c(); // - }); + auto obj = make_function_object(std::move(callback)); + auto* ptr = obj.get(); const auto invoker = +[](void* cb) { - (*static_cast*>(cb))(); // + const auto& func = *static_cast(cb); + (void)func(); // }; - const auto id = icicle_add_syscall_hook(this->emu_, invoker, callback_store.get()); - this->syscall_hooks_[id] = std::move(callback_store); + const auto id = icicle_add_syscall_hook(this->emu_, invoker, ptr); + this->hooks_[id] = std::move(obj); - return reinterpret_cast(static_cast(id)); + return wrap_hook(id); } emulator_hook* hook_basic_block(basic_block_hook_callback callback) override { + // TODO (void)callback; throw std::runtime_error("Not implemented"); } emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override { + // TODO (void)callback; throw std::runtime_error("Not implemented"); } emulator_hook* hook_interrupt(interrupt_hook_callback callback) override { + // TODO (void)callback; return nullptr; // throw std::runtime_error("Not implemented"); } - emulator_hook* hook_memory_violation(uint64_t address, size_t size, + emulator_hook* hook_memory_violation(const uint64_t address, const size_t size, memory_violation_hook_callback callback) override { (void)address; (void)size; - (void)callback; - return nullptr; - // throw std::runtime_error("Not implemented"); + + auto obj = make_function_object(std::move(callback)); + auto* ptr = obj.get(); + auto* wrapper = + +[](void* user, const uint64_t address, const uint8_t operation, const int32_t unmapped) -> int32_t { + const auto violation_type = unmapped // + ? memory_violation_type::unmapped + : memory_violation_type::protection; + + const auto& func = *static_cast(user); + const auto res = func(address, 1, static_cast(operation), violation_type); + return res == memory_violation_continuation::resume ? 1 : 0; + }; + + const auto id = icicle_add_violation_hook(this->emu_, wrapper, ptr); + this->hooks_[id] = std::move(obj); + + return wrap_hook(id); } emulator_hook* hook_memory_access(const uint64_t address, const size_t size, const memory_operation filter, @@ -263,41 +327,65 @@ namespace icicle return nullptr; } - (void)address; - (void)size; - (void)callback; + const auto shared_callback = std::make_shared(std::move(callback)); + + if ((filter & memory_permission::exec) == memory_permission::exec) + { + if (address != 0 || size != std::numeric_limits::max()) + { + throw std::runtime_error("Not supported!"); + } + + auto* ptr = shared_callback.get(); + auto wrapper = wrap_shared(shared_callback); + auto* func = +[](void* user, const uint64_t ptr) { + (*static_cast(user))(ptr, 0, 0, memory_permission::exec); + }; + + const auto id = icicle_add_execution_hook(this->emu_, func, ptr); + this->hooks_[id] = std::move(wrapper); + + return wrap_hook(id); + } + return nullptr; - // throw std::runtime_error("Not implemented"); } void delete_hook(emulator_hook* hook) override { const auto id = static_cast(reinterpret_cast(hook)); - const auto entry = this->syscall_hooks_.find(id); - if (entry == this->syscall_hooks_.end()) + const auto entry = this->hooks_.find(id); + if (entry == this->hooks_.end()) { return; } icicle_remove_syscall_hook(this->emu_, id); - this->syscall_hooks_.erase(entry); + this->hooks_.erase(entry); } void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override { - (void)buffer; - (void)is_snapshot; - throw std::runtime_error("Not implemented"); + if (is_snapshot) + { + throw std::runtime_error("Not implemented"); + } + + buffer.write_vector(this->save_registers()); } void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override { - (void)buffer; - (void)is_snapshot; - throw std::runtime_error("Not implemented"); + if (is_snapshot) + { + throw std::runtime_error("Not implemented"); + } + + const auto data = buffer.read_vector(); + this->restore_registers(data); } - std::vector save_registers() override + std::vector save_registers() const override { std::vector data{}; auto* accessor = +[](void* user, const void* data, const size_t length) { @@ -323,8 +411,7 @@ namespace icicle private: std::list> storage_{}; - using syscall_hook_storage = std::unique_ptr>; - std::unordered_map syscall_hooks_{}; + std::unordered_map> hooks_{}; icicle_emulator* emu_{}; }; diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 85ec2f64..292c4fd3 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -1,5 +1,6 @@ use icicle_cpu::ValueSource; -use std::collections::HashMap; +use icicle_cpu::ExceptionCode; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; use crate::registers; @@ -16,11 +17,11 @@ fn create_x64_vm() -> icicle_vm::Vm { return icicle_vm::build(&cpu_config).unwrap(); } -fn map_permissions(foreign_permissions: u8) -> u8 { - const FOREIGN_READ: u8 = 1 << 0; - const FOREIGN_WRITE: u8 = 1 << 1; - const FOREIGN_EXEC: u8 = 1 << 2; +const FOREIGN_READ: u8 = 1 << 0; +const FOREIGN_WRITE: u8 = 1 << 1; +const FOREIGN_EXEC: u8 = 1 << 2; +fn map_permissions(foreign_permissions: u8) -> u8 { let mut permissions: u8 = 0; if (foreign_permissions & FOREIGN_READ) != 0 { @@ -46,6 +47,7 @@ enum HookType { Read, Write, Execute, + Violation, Unknown, } @@ -96,10 +98,45 @@ impl HookContainer { } } +struct InstructionHookInjector { + hook: pcode::HookId, +} + +impl icicle_vm::CodeInjector for InstructionHookInjector { + fn inject( + &mut self, + _cpu: &mut icicle_vm::cpu::Cpu, + group: &icicle_vm::cpu::BlockGroup, + code: &mut icicle_vm::BlockTable, + ) { + for id in group.range() { + let block = &mut code.blocks[id]; + + let mut tmp_block = pcode::Block::new(); + tmp_block.next_tmp = block.pcode.next_tmp; + + for stmt in block.pcode.instructions.drain(..) { + tmp_block.push(stmt); + if let pcode::Op::InstructionMarker = stmt.op { + tmp_block.push(pcode::Op::Hook(self.hook)); + code.modified.insert(id); + } + } + + std::mem::swap( + &mut tmp_block.instructions, + &mut block.pcode.instructions, + ); + } + } +} + pub struct IcicleEmulator { vm: icicle_vm::Vm, reg: registers::X64RegisterNodes, syscall_hooks: HookContainer, + violation_hooks: HookContainer bool>, + execution_hooks: Rc>>, } pub struct MmioHandler { @@ -133,11 +170,26 @@ impl icicle_cpu::mem::IoMemory for MmioHandler { impl IcicleEmulator { pub fn new() -> Self { - let virtual_machine = create_x64_vm(); + let mut virtual_machine = create_x64_vm(); + let exec_hooks: Rc>> = Rc::new(RefCell::new(HookContainer::new())); + + let exec_hooks_clone = Rc::clone(&exec_hooks); + + let hook = icicle_cpu::InstHook::new(move |_: &mut icicle_cpu::Cpu, addr: u64| { + for (_key, func) in exec_hooks_clone.borrow().get_hooks() { + func(addr); + } + }); + + let hook = virtual_machine.cpu.add_hook(hook); + virtual_machine.add_injector(InstructionHookInjector { hook }); + Self { reg: registers::X64RegisterNodes::new(&virtual_machine.cpu.arch), vm: virtual_machine, syscall_hooks: HookContainer::new(), + violation_hooks: HookContainer::new(), + execution_hooks: exec_hooks, } } @@ -145,29 +197,80 @@ impl IcicleEmulator { return &mut self.vm.cpu.mem; } - pub fn start(&mut self) { + pub fn start(&mut self, count: u64) { + self.vm.icount_limit = match count { + 0 => u64::MAX, + _ => self.vm.cpu.icount + count, + }; + loop { let reason = self.vm.run(); - let invoke_syscall = match reason { - icicle_vm::VmExit::UnhandledException((code, _)) => { - code == icicle_cpu::ExceptionCode::Syscall - } - _ => false, + match reason { + icicle_vm::VmExit::InstructionLimit => break, + icicle_vm::VmExit::UnhandledException((code, value)) => { + let continue_execution = self.handle_exception(code, value); + if !continue_execution { + break + } + }, + _ => break, }; - - if !invoke_syscall { - break; - } - - for (_key, func) in self.syscall_hooks.get_hooks() { - func(); - } - - self.vm.cpu.write_pc(self.vm.cpu.read_pc() + 2); } } + fn handle_exception(&mut self, code: ExceptionCode, value: u64) -> bool { + let continue_execution = match code { + ExceptionCode::Syscall => self.handle_syscall(), + ExceptionCode::ReadPerm => self.handle_violation(value, FOREIGN_READ, false), + ExceptionCode::WritePerm => self.handle_violation(value, FOREIGN_WRITE, false), + ExceptionCode::ReadUnmapped => self.handle_violation(value, FOREIGN_READ, true), + ExceptionCode::WriteUnmapped => self.handle_violation(value, FOREIGN_WRITE, true), + ExceptionCode::ExecViolation => self.handle_violation(value, FOREIGN_EXEC, true), + _ => false + }; + + return continue_execution; + } + + fn handle_violation(&mut self, address: u64, permission: u8, unmapped: bool) -> bool { + let hooks = &self.violation_hooks.get_hooks(); + if hooks.is_empty() { + return false; + } + + let mut continue_execution = true; + + for (_key, func) in self.violation_hooks.get_hooks() { + continue_execution &= func(address, permission, unmapped ); + } + + return continue_execution; + } + + fn handle_syscall(&mut self) -> bool{ + for (_key, func) in self.syscall_hooks.get_hooks() { + func(); + } + + self.vm.cpu.write_pc(self.vm.cpu.read_pc() + 2); + return true; + } + + pub fn stop(&mut self) { + self.vm.icount_limit = 0; + } + + pub fn add_violation_hook(&mut self, callback: Box bool>) -> u32 { + let hook_id = self.violation_hooks.add_hook(callback); + return qualify_hook_id(hook_id, HookType::Violation); + } + + pub fn add_execution_hook(&mut self, callback: Box) -> u32 { + let hook_id = self.execution_hooks.borrow_mut().add_hook(callback); + return qualify_hook_id(hook_id, HookType::Execute); + } + pub fn add_syscall_hook(&mut self, callback: Box) -> u32 { let hook_id = self.syscall_hooks.add_hook(callback); return qualify_hook_id(hook_id, HookType::Syscall); @@ -178,6 +281,8 @@ impl IcicleEmulator { match hook_type { HookType::Syscall => self.syscall_hooks.remove_hook(hook_id), + HookType::Violation => self.violation_hooks.remove_hook(hook_id), + HookType::Execute => self.execution_hooks.borrow_mut().remove_hook(hook_id), _ => {} } } diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index d12b64d5..0e6eab75 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -20,17 +20,27 @@ pub fn icicle_create_emulator() -> *mut c_void { } #[unsafe(no_mangle)] -pub fn icicle_start(ptr: *mut c_void) { +pub fn icicle_start(ptr: *mut c_void, count: usize) { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - emulator.start(); + emulator.start(count as u64); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_stop(ptr: *mut c_void) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + emulator.stop(); } } type RawFunction = extern "C" fn(*mut c_void); +type PtrFunction = extern "C" fn(*mut c_void, u64); type DataFunction = extern "C" fn(*mut c_void, *const c_void, usize); type MmioReadFunction = extern "C" fn(*mut c_void, u64, usize, *mut c_void); type MmioWriteFunction = extern "C" fn(*mut c_void, u64, usize, *const c_void); +type ViolationFunction = extern "C" fn(*mut c_void, u64, u8, i32) -> i32; #[unsafe(no_mangle)] pub fn icicle_map_mmio( @@ -107,7 +117,11 @@ pub fn icicle_save_registers(ptr: *mut c_void, accessor: DataFunction, accessor_ unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let registers = emulator.save_registers(); - accessor(accessor_data, registers.as_ptr() as *const c_void, registers.len()); + accessor( + accessor_data, + registers.as_ptr() as *const c_void, + registers.len(), + ); } } @@ -131,10 +145,35 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz } #[unsafe(no_mangle)] -pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: RawFunction, data: *mut c_void) { +pub fn icicle_add_violation_hook(ptr: *mut c_void, callback: ViolationFunction, data: *mut c_void) -> u32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - emulator.add_syscall_hook(Box::new(move || callback(data))); + return emulator.add_violation_hook(Box::new( + move |address: u64, permission: u8, unmapped: bool| { + let result = callback(data, address, permission, to_cbool(unmapped)); + if result == 0 { + return false; + } + + return true; + }, + )); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: RawFunction, data: *mut c_void) -> u32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + return emulator.add_syscall_hook(Box::new(move || callback(data))); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_add_execution_hook(ptr: *mut c_void, callback: PtrFunction, data: *mut c_void) -> u32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + return emulator.add_execution_hook(Box::new(move |ptr: u64| callback(data, ptr))); } } diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index 029ad15e..f26dddda 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -269,17 +269,12 @@ namespace unicorn uc_close(this->uc_); } - void start(const uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, - const size_t count) override + void start(const size_t count) override { - if (timeout.count() < 0) - { - timeout = {}; - } - 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); + const auto start = this->read_instruction_pointer(); + constexpr auto end = std::numeric_limits::max(); + const auto res = uc_emu_start(*this, start, end, 0, count); if (res == UC_ERR_OK) { return; @@ -647,7 +642,7 @@ namespace unicorn serializer.deserialize(buffer); } - std::vector save_registers() override + std::vector save_registers() const override { utils::buffer_serializer buffer{}; const uc_context_serializer serializer(this->uc_, false); diff --git a/src/windows-emulator-test/emulation_test.cpp b/src/windows-emulator-test/emulation_test.cpp index f5833843..dc600f92 100644 --- a/src/windows-emulator-test/emulation_test.cpp +++ b/src/windows-emulator-test/emulation_test.cpp @@ -15,7 +15,7 @@ namespace test constexpr auto count = 200000; auto emu = create_sample_emulator(); - emu.start({}, count); + emu.start(count); ASSERT_EQ(emu.get_executed_instructions(), count); } @@ -34,12 +34,12 @@ namespace test constexpr auto offset = 1; const auto instructionsToExecute = executedInstructions - offset; - new_emu.start({}, instructionsToExecute); + new_emu.start(instructionsToExecute); ASSERT_EQ(new_emu.get_executed_instructions(), instructionsToExecute); ASSERT_NOT_TERMINATED(new_emu); - new_emu.start({}, offset); + new_emu.start(offset); ASSERT_TERMINATED_SUCCESSFULLY(new_emu); ASSERT_EQ(new_emu.get_executed_instructions(), executedInstructions); diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index 69b4babc..5437aec1 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -141,7 +141,7 @@ namespace test const auto get_state_for_count = [&](const size_t count) { reset_emulator(); - emu.start({}, count); + emu.start(count); utils::buffer_serializer state{}; emu.serialize(state); diff --git a/src/windows-emulator-test/serialization_test.cpp b/src/windows-emulator-test/serialization_test.cpp index b82de8d3..1aadaabc 100644 --- a/src/windows-emulator-test/serialization_test.cpp +++ b/src/windows-emulator-test/serialization_test.cpp @@ -77,7 +77,7 @@ namespace test TEST(SerializationTest, DeserializedEmulatorBehavesLikeSource) { auto emu = create_sample_emulator(); - emu.start({}, 100); + emu.start(100); utils::buffer_serializer serializer{}; emu.serialize(serializer); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 8a08ae67..cccbb3fb 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -514,15 +514,10 @@ void windows_emulator::setup_hooks() [&](const uint64_t address, const size_t, const uint64_t) { this->on_instruction_execution(address); }); } -void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count) +void windows_emulator::start(size_t count) { const auto use_count = count > 0; - const auto use_timeout = timeout != std::chrono::nanoseconds{}; - - const auto start_time = std::chrono::high_resolution_clock::now(); const auto start_instructions = this->executed_instructions_; - - const auto target_time = start_time + timeout; const auto target_instructions = start_instructions + count; while (true) @@ -532,25 +527,13 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count) this->perform_thread_switch(); } - this->emu().start_from_ip(timeout, count); + this->emu().start(count); if (!this->switch_thread_ && !this->emu().has_violation()) { break; } - if (use_timeout) - { - const auto now = std::chrono::high_resolution_clock::now(); - - if (now >= target_time) - { - break; - } - - timeout = target_time - now; - } - if (use_count) { const auto current_instructions = this->executed_instructions_; diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 7da1b18b..53c17f5c 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -130,7 +130,7 @@ class windows_emulator return this->executed_instructions_; } - void start(std::chrono::nanoseconds timeout = {}, size_t count = 0); + void start(size_t count = 0); void serialize(utils::buffer_serializer& buffer) const; void deserialize(utils::buffer_deserializer& buffer); diff --git a/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp b/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp index b3ec03a4..1755e09a 100644 --- a/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp +++ b/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp @@ -37,7 +37,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler { try { - this->win_emu_->start({}, 1); + this->win_emu_->start(1); } catch (const std::exception& e) { diff --git a/src/windows-gdb-stub/x64_gdb_stub_handler.hpp b/src/windows-gdb-stub/x64_gdb_stub_handler.hpp index 64dea478..6fedb346 100644 --- a/src/windows-gdb-stub/x64_gdb_stub_handler.hpp +++ b/src/windows-gdb-stub/x64_gdb_stub_handler.hpp @@ -64,7 +64,7 @@ class x64_gdb_stub_handler : public gdb_stub::debugging_handler { try { - this->emu_->start_from_ip(); + this->emu_->start(); } catch (const std::exception& e) { @@ -78,7 +78,7 @@ class x64_gdb_stub_handler : public gdb_stub::debugging_handler { try { - this->emu_->start_from_ip({}, 1); + this->emu_->start(1); } catch (const std::exception& e) {