aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2026-08-28 02:30:18 +0200
committercrueter <crueter@eden-emu.dev>2026-08-28 02:30:18 +0200
commitb859d7fdf4ed64651d01ed4eebd4dfb93eea4cc3 (patch)
tree33cd187f3a9a921ac479170db442b23b74346850 /src
parentf635827fa66c2c4e5d50136e147dd1ac1439cd3f (diff)
[dynarmic/backend/exception_handler] normalize EH for arches, use LOG_ERROR instead of fmt::print (#4283)
Signed-off-by: lizzie <lizzie@eden-emu.dev> - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- this should simplify a bit of code logic akin to NetBSD's UC_CONTEXT_PC... additionally use LOG_ERROR so the "unhandled ..." is logged unto a file before sigsegv'ing Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4283 Reviewed-by: Maufeat <sahyno1996@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp75
-rw-r--r--src/dynarmic/src/dynarmic/common/context.h6
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 <sys/mman.h>
#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<u64, CodeBlockInfo> 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<uint8_t[]> signal_stack_memory;
+ bool supports_fast_mem = true;
public:
SigHandler() noexcept {
- signal_stack_size = std::max<size_t>(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<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
+ signal_stack_memory = std::make_unique<uint8_t[]>(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<SigHandler> sig_handler;
-void RegisterHandler() {
- std::lock_guard<std::mutex> 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<u64*>(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<FakeCall(u64)> 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"