mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 08:36:16 +00:00
Improve clarity in dispatch_user_callback
This commit is contained in:
@@ -408,6 +408,8 @@ inline std::u16string read_unicode_string(emulator& emu, const uint64_t uc_strin
|
||||
return read_unicode_string(emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{emu, uc_string});
|
||||
}
|
||||
|
||||
/// Retrieves function arguments from registers or stack memory. This function assumes the caller has already allocated
|
||||
/// stack space and that RSP currently points to the return address.
|
||||
inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index, const bool is_syscall = false)
|
||||
{
|
||||
bool use_32bit_stack = false;
|
||||
@@ -441,6 +443,8 @@ inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets function arguments in registers or stack memory. This function does not modify RSP and assumes the caller has already allocated
|
||||
/// stack space and that RSP currently points to the return address.
|
||||
inline void set_function_argument(x86_64_emulator& emu, const size_t index, const uint64_t value, const bool is_syscall = false)
|
||||
{
|
||||
bool use_32bit_stack = false;
|
||||
|
||||
@@ -7,39 +7,41 @@
|
||||
// index that refers to an entry in PEB->KernelCallbackTable. The dispatcher then looks up the function
|
||||
// pointer in that table and invokes the corresponding user-mode callback.
|
||||
|
||||
template <typename... Args>
|
||||
void prepare_call_stack(x86_64_emulator& emu, uint64_t return_address, Args... args)
|
||||
{
|
||||
constexpr size_t arg_count = sizeof...(Args);
|
||||
const size_t stack_args_size = aligned_stack_space(arg_count);
|
||||
|
||||
const uint64_t current_rsp = emu.read_stack_pointer();
|
||||
const uint64_t aligned_rsp = align_down(current_rsp, 16);
|
||||
|
||||
// We subtract the args size (including the shadow space) AND the size of the return address
|
||||
const uint64_t new_rsp = aligned_rsp - stack_args_size - sizeof(emulator_pointer);
|
||||
emu.reg(x86_register::rsp, new_rsp);
|
||||
|
||||
emu.write_memory(new_rsp, &return_address, sizeof(return_address));
|
||||
|
||||
size_t index = 0;
|
||||
(set_function_argument(emu, index++, static_cast<uint64_t>(args)), ...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void dispatch_user_callback(const syscall_context& c, callback_id completion_id, uint64_t func_address, Args... args)
|
||||
{
|
||||
const uint64_t original_rsp = c.emu.read_stack_pointer();
|
||||
|
||||
// Save syscall argument registers BEFORE modifying anything
|
||||
const callback_frame frame{
|
||||
.handler_id = completion_id,
|
||||
.rip = c.emu.read_instruction_pointer(),
|
||||
.rsp = original_rsp,
|
||||
.rsp = c.emu.read_stack_pointer(),
|
||||
.r10 = c.emu.reg(x86_register::r10),
|
||||
.rcx = c.emu.reg(x86_register::rcx),
|
||||
.rdx = c.emu.reg(x86_register::rdx),
|
||||
.r8 = c.emu.reg(x86_register::r8),
|
||||
.r9 = c.emu.reg(x86_register::r9),
|
||||
};
|
||||
|
||||
uint64_t stack_ptr = align_down(original_rsp, 16);
|
||||
|
||||
constexpr size_t arg_count = sizeof...(Args);
|
||||
const size_t allocation_size = aligned_stack_space(arg_count);
|
||||
stack_ptr -= allocation_size;
|
||||
|
||||
// Push the return address onto the stack (Simulating CALL)
|
||||
stack_ptr -= sizeof(emulator_pointer);
|
||||
c.emu.write_memory(stack_ptr, &c.proc.callback_sentinel_addr, sizeof(c.proc.callback_sentinel_addr));
|
||||
|
||||
c.proc.active_thread->callback_stack.push_back(frame);
|
||||
|
||||
c.emu.reg(x86_register::rsp, stack_ptr);
|
||||
|
||||
size_t index = 0;
|
||||
(set_function_argument(c.emu, index++, static_cast<uint64_t>(args)), ...);
|
||||
prepare_call_stack(c.emu, c.proc.callback_sentinel_addr, args...);
|
||||
|
||||
c.emu.reg(x86_register::rip, func_address);
|
||||
c.run_callback = true;
|
||||
|
||||
Reference in New Issue
Block a user