From 6c1e327ade7ef8e3c470a9d85a2d36f715c01376 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 22 Aug 2026 19:41:29 +0000 Subject: [PATCH] [dynarmic/backend/exception_handler] normalize EH for arches, use LOG_ERROR instead of fmt::print Signed-off-by: lizzie --- .../backend/exception_handler_posix.cpp | 75 +++++++------------ src/dynarmic/src/dynarmic/common/context.h | 6 +- 2 files changed, 28 insertions(+), 53 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index c586cf2fb1..a64423581b 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -22,6 +22,7 @@ #include #include "common/assert.h" +#include "common/logging.h" #include "common/common_types.h" #include "dynarmic/backend/exception_handler.h" #include "dynarmic/common/context.h" @@ -53,23 +54,21 @@ class SigHandler { return e.first <= offset && e.first + e.second.size > offset; }); } - static void SigAction(int sig, siginfo_t* info, void* raw_context); - bool supports_fast_mem = true; - void* signal_stack_memory = nullptr; ankerl::unordered_dense::map code_block_infos; std::shared_mutex code_block_infos_mutex; struct sigaction old_sa_segv; struct sigaction old_sa_bus; - std::size_t signal_stack_size; + std::unique_ptr signal_stack_memory; + bool supports_fast_mem = true; public: SigHandler() noexcept { - signal_stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); - signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + auto const stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); + signal_stack_memory = std::make_unique(stack_size); stack_t signal_stack{}; - signal_stack.ss_sp = signal_stack_memory; - signal_stack.ss_size = signal_stack_size; + signal_stack.ss_sp = signal_stack_memory.get(); + signal_stack.ss_size = stack_size; signal_stack.ss_flags = 0; if (sigaltstack(&signal_stack, nullptr) != 0) { fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n"); @@ -87,7 +86,7 @@ public: supports_fast_mem = false; return; } -#ifdef __APPLE__ +#if defined(__APPLE__) if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) { fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n"); supports_fast_mem = false; @@ -96,10 +95,6 @@ public: #endif } - ~SigHandler() noexcept { - munmap(signal_stack_memory, signal_stack_size); - } - void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept { std::unique_lock guard(code_block_infos_mutex); code_block_infos.insert_or_assign(offset, cbi); @@ -109,14 +104,17 @@ public: code_block_infos.erase(offset); } - bool SupportsFastmem() const noexcept { return supports_fast_mem; } + [[nodiscard]] inline bool SupportsFastmem() const noexcept { + return supports_fast_mem; + } + + static void RegisterHandler(); + static void SigAction(int sig, siginfo_t* info, void* raw_context); }; -std::mutex handler_lock; std::optional sig_handler; -void RegisterHandler() { - std::lock_guard guard(handler_lock); +void SigHandler::RegisterHandler() { if (!sig_handler) { sig_handler.emplace(); } @@ -125,51 +123,27 @@ void RegisterHandler() { void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS); CTX_DECLARE(raw_context); -#if defined(ARCHITECTURE_x86_64) { std::shared_lock guard(sig_handler->code_block_infos_mutex); if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) { FakeCall fc = iter->second.cb(CTX_PC); +#if defined(ARCHITECTURE_x86_64) CTX_SP -= sizeof(u64); *std::bit_cast(CTX_SP) = fc.ret_rip; CTX_PC = fc.call_rip; - return; - } - } - fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); #elif defined(ARCHITECTURE_arm64) - { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_PC); CTX_PC = fc.call_pc; - return; - } - } - fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); #elif defined(ARCHITECTURE_riscv64) - { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_SEPC); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_SEPC); - CTX_SEPC = fc.call_sepc; - return; - } - } - fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_SEPC); + CTX_PC = fc.call_sepc; #elif defined(ARCHITECTURE_loongarch64) - { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_PC); CTX_PC = fc.call_pc; +#else + ASSERT(false); +#endif return; } } - fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); -#else -# error "Invalid architecture" -#endif + LOG_ERROR(Core, "Unhandled {} at {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus; if (retry_sa->sa_flags & SA_SIGINFO) { @@ -190,9 +164,10 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { struct ExceptionHandler::Impl final { Impl(u64 offset_, u64 size_) - : offset(offset_) - , size(size_) { - RegisterHandler(); + : offset(offset_) + , size(size_) + { + SigHandler::RegisterHandler(); } void SetCallback(std::function cb) { diff --git a/src/dynarmic/src/dynarmic/common/context.h b/src/dynarmic/src/dynarmic/common/context.h index db7af8e0ae..0c18807ce5 100644 --- a/src/dynarmic/src/dynarmic/common/context.h +++ b/src/dynarmic/src/dynarmic/common/context.h @@ -136,14 +136,14 @@ # endif #elif defined(ARCHITECTURE_riscv64) # if defined(__FreeBSD__) -# define CTX_SEPC (mctx.mc_gpregs.gp_sepc) +# define CTX_PC (mctx.mc_gpregs.gp_sepc) # define CTX_SP (mctx.mc_gpregs.gp_sp) # elif defined(__linux__) -# define CTX_SEPC (mctx.__gregs[REG_PC]) +# define CTX_PC (mctx.__gregs[REG_PC]) # define CTX_SP (mctx.__gregs[REG_SP]) # elif defined(__OpenBSD__) // https://github.com/openbsd/src/blob/master/sys/arch/riscv64/include/signal.h -# define CTX_SEPC (ucontext->sc_sepc) +# define CTX_PC (ucontext->sc_sepc) # define CTX_SP (ucontext->sc_sp) # else # error "unknown platform"