rexglue-skate3/src/core/seh_win.cpp
2026-05-18 22:41:13 +01:00

72 lines
2 KiB
C++

/**
* @file core/seh_win.cpp
* @brief Windows platform SEH implementations
*
* @copyright Copyright (c) 2026 Tom Clay <tomc@tctechstuff.com>
* @license BSD 3-Clause License
*/
#include <rex/platform.h>
#include <rex/platform/seh.h>
static_assert(REX_PLATFORM_WIN32, "This file is Windows-only");
#include "platform_win.h"
namespace rex::platform {
static thread_local SehThreadState tls_seh_state;
static thread_local bool tls_seh_active = false;
SehThreadState& seh_thread_state() {
return tls_seh_state;
}
int seh_filter(uint32_t code, void* ep) {
auto* pointers = static_cast<EXCEPTION_POINTERS*>(ep);
switch (code) {
case EXCEPTION_ACCESS_VIOLATION:
case EXCEPTION_IN_PAGE_ERROR:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_STACK_OVERFLOW:
tls_seh_state.code = code;
if (pointers && pointers->ExceptionRecord) {
tls_seh_state.info[0] = pointers->ExceptionRecord->ExceptionInformation[0];
tls_seh_state.info[1] = pointers->ExceptionRecord->ExceptionInformation[1];
}
return EXCEPTION_EXECUTE_HANDLER;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
[[noreturn]] void seh_rethrow() {
uint32_t code = tls_seh_state.code;
ULONG_PTR info[2] = {tls_seh_state.info[0], tls_seh_state.info[1]};
// For access violations, include the extra info (read/write flag and address)
if (code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_IN_PAGE_ERROR) {
RaiseException(code, EXCEPTION_NONCONTINUABLE, 2, info);
} else {
RaiseException(code, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
// RaiseException doesn't return, but compiler may not know that
#ifdef __clang__
__builtin_unreachable();
#else
__assume(false);
#endif
}
void seh_initialize() {
// Native SEH needs no signal handler setup, but mark as initialized
g_seh_initialized.store(true, std::memory_order_relaxed);
}
bool& seh_active() {
return tls_seh_active;
}
} // namespace rex::platform