mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-26 00:56:45 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c1e327ade |
@@ -22,6 +22,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/logging.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "dynarmic/backend/exception_handler.h"
|
#include "dynarmic/backend/exception_handler.h"
|
||||||
#include "dynarmic/common/context.h"
|
#include "dynarmic/common/context.h"
|
||||||
@@ -53,23 +54,21 @@ class SigHandler {
|
|||||||
return e.first <= offset && e.first + e.second.size > offset;
|
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;
|
ankerl::unordered_dense::map<u64, CodeBlockInfo> code_block_infos;
|
||||||
std::shared_mutex code_block_infos_mutex;
|
std::shared_mutex code_block_infos_mutex;
|
||||||
struct sigaction old_sa_segv;
|
struct sigaction old_sa_segv;
|
||||||
struct sigaction old_sa_bus;
|
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:
|
public:
|
||||||
SigHandler() noexcept {
|
SigHandler() noexcept {
|
||||||
signal_stack_size = std::max<size_t>(SIGSTKSZ, 2 * 1024 * 1024);
|
auto const 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);
|
signal_stack_memory = std::make_unique<uint8_t[]>(stack_size);
|
||||||
|
|
||||||
stack_t signal_stack{};
|
stack_t signal_stack{};
|
||||||
signal_stack.ss_sp = signal_stack_memory;
|
signal_stack.ss_sp = signal_stack_memory.get();
|
||||||
signal_stack.ss_size = signal_stack_size;
|
signal_stack.ss_size = stack_size;
|
||||||
signal_stack.ss_flags = 0;
|
signal_stack.ss_flags = 0;
|
||||||
if (sigaltstack(&signal_stack, nullptr) != 0) {
|
if (sigaltstack(&signal_stack, nullptr) != 0) {
|
||||||
fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n");
|
fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n");
|
||||||
@@ -87,7 +86,7 @@ public:
|
|||||||
supports_fast_mem = false;
|
supports_fast_mem = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
#if defined(__APPLE__)
|
||||||
if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) {
|
if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) {
|
||||||
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n");
|
fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n");
|
||||||
supports_fast_mem = false;
|
supports_fast_mem = false;
|
||||||
@@ -96,10 +95,6 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~SigHandler() noexcept {
|
|
||||||
munmap(signal_stack_memory, signal_stack_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {
|
void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept {
|
||||||
std::unique_lock guard(code_block_infos_mutex);
|
std::unique_lock guard(code_block_infos_mutex);
|
||||||
code_block_infos.insert_or_assign(offset, cbi);
|
code_block_infos.insert_or_assign(offset, cbi);
|
||||||
@@ -109,14 +104,17 @@ public:
|
|||||||
code_block_infos.erase(offset);
|
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;
|
std::optional<SigHandler> sig_handler;
|
||||||
|
|
||||||
void RegisterHandler() {
|
void SigHandler::RegisterHandler() {
|
||||||
std::lock_guard<std::mutex> guard(handler_lock);
|
|
||||||
if (!sig_handler) {
|
if (!sig_handler) {
|
||||||
sig_handler.emplace();
|
sig_handler.emplace();
|
||||||
}
|
}
|
||||||
@@ -125,51 +123,27 @@ void RegisterHandler() {
|
|||||||
void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS);
|
DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS);
|
||||||
CTX_DECLARE(raw_context);
|
CTX_DECLARE(raw_context);
|
||||||
#if defined(ARCHITECTURE_x86_64)
|
|
||||||
{
|
{
|
||||||
std::shared_lock guard(sig_handler->code_block_infos_mutex);
|
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()) {
|
if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) {
|
||||||
FakeCall fc = iter->second.cb(CTX_PC);
|
FakeCall fc = iter->second.cb(CTX_PC);
|
||||||
|
#if defined(ARCHITECTURE_x86_64)
|
||||||
CTX_SP -= sizeof(u64);
|
CTX_SP -= sizeof(u64);
|
||||||
*std::bit_cast<u64*>(CTX_SP) = fc.ret_rip;
|
*std::bit_cast<u64*>(CTX_SP) = fc.ret_rip;
|
||||||
CTX_PC = fc.call_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)
|
#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;
|
CTX_PC = fc.call_pc;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
|
|
||||||
#elif defined(ARCHITECTURE_riscv64)
|
#elif defined(ARCHITECTURE_riscv64)
|
||||||
{
|
CTX_PC = fc.call_sepc;
|
||||||
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);
|
|
||||||
#elif defined(ARCHITECTURE_loongarch64)
|
#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;
|
CTX_PC = fc.call_pc;
|
||||||
|
#else
|
||||||
|
ASSERT(false);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
|
LOG_ERROR(Core, "Unhandled {} at {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC);
|
||||||
#else
|
|
||||||
# error "Invalid architecture"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus;
|
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus;
|
||||||
if (retry_sa->sa_flags & SA_SIGINFO) {
|
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 {
|
struct ExceptionHandler::Impl final {
|
||||||
Impl(u64 offset_, u64 size_)
|
Impl(u64 offset_, u64 size_)
|
||||||
: offset(offset_)
|
: offset(offset_)
|
||||||
, size(size_) {
|
, size(size_)
|
||||||
RegisterHandler();
|
{
|
||||||
|
SigHandler::RegisterHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCallback(std::function<FakeCall(u64)> cb) {
|
void SetCallback(std::function<FakeCall(u64)> cb) {
|
||||||
|
|||||||
@@ -136,14 +136,14 @@
|
|||||||
# endif
|
# endif
|
||||||
#elif defined(ARCHITECTURE_riscv64)
|
#elif defined(ARCHITECTURE_riscv64)
|
||||||
# if defined(__FreeBSD__)
|
# 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)
|
# define CTX_SP (mctx.mc_gpregs.gp_sp)
|
||||||
# elif defined(__linux__)
|
# elif defined(__linux__)
|
||||||
# define CTX_SEPC (mctx.__gregs[REG_PC])
|
# define CTX_PC (mctx.__gregs[REG_PC])
|
||||||
# define CTX_SP (mctx.__gregs[REG_SP])
|
# define CTX_SP (mctx.__gregs[REG_SP])
|
||||||
# elif defined(__OpenBSD__)
|
# elif defined(__OpenBSD__)
|
||||||
// https://github.com/openbsd/src/blob/master/sys/arch/riscv64/include/signal.h
|
// 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)
|
# define CTX_SP (ucontext->sc_sp)
|
||||||
# else
|
# else
|
||||||
# error "unknown platform"
|
# error "unknown platform"
|
||||||
|
|||||||
Reference in New Issue
Block a user