Move executed instructions into windows emulator

This commit is contained in:
Maurice Heumann
2025-03-18 12:35:38 +01:00
parent 2cc2137c3a
commit 95c7ffbf91
6 changed files with 26 additions and 29 deletions

View File

@@ -17,7 +17,7 @@ namespace test
auto emu = create_sample_emulator();
emu.start({}, count);
ASSERT_EQ(emu.process.executed_instructions, count);
ASSERT_EQ(emu.get_executed_instructions(), count);
}
TEST(EmulationTest, CountedEmulationIsAccurate)
@@ -27,7 +27,7 @@ namespace test
ASSERT_TERMINATED_SUCCESSFULLY(emu);
const auto executedInstructions = emu.process.executed_instructions;
const auto executedInstructions = emu.get_executed_instructions();
auto new_emu = create_sample_emulator();
@@ -36,12 +36,12 @@ namespace test
new_emu.start({}, instructionsToExecute);
ASSERT_EQ(new_emu.process.executed_instructions, instructionsToExecute);
ASSERT_EQ(new_emu.get_executed_instructions(), instructionsToExecute);
ASSERT_NOT_TERMINATED(new_emu);
new_emu.start({}, offset);
ASSERT_TERMINATED_SUCCESSFULLY(new_emu);
ASSERT_EQ(new_emu.process.executed_instructions, executedInstructions);
ASSERT_EQ(new_emu.get_executed_instructions(), executedInstructions);
}
}

View File

@@ -101,7 +101,7 @@ namespace test
emu.serialize(start_state);
emu.start();
const auto limit = emu.process.executed_instructions;
const auto limit = emu.get_executed_instructions();
const auto reset_emulator = [&] {
utils::buffer_deserializer deserializer{start_state.get_buffer()};

View File

@@ -125,7 +125,6 @@ void process_context::setup(x64_emulator& emu, memory_manager& memory, const app
void process_context::serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->executed_instructions);
buffer.write(this->current_ip);
buffer.write(this->previous_ip);
buffer.write_optional(this->exception_rip);
@@ -159,7 +158,6 @@ void process_context::serialize(utils::buffer_serializer& buffer) const
void process_context::deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->executed_instructions);
buffer.read(this->current_ip);
buffer.read(this->previous_ip);
buffer.read_optional(this->exception_rip);

View File

@@ -58,7 +58,6 @@ struct process_context
callbacks* callbacks_{};
uint64_t executed_instructions{0};
uint64_t current_ip{0};
uint64_t previous_ip{0};

View File

@@ -164,31 +164,26 @@ namespace
struct instruction_tick_clock : utils::tick_clock
{
windows_emulator* win_emu_{};
const uint64_t* instructions_{};
instruction_tick_clock(windows_emulator& win_emu, const system_time_point system_start = {},
instruction_tick_clock(const uint64_t& instructions, const system_time_point system_start = {},
const steady_time_point steady_start = {})
: tick_clock(1000, system_start, steady_start),
win_emu_(&win_emu)
instructions_(&instructions)
{
}
uint64_t ticks() override
{
if (!this->win_emu_->base_constructed_) // TODO: Remove that
{
throw std::runtime_error("Requesting ticks before construction!");
}
return this->win_emu_->process.executed_instructions;
return *this->instructions_;
}
};
std::unique_ptr<utils::clock> get_clock(windows_emulator& win_emu, const bool use_relative_time)
std::unique_ptr<utils::clock> get_clock(const uint64_t& instructions, const bool use_relative_time)
{
if (use_relative_time)
{
return std::make_unique<instruction_tick_clock>(win_emu);
return std::make_unique<instruction_tick_clock>(instructions);
}
return std::make_unique<utils::clock>();
@@ -212,7 +207,7 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul
windows_emulator::windows_emulator(const emulator_settings& settings, std::unique_ptr<x64_emulator> emu)
: emu_(std::move(emu)),
clock_(get_clock(*this, settings.use_relative_time)),
clock_(get_clock(this->executed_instructions_, settings.use_relative_time)),
emulation_root{settings.emulation_root.empty() ? settings.emulation_root : absolute(settings.emulation_root)},
file_sys(emulation_root.empty() ? emulation_root : emulation_root / "filesys"),
memory(*this->emu_),
@@ -220,8 +215,6 @@ windows_emulator::windows_emulator(const emulator_settings& settings, std::uniqu
mod_manager(memory, file_sys, callbacks),
process(*this->emu_, memory, *this->clock_, callbacks)
{
this->base_constructed_ = true;
#ifndef OS_WINDOWS
if (this->emulation_root.empty())
{
@@ -288,7 +281,7 @@ void windows_emulator::perform_thread_switch()
{
if (this->use_relative_time_)
{
this->process.executed_instructions += MAX_INSTRUCTIONS_PER_TIME_SLICE;
this->executed_instructions_ += MAX_INSTRUCTIONS_PER_TIME_SLICE;
}
else
{
@@ -312,7 +305,7 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
{
auto& thread = this->current_thread();
++this->process.executed_instructions;
++this->executed_instructions_;
const auto thread_insts = ++thread.executed_instructions;
if (thread_insts % MAX_INSTRUCTIONS_PER_TIME_SLICE == 0)
{
@@ -403,7 +396,7 @@ void windows_emulator::setup_hooks()
});
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] {
const auto instructions = this->process.executed_instructions;
const auto instructions = this->executed_instructions_;
this->emu().reg(x64_register::rax, instructions & 0xFFFFFFFF);
this->emu().reg(x64_register::rdx, (instructions >> 32) & 0xFFFFFFFF);
return instruction_hook_continuation::skip_instruction;
@@ -484,7 +477,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
const auto use_timeout = timeout != std::chrono::nanoseconds{};
const auto start_time = std::chrono::high_resolution_clock::now();
const auto start_instructions = this->process.executed_instructions;
const auto start_instructions = this->executed_instructions_;
const auto target_time = start_time + timeout;
const auto target_instructions = start_instructions + count;
@@ -517,7 +510,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
if (use_count)
{
const auto current_instructions = this->process.executed_instructions;
const auto current_instructions = this->executed_instructions_;
if (current_instructions >= target_instructions)
{
@@ -531,6 +524,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
void windows_emulator::serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->executed_instructions_);
buffer.write(this->switch_thread_);
buffer.write(this->use_relative_time_);
this->emu().serialize_state(buffer, false);
@@ -562,6 +556,7 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
return clock_wrapper{this->clock()}; //
});
buffer.read(this->executed_instructions_);
buffer.read(this->switch_thread_);
const auto old_relative_time = this->use_relative_time_;

View File

@@ -47,6 +47,8 @@ struct emulator_settings
class windows_emulator
{
uint64_t executed_instructions_{0};
std::unique_ptr<x64_emulator> emu_{};
std::unique_ptr<utils::clock> clock_{};
@@ -104,6 +106,11 @@ class windows_emulator
return *this->process.active_thread;
}
uint64_t get_executed_instructions() const
{
return this->executed_instructions_;
}
void start(std::chrono::nanoseconds timeout = {}, size_t count = 0);
void serialize(utils::buffer_serializer& buffer) const;
@@ -160,8 +167,6 @@ class windows_emulator
void perform_thread_switch();
bool activate_thread(uint32_t id);
bool base_constructed_{false};
private:
bool switch_thread_{false};
bool use_relative_time_{false};