Cleanup exception handling and prepare UI support

This commit is contained in:
momo5502
2025-01-11 09:51:22 +01:00
parent ff6fd79dd5
commit b2b2ffd6be
3 changed files with 67 additions and 33 deletions

View File

@@ -407,8 +407,10 @@ namespace
});
}
void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address,
const memory_operation operation)
template <typename T>
requires(std::is_integral_v<T>)
void dispatch_exception(x64_emulator& emu, const process_context& proc, const T status,
const std::vector<EmulatorTraits<Emu64>::ULONG_PTR>& parameters)
{
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
@@ -416,40 +418,47 @@ namespace
EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ACCESS_VIOLATION);
record.ExceptionCode = static_cast<DWORD>(status);
record.ExceptionFlags = 0;
record.ExceptionRecord = 0;
record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 2;
record.ExceptionInformation[0] = map_violation_operation_to_parameter(operation);
record.ExceptionInformation[1] = address;
record.ExceptionAddress = emu.read_instruction_pointer();
record.NumberParameters = static_cast<DWORD>(parameters.size());
if (parameters.size() > 15)
{
throw std::runtime_error("Too many exception parameters");
}
for (size_t i = 0; i < parameters.size(); ++i)
{
record.ExceptionInformation[i] = parameters[i];
}
EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers);
dispatch_exception_pointers(emu, proc.ki_user_exception_dispatcher, pointers);
}
void dispatch_illegal_instruction_violation(x64_emulator& emu, const uint64_t dispatcher)
void dispatch_access_violation(x64_emulator& emu, const process_context& proc, const uint64_t address,
const memory_operation operation)
{
CONTEXT64 ctx{};
ctx.ContextFlags = CONTEXT64_ALL;
context_frame::save(emu, ctx);
dispatch_exception(emu, proc, STATUS_ACCESS_VIOLATION,
{
map_violation_operation_to_parameter(operation),
address,
});
}
EMU_EXCEPTION_RECORD<EmulatorTraits<Emu64>> record{};
memset(&record, 0, sizeof(record));
record.ExceptionCode = static_cast<DWORD>(STATUS_ILLEGAL_INSTRUCTION);
record.ExceptionFlags = 0;
record.ExceptionRecord = 0;
record.ExceptionAddress = static_cast<EmulatorTraits<Emu64>::PVOID>(emu.read_instruction_pointer());
record.NumberParameters = 0;
void dispatch_illegal_instruction_violation(x64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_ILLEGAL_INSTRUCTION, {});
}
EMU_EXCEPTION_POINTERS<EmulatorTraits<Emu64>> pointers{};
pointers.ContextRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&ctx);
pointers.ExceptionRecord = reinterpret_cast<EmulatorTraits<Emu64>::PVOID>(&record);
dispatch_exception_pointers(emu, dispatcher, pointers);
void dispatch_integer_division_by_zero(x64_emulator& emu, const process_context& proc)
{
dispatch_exception(emu, proc, STATUS_INTEGER_DIVIDE_BY_ZERO, {});
}
void perform_context_switch_work(windows_emulator& win_emu)
@@ -891,9 +900,15 @@ void windows_emulator::setup_hooks()
});
this->emu().hook_interrupt([&](const int interrupt) {
if (interrupt == 0)
{
dispatch_integer_division_by_zero(this->emu(), this->process());
return;
}
if (interrupt == 6)
{
dispatch_illegal_instruction_violation(this->emu(), this->process().ki_user_exception_dispatcher);
dispatch_illegal_instruction_violation(this->emu(), this->process());
return;
}
@@ -931,7 +946,7 @@ void windows_emulator::setup_hooks()
return memory_violation_continuation::stop;
}
dispatch_access_violation(this->emu(), this->process().ki_user_exception_dispatcher, address, operation);
dispatch_access_violation(this->emu(), this->process(), address, operation);
return memory_violation_continuation::resume;
});