mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-22 21:21:03 +00:00
Fix thread serialization
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
@@ -162,6 +163,21 @@ namespace utils
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
requires(std::is_invocable_r_v<T, F>)
|
||||
void read_optional(std::optional<T>& val, const F& constructor)
|
||||
{
|
||||
if (this->read<bool>())
|
||||
{
|
||||
val.emplace(constructor());
|
||||
this->read<T>(*val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = {};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_vector(std::vector<T>& result)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace
|
||||
try
|
||||
{
|
||||
win_emu.logger.disable_output(true);
|
||||
win_emu.emu().start_from_ip();
|
||||
win_emu.start();
|
||||
|
||||
if (win_emu.process().exception_rip.has_value())
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ struct handle_types
|
||||
{
|
||||
enum type : uint16_t
|
||||
{
|
||||
invalid = 0,
|
||||
file,
|
||||
event,
|
||||
section,
|
||||
@@ -35,6 +36,16 @@ union handle
|
||||
HANDLE h;
|
||||
};
|
||||
|
||||
inline void serialize(utils::buffer_serializer& buffer, const handle& h)
|
||||
{
|
||||
buffer.write(h.bits);
|
||||
}
|
||||
|
||||
inline void deserialize(utils::buffer_deserializer& buffer, handle& h)
|
||||
{
|
||||
buffer.read(h.bits);
|
||||
}
|
||||
|
||||
inline bool operator==(const handle& h1, const handle& h2)
|
||||
{
|
||||
return h1.bits == h2.bits;
|
||||
@@ -88,7 +99,8 @@ template <handle_types::type Type, typename T>
|
||||
class handle_store
|
||||
{
|
||||
public:
|
||||
using value_map = std::map<uint32_t, T>;
|
||||
using index_type = uint32_t;
|
||||
using value_map = std::map<index_type, T>;
|
||||
|
||||
handle store(T value)
|
||||
{
|
||||
@@ -98,7 +110,7 @@ public:
|
||||
return make_handle(index);
|
||||
}
|
||||
|
||||
handle make_handle(const uint32_t index)
|
||||
handle make_handle(const index_type index) const
|
||||
{
|
||||
handle h{};
|
||||
h.bits = 0;
|
||||
@@ -109,6 +121,11 @@ public:
|
||||
return h;
|
||||
}
|
||||
|
||||
T* get_by_index(const uint32_t index)
|
||||
{
|
||||
return this->get(this->make_handle(index));
|
||||
}
|
||||
|
||||
T* get(const handle_value h)
|
||||
{
|
||||
const auto entry = this->get_iterator(h);
|
||||
@@ -220,6 +237,27 @@ public:
|
||||
return i;
|
||||
}
|
||||
|
||||
handle find_handle(const T& value) const
|
||||
{
|
||||
const auto entry = this->find(value);
|
||||
if (entry == this->end())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return this->make_handle(entry->first);
|
||||
}
|
||||
|
||||
handle find_handle(const T* value) const
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return this->find_handle(*value);
|
||||
}
|
||||
|
||||
typename value_map::iterator begin()
|
||||
{
|
||||
return this->store_.begin();
|
||||
|
||||
@@ -23,6 +23,20 @@
|
||||
#define GDT_LIMIT 0x1000
|
||||
#define GDT_ENTRY_SIZE 0x8
|
||||
|
||||
inline void serialize(utils::buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp)
|
||||
{
|
||||
buffer.write(tp.time_since_epoch().count());
|
||||
}
|
||||
|
||||
inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp)
|
||||
{
|
||||
using time_point = std::chrono::steady_clock::time_point;
|
||||
using duration = time_point::duration;
|
||||
|
||||
const auto count = buffer.read<duration::rep>();
|
||||
tp = time_point{duration{count}};
|
||||
}
|
||||
|
||||
struct ref_counted_object
|
||||
{
|
||||
uint32_t ref_count{1};
|
||||
@@ -269,14 +283,54 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer&) const
|
||||
void serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
// TODO
|
||||
buffer.write(this->stack_base);
|
||||
buffer.write(this->stack_size);
|
||||
buffer.write(this->start_address);
|
||||
buffer.write(this->argument);
|
||||
buffer.write(this->executed_instructions);
|
||||
buffer.write(this->id);
|
||||
|
||||
buffer.write_string(this->name);
|
||||
|
||||
buffer.write_optional(this->exit_status);
|
||||
buffer.write_optional(this->await_object);
|
||||
|
||||
buffer.write(this->waiting_for_alert);
|
||||
buffer.write(this->alerted);
|
||||
|
||||
buffer.write_optional(this->await_time);
|
||||
buffer.write_optional(this->pending_status);
|
||||
buffer.write_optional(this->gs_segment);
|
||||
buffer.write_optional(this->teb);
|
||||
|
||||
buffer.write_vector(this->last_registers);
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer&)
|
||||
void deserialize(utils::buffer_deserializer& buffer)
|
||||
{
|
||||
// TODO
|
||||
buffer.read(this->stack_base);
|
||||
buffer.read(this->stack_size);
|
||||
buffer.read(this->start_address);
|
||||
buffer.read(this->argument);
|
||||
buffer.read(this->executed_instructions);
|
||||
buffer.read(this->id);
|
||||
|
||||
buffer.read_string(this->name);
|
||||
|
||||
buffer.read_optional(this->exit_status);
|
||||
buffer.read_optional(this->await_object);
|
||||
|
||||
buffer.read(this->waiting_for_alert);
|
||||
buffer.read(this->alerted);
|
||||
|
||||
buffer.read_optional(this->await_time);
|
||||
buffer.read_optional(this->pending_status);
|
||||
buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->emu_ptr); });
|
||||
buffer.read_optional(this->teb, [this] { return emulator_object<TEB>(*this->emu_ptr); });
|
||||
|
||||
buffer.read_vector(this->last_registers);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -336,6 +390,7 @@ struct process_context
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
buffer.write_optional(this->exception_rip);
|
||||
buffer.write(this->base_allocator);
|
||||
buffer.write(this->peb);
|
||||
buffer.write(this->process_params);
|
||||
buffer.write(this->kusd);
|
||||
@@ -345,6 +400,8 @@ struct process_context
|
||||
buffer.write(this->ntdll->image_base);
|
||||
buffer.write(this->win32u->image_base);
|
||||
|
||||
buffer.write(this->ldr_initialize_thunk);
|
||||
buffer.write(this->rtl_user_thread_start);
|
||||
buffer.write(this->ki_user_exception_dispatcher);
|
||||
|
||||
buffer.write(this->shared_section_size);
|
||||
@@ -354,7 +411,11 @@ struct process_context
|
||||
buffer.write(this->ports);
|
||||
buffer.write_map(this->atoms);
|
||||
|
||||
// TODO: Serialize/deserialize threads
|
||||
buffer.write_vector(this->default_register_set);
|
||||
buffer.write(this->current_thread_id);
|
||||
buffer.write(this->threads);
|
||||
|
||||
buffer.write(this->threads.find_handle(this->active_thread).bits);
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer& buffer)
|
||||
@@ -363,6 +424,7 @@ struct process_context
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
buffer.read_optional(this->exception_rip);
|
||||
buffer.read(this->base_allocator);
|
||||
buffer.read(this->peb);
|
||||
buffer.read(this->process_params);
|
||||
buffer.read(this->kusd);
|
||||
@@ -376,6 +438,8 @@ struct process_context
|
||||
this->ntdll = this->module_manager.find_by_address(ntdll_base);
|
||||
this->win32u = this->module_manager.find_by_address(win32u_base);
|
||||
|
||||
buffer.read(this->ldr_initialize_thunk);
|
||||
buffer.read(this->rtl_user_thread_start);
|
||||
buffer.read(this->ki_user_exception_dispatcher);
|
||||
|
||||
buffer.read(this->shared_section_size);
|
||||
@@ -384,6 +448,12 @@ struct process_context
|
||||
buffer.read(this->semaphores);
|
||||
buffer.read(this->ports);
|
||||
buffer.read_map(this->atoms);
|
||||
|
||||
buffer.read_vector(this->default_register_set);
|
||||
buffer.read(this->current_thread_id);
|
||||
buffer.read(this->threads);
|
||||
|
||||
this->active_thread = this->threads.get(buffer.read<uint64_t>());
|
||||
}
|
||||
|
||||
handle create_thread(x64_emulator& emu, const uint64_t start_address, const uint64_t argument,
|
||||
|
||||
Reference in New Issue
Block a user