From d635b12b846b42926fccb93d378de2d18dcd62cd Mon Sep 17 00:00:00 2001 From: Merry Date: Sun, 11 Dec 2022 02:38:58 +0000 Subject: [PATCH] exception_handler_posix: Support arm64 backend --- src/dynarmic/CMakeLists.txt | 21 +- src/dynarmic/backend/exception_handler.h | 67 ++++ .../{x64 => }/exception_handler_generic.cpp | 16 +- .../backend/exception_handler_posix.cpp | 294 ++++++++++++++++++ src/dynarmic/backend/x64/emit_x64.h | 2 +- src/dynarmic/backend/x64/exception_handler.h | 37 --- .../backend/x64/exception_handler_macos.cpp | 8 +- .../backend/x64/exception_handler_posix.cpp | 208 ------------- .../backend/x64/exception_handler_windows.cpp | 8 +- 9 files changed, 399 insertions(+), 262 deletions(-) create mode 100644 src/dynarmic/backend/exception_handler.h rename src/dynarmic/backend/{x64 => }/exception_handler_generic.cpp (54%) create mode 100644 src/dynarmic/backend/exception_handler_posix.cpp delete mode 100644 src/dynarmic/backend/x64/exception_handler.h delete mode 100644 src/dynarmic/backend/x64/exception_handler_posix.cpp diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index aa1a5ac6..9b5cb40d 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(dynarmic + backend/exception_handler.h common/cast_util.h common/crypto/aes.cpp common/crypto/aes.h @@ -289,7 +290,6 @@ if (ARCHITECTURE STREQUAL "x86_64") backend/x64/emit_x64_vector.cpp backend/x64/emit_x64_vector_floating_point.cpp backend/x64/emit_x64_vector_saturation.cpp - backend/x64/exception_handler.h backend/x64/exclusive_monitor.cpp backend/x64/exclusive_monitor_friend.h backend/x64/host_feature.h @@ -336,7 +336,7 @@ if (ARCHITECTURE STREQUAL "x86_64") find_path(MACH_EXC_DEFS_DIR "mach/mach_exc.defs") if (NOT MACH_EXC_DEFS_DIR) message(WARNING "macOS fastmem disabled: unable to find mach/mach_exc.defs") - target_sources(dynarmic PRIVATE backend/x64/exception_handler_generic.cpp) + target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp) else() message(STATUS "mach/mach_exc.defs location: ${MACH_EXC_DEFS_DIR}") execute_process( @@ -361,9 +361,9 @@ if (ARCHITECTURE STREQUAL "x86_64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(dynarmic PRIVATE rt) endif() - target_sources(dynarmic PRIVATE backend/x64/exception_handler_posix.cpp) + target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp) else() - target_sources(dynarmic PRIVATE backend/x64/exception_handler_generic.cpp) + target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp) endif() elseif(ARCHITECTURE STREQUAL "arm64") target_link_libraries(dynarmic PRIVATE merry::oaknut) @@ -414,12 +414,21 @@ elseif(ARCHITECTURE STREQUAL "arm64") endif() if ("A64" IN_LIST DYNARMIC_FRONTENDS) - target_sources(dynarmic PRIVATE + target_sources(dynarmic PRIVATE backend/arm64/a64_address_space.cpp backend/arm64/a64_address_space.h backend/arm64/a64_core.h backend/arm64/a64_interface.cpp - ) + ) + endif() + + if (UNIX) + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + target_link_libraries(dynarmic PRIVATE rt) + endif() + target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp) + else() + target_sources(dynarmic PRIVATE backend/exception_handler_generic.cpp) endif() else() message(FATAL_ERROR "Unsupported architecture") diff --git a/src/dynarmic/backend/exception_handler.h b/src/dynarmic/backend/exception_handler.h new file mode 100644 index 00000000..2268297e --- /dev/null +++ b/src/dynarmic/backend/exception_handler.h @@ -0,0 +1,67 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#if defined(MCL_ARCHITECTURE_X86_64) +namespace Dynarmic::Backend::X64 { +class BlockOfCode; +} // namespace Dynarmic::Backend::X64 +#elif defined(MCL_ARCHITECTURE_ARM64) +namespace oaknut { +class CodeBlock; +} // namespace oaknut +#else +# error "Invalid architecture" +#endif + +namespace Dynarmic::Backend { + +#if defined(MCL_ARCHITECTURE_X86_64) +struct FakeCall { + u64 call_rip; + u64 ret_rip; +}; +#elif defined(MCL_ARCHITECTURE_ARM64) +struct FakeCall { + u64 call_pc; + u64 ret_pc; + std::optional load_xscratch0; + std::optional load_xscratch1; + std::optional load_q0; +}; +#else +# error "Invalid architecture" +#endif + +class ExceptionHandler final { +public: + ExceptionHandler(); + ~ExceptionHandler(); + +#if defined(MCL_ARCHITECTURE_X86_64) + void Register(X64::BlockOfCode& code); +#elif defined(MCL_ARCHITECTURE_ARM64) + void Register(oaknut::CodeBlock& mem, std::size_t mem_size); +#else +# error "Invalid architecture" +#endif + + bool SupportsFastmem() const noexcept; + void SetFastmemCallback(std::function cb); + +private: + struct Impl; + std::unique_ptr impl; +}; + +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/x64/exception_handler_generic.cpp b/src/dynarmic/backend/exception_handler_generic.cpp similarity index 54% rename from src/dynarmic/backend/x64/exception_handler_generic.cpp rename to src/dynarmic/backend/exception_handler_generic.cpp index 1bbf4e54..bbaa071a 100644 --- a/src/dynarmic/backend/x64/exception_handler_generic.cpp +++ b/src/dynarmic/backend/exception_handler_generic.cpp @@ -3,9 +3,9 @@ * SPDX-License-Identifier: 0BSD */ -#include "dynarmic/backend/x64/exception_handler.h" +#include "dynarmic/backend/exception_handler.h" -namespace Dynarmic::Backend::X64 { +namespace Dynarmic::Backend { struct ExceptionHandler::Impl final { }; @@ -13,9 +13,17 @@ struct ExceptionHandler::Impl final { ExceptionHandler::ExceptionHandler() = default; ExceptionHandler::~ExceptionHandler() = default; -void ExceptionHandler::Register(BlockOfCode&) { +#if defined(MCL_ARCHITECTURE_X86_64) +void ExceptionHandler::Register(X64::BlockOfCode&) { // Do nothing } +#elif defined(MCL_ARCHITECTURE_ARM64) +void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) { + // Do nothing +} +#else +# error "Invalid architecture" +#endif bool ExceptionHandler::SupportsFastmem() const noexcept { return false; @@ -25,4 +33,4 @@ void ExceptionHandler::SetFastmemCallback(std::function) { // Do nothing } -} // namespace Dynarmic::Backend::X64 +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/backend/exception_handler_posix.cpp new file mode 100644 index 00000000..07d6e6e8 --- /dev/null +++ b/src/dynarmic/backend/exception_handler_posix.cpp @@ -0,0 +1,294 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2019 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/backend/exception_handler.h" + +#ifdef __APPLE__ +# include +# include +#else +# include +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(MCL_ARCHITECTURE_X86_64) +# include "dynarmic/backend/x64/block_of_code.h" +#elif defined(MCL_ARCHITECTURE_ARM64) +# include + +# include "dynarmic/backend/arm64/abi.h" +#else +# error "Invalid architecture" +#endif + +namespace Dynarmic::Backend { + +namespace { + +struct CodeBlockInfo { + u64 code_begin, code_end; + std::function cb; +}; + +class SigHandler { +public: + SigHandler(); + ~SigHandler(); + + void AddCodeBlock(CodeBlockInfo info); + void RemoveCodeBlock(u64 host_pc); + + bool SupportsFastmem() const { return supports_fast_mem; } + +private: + auto FindCodeBlockInfo(u64 host_pc) { + return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](const auto& x) { return x.code_begin <= host_pc && x.code_end > host_pc; }); + } + + bool supports_fast_mem = true; + + void* signal_stack_memory = nullptr; + + std::vector code_block_infos; + std::mutex code_block_infos_mutex; + + struct sigaction old_sa_segv; + struct sigaction old_sa_bus; + + static void SigAction(int sig, siginfo_t* info, void* raw_context); +}; + +SigHandler sig_handler; + +SigHandler::SigHandler() { + const size_t signal_stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); + + signal_stack_memory = std::malloc(signal_stack_size); + + stack_t signal_stack; + signal_stack.ss_sp = signal_stack_memory; + signal_stack.ss_size = signal_stack_size; + signal_stack.ss_flags = 0; + if (sigaltstack(&signal_stack, nullptr) != 0) { + fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n"); + supports_fast_mem = false; + return; + } + + struct sigaction sa; + sa.sa_handler = nullptr; + sa.sa_sigaction = &SigHandler::SigAction; + sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) { + fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n"); + supports_fast_mem = false; + return; + } +#ifdef __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; + return; + } +#endif +} + +SigHandler::~SigHandler() { + std::free(signal_stack_memory); +} + +void SigHandler::AddCodeBlock(CodeBlockInfo cbi) { + std::lock_guard guard(code_block_infos_mutex); + if (auto iter = FindCodeBlockInfo(cbi.code_begin); iter != code_block_infos.end()) { + code_block_infos.erase(iter); + } + code_block_infos.push_back(cbi); +} + +void SigHandler::RemoveCodeBlock(u64 host_pc) { + std::lock_guard guard(code_block_infos_mutex); + const auto iter = FindCodeBlockInfo(host_pc); + if (iter == code_block_infos.end()) { + return; + } + code_block_infos.erase(iter); +} + +void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { + ASSERT(sig == SIGSEGV || sig == SIGBUS); + +#if defined(MCL_ARCHITECTURE_X86_64) + +# if defined(__APPLE__) +# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext->__ss.__rip) +# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext->__ss.__rsp) +# elif defined(__linux__) +# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext.gregs[REG_RIP]) +# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext.gregs[REG_RSP]) +# elif defined(__FreeBSD__) +# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext.mc_rip) +# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext.mc_rsp) +# else +# error "Unknown platform" +# endif + + { + std::lock_guard guard(sig_handler.code_block_infos_mutex); + + const auto iter = sig_handler.FindCodeBlockInfo(CTX_RIP); + if (iter != sig_handler.code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_RIP); + + CTX_RSP -= sizeof(u64); + *mcl::bit_cast(CTX_RSP) = fc.ret_rip; + CTX_RIP = fc.call_rip; + + return; + } + } + + fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP); + +#elif defined(MCL_ARCHITECTURE_ARM64) + +# if defined(__APPLE__) +# define CTX_PC (((ucontext_t*)raw_context)->uc_mcontext->__ss.__pc) +# define CTX_SP (((ucontext_t*)raw_context)->uc_mcontext->__ss.__sp) +# define CTX_LR (((ucontext_t*)raw_context)->uc_mcontext->__ss.__lr) +# define CTX_X(i) (((ucontext_t*)raw_context)->uc_mcontext->__ss.__x[i]) +# define CTX_Q(i) (((ucontext_t*)raw_context)->uc_mcontext->__ns.__v[i]) +# elif defined(__linux__) +# define CTX_PC (((ucontext_t*)raw_context)->uc_mcontext.pc) +# define CTX_SP (((ucontext_t*)raw_context)->uc_mcontext.sp) +# define CTX_LR (((ucontext_t*)raw_context)->uc_mcontext.regs[30]) +# define CTX_X(i) (((ucontext_t*)raw_context)->uc_mcontext.regs[i]) +# define CTX_Q(i) (fp->vregs[i]) + const auto fp = [raw_context] { + _aarch64_ctx* head = (_aarch64_ctx*)(((ucontext_t*)raw_context)->uc_mcontext.__reserved); + while (head->magic != FPSIMD_MAGIC) { + ASSERT(head->magic && head->size); + head = (_aarch64_ctx*)(((char*)head) + head->size); + } + return (fpsimd_context*)head; + }(); +# elif defined(__FreeBSD__) +# define CTX_PC (((ucontext_t*)raw_context)->uc_mcontext.mc_gpregs.gp_elr) +# define CTX_SP (((ucontext_t*)raw_context)->uc_mcontext.mc_gpregs.gp_sp) +# define CTX_LR (((ucontext_t*)raw_context)->uc_mcontext.mc_gpregs.gp_lr) +# define CTX_X(i) (((ucontext_t*)raw_context)->uc_mcontext.mc_gpregs.gp_x[i]) +# define CTX_Q(i) (((ucontext_t*)raw_context)->uc_mcontext.mc_fpregs.fp_q[i]) +# else +# error "Unknown platform" +# endif + + { + std::lock_guard guard(sig_handler.code_block_infos_mutex); + + const auto iter = sig_handler.FindCodeBlockInfo(CTX_PC); + if (iter != sig_handler.code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_PC); + + CTX_LR = fc.ret_pc; + CTX_PC = fc.call_pc; + + if (fc.load_xscratch0) { + CTX_X(Arm64::Xscratch0.index()) = CTX_X(*fc.load_xscratch0); + } + if (fc.load_xscratch1) { + CTX_X(Arm64::Xscratch1.index()) = CTX_X(*fc.load_xscratch1); + } + if (fc.load_q0) { + CTX_Q(0) = CTX_Q(*fc.load_q0); + } + + return; + } + } + + fmt::print(stderr, "Unhandled {} at pc {:#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; + if (retry_sa->sa_flags & SA_SIGINFO) { + retry_sa->sa_sigaction(sig, info, raw_context); + return; + } + if (retry_sa->sa_handler == SIG_DFL) { + signal(sig, SIG_DFL); + return; + } + if (retry_sa->sa_handler == SIG_IGN) { + return; + } + retry_sa->sa_handler(sig); +} + +} // anonymous namespace + +struct ExceptionHandler::Impl final { + Impl(u64 code_begin_, u64 code_end_) + : code_begin(code_begin_) + , code_end(code_end_) {} + + void SetCallback(std::function cb) { + CodeBlockInfo cbi; + cbi.code_begin = code_begin; + cbi.code_end = code_end; + cbi.cb = cb; + sig_handler.AddCodeBlock(cbi); + } + + ~Impl() { + sig_handler.RemoveCodeBlock(code_begin); + } + +private: + u64 code_begin, code_end; +}; + +ExceptionHandler::ExceptionHandler() = default; +ExceptionHandler::~ExceptionHandler() = default; + +#if defined(MCL_ARCHITECTURE_X86_64) +void ExceptionHandler::Register(X64::BlockOfCode& code) { + const u64 code_begin = mcl::bit_cast(code.getCode()); + const u64 code_end = code_begin + code.GetTotalCodeSize(); + impl = std::make_unique(code_begin, code_end); +} +#elif defined(MCL_ARCHITECTURE_ARM64) +void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) { + const u64 code_begin = mcl::bit_cast(mem.ptr()); + const u64 code_end = code_begin + size; + impl = std::make_unique(code_begin, code_end); +} +#else +# error "Invalid architecture" +#endif + +bool ExceptionHandler::SupportsFastmem() const noexcept { + return static_cast(impl) && sig_handler.SupportsFastmem(); +} + +void ExceptionHandler::SetFastmemCallback(std::function cb) { + impl->SetCallback(cb); +} + +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/backend/x64/emit_x64.h index 2e5d434f..4efec77f 100644 --- a/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/backend/x64/emit_x64.h @@ -19,7 +19,7 @@ #include #include -#include "dynarmic/backend/x64/exception_handler.h" +#include "dynarmic/backend/exception_handler.h" #include "dynarmic/backend/x64/reg_alloc.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/ir/location_descriptor.h" diff --git a/src/dynarmic/backend/x64/exception_handler.h b/src/dynarmic/backend/x64/exception_handler.h deleted file mode 100644 index 0e094eba..00000000 --- a/src/dynarmic/backend/x64/exception_handler.h +++ /dev/null @@ -1,37 +0,0 @@ -/* This file is part of the dynarmic project. - * Copyright (c) 2020 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#pragma once - -#include -#include - -#include - -namespace Dynarmic::Backend::X64 { - -class BlockOfCode; - -struct FakeCall { - u64 call_rip; - u64 ret_rip; -}; - -class ExceptionHandler final { -public: - ExceptionHandler(); - ~ExceptionHandler(); - - void Register(BlockOfCode& code); - - bool SupportsFastmem() const noexcept; - void SetFastmemCallback(std::function cb); - -private: - struct Impl; - std::unique_ptr impl; -}; - -} // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/backend/x64/exception_handler_macos.cpp b/src/dynarmic/backend/x64/exception_handler_macos.cpp index 5991d1c0..763ced7d 100644 --- a/src/dynarmic/backend/x64/exception_handler_macos.cpp +++ b/src/dynarmic/backend/x64/exception_handler_macos.cpp @@ -18,13 +18,15 @@ #include #include +#include "dynarmic/backend/exception_handler.h" #include "dynarmic/backend/x64/block_of_code.h" -#include "dynarmic/backend/x64/exception_handler.h" #define mig_external extern "C" #include "dynarmic/backend/x64/mig/mach_exc_server.h" -namespace Dynarmic::Backend::X64 { +namespace Dynarmic::Backend { + +using namespace Dynarmic::Backend::X64; namespace { @@ -224,4 +226,4 @@ void ExceptionHandler::SetFastmemCallback(std::function cb) { impl->SetCallback(cb); } -} // namespace Dynarmic::Backend::X64 +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/x64/exception_handler_posix.cpp b/src/dynarmic/backend/x64/exception_handler_posix.cpp deleted file mode 100644 index 3a997d95..00000000 --- a/src/dynarmic/backend/x64/exception_handler_posix.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* This file is part of the dynarmic project. - * Copyright (c) 2019 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#include "dynarmic/backend/x64/exception_handler.h" - -#ifdef __APPLE__ -# include -# include -#else -# include -# include -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "dynarmic/backend/x64/block_of_code.h" - -namespace Dynarmic::Backend::X64 { - -namespace { - -struct CodeBlockInfo { - u64 code_begin, code_end; - std::function cb; -}; - -class SigHandler { -public: - SigHandler(); - ~SigHandler(); - - void AddCodeBlock(CodeBlockInfo info); - void RemoveCodeBlock(u64 rip); - - bool SupportsFastmem() const { return supports_fast_mem; } - -private: - auto FindCodeBlockInfo(u64 rip) { - return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](const auto& x) { return x.code_begin <= rip && x.code_end > rip; }); - } - - bool supports_fast_mem = true; - - void* signal_stack_memory = nullptr; - - std::vector code_block_infos; - std::mutex code_block_infos_mutex; - - struct sigaction old_sa_segv; - struct sigaction old_sa_bus; - - static void SigAction(int sig, siginfo_t* info, void* raw_context); -}; - -SigHandler sig_handler; - -SigHandler::SigHandler() { - const size_t signal_stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); - - signal_stack_memory = std::malloc(signal_stack_size); - - stack_t signal_stack; - signal_stack.ss_sp = signal_stack_memory; - signal_stack.ss_size = signal_stack_size; - signal_stack.ss_flags = 0; - if (sigaltstack(&signal_stack, nullptr) != 0) { - fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n"); - supports_fast_mem = false; - return; - } - - struct sigaction sa; - sa.sa_handler = nullptr; - sa.sa_sigaction = &SigHandler::SigAction; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) { - fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n"); - supports_fast_mem = false; - return; - } -#ifdef __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; - return; - } -#endif -} - -SigHandler::~SigHandler() { - std::free(signal_stack_memory); -} - -void SigHandler::AddCodeBlock(CodeBlockInfo cbi) { - std::lock_guard guard(code_block_infos_mutex); - if (auto iter = FindCodeBlockInfo(cbi.code_begin); iter != code_block_infos.end()) { - code_block_infos.erase(iter); - } - code_block_infos.push_back(cbi); -} - -void SigHandler::RemoveCodeBlock(u64 rip) { - std::lock_guard guard(code_block_infos_mutex); - const auto iter = FindCodeBlockInfo(rip); - if (iter == code_block_infos.end()) { - return; - } - code_block_infos.erase(iter); -} - -void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { - ASSERT(sig == SIGSEGV || sig == SIGBUS); - -#if defined(__APPLE__) -# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext->__ss.__rip) -# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext->__ss.__rsp) -#elif defined(__linux__) -# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext.gregs[REG_RIP]) -# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext.gregs[REG_RSP]) -#elif defined(__FreeBSD__) -# define CTX_RIP (((ucontext_t*)raw_context)->uc_mcontext.mc_rip) -# define CTX_RSP (((ucontext_t*)raw_context)->uc_mcontext.mc_rsp) -#else -# error "Unknown platform" -#endif - - { - std::lock_guard guard(sig_handler.code_block_infos_mutex); - - const auto iter = sig_handler.FindCodeBlockInfo(CTX_RIP); - if (iter != sig_handler.code_block_infos.end()) { - FakeCall fc = iter->cb(CTX_RIP); - - CTX_RSP -= sizeof(u64); - *mcl::bit_cast(CTX_RSP) = fc.ret_rip; - CTX_RIP = fc.call_rip; - - return; - } - } - - fmt::print(stderr, "Unhandled {} at rip {:#016x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP); - - struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler.old_sa_segv : &sig_handler.old_sa_bus; - if (retry_sa->sa_flags & SA_SIGINFO) { - retry_sa->sa_sigaction(sig, info, raw_context); - return; - } - if (retry_sa->sa_handler == SIG_DFL) { - signal(sig, SIG_DFL); - return; - } - if (retry_sa->sa_handler == SIG_IGN) { - return; - } - retry_sa->sa_handler(sig); -} - -} // anonymous namespace - -struct ExceptionHandler::Impl final { - Impl(BlockOfCode& code) - : code_begin(mcl::bit_cast(code.getCode())) - , code_end(code_begin + code.GetTotalCodeSize()) {} - - void SetCallback(std::function cb) { - CodeBlockInfo cbi; - cbi.code_begin = code_begin; - cbi.code_end = code_end; - cbi.cb = cb; - sig_handler.AddCodeBlock(cbi); - } - - ~Impl() { - sig_handler.RemoveCodeBlock(code_begin); - } - -private: - u64 code_begin, code_end; -}; - -ExceptionHandler::ExceptionHandler() = default; -ExceptionHandler::~ExceptionHandler() = default; - -void ExceptionHandler::Register(BlockOfCode& code) { - impl = std::make_unique(code); -} - -bool ExceptionHandler::SupportsFastmem() const noexcept { - return static_cast(impl) && sig_handler.SupportsFastmem(); -} - -void ExceptionHandler::SetFastmemCallback(std::function cb) { - impl->SetCallback(cb); -} - -} // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/backend/x64/exception_handler_windows.cpp b/src/dynarmic/backend/x64/exception_handler_windows.cpp index 82479b9c..a7f96433 100644 --- a/src/dynarmic/backend/x64/exception_handler_windows.cpp +++ b/src/dynarmic/backend/x64/exception_handler_windows.cpp @@ -13,8 +13,8 @@ #include #include +#include "dynarmic/backend/exception_handler.h" #include "dynarmic/backend/x64/block_of_code.h" -#include "dynarmic/backend/x64/exception_handler.h" #include "dynarmic/common/safe_ops.h" using UBYTE = u8; @@ -77,7 +77,9 @@ struct UNW_EXCEPTION_INFO { // OPTIONAL ARBITRARY HandlerData; }; -namespace Dynarmic::Backend::X64 { +namespace Dynarmic::Backend { + +using namespace Dynarmic::Backend::X64; struct PrologueInformation { std::vector unwind_code; @@ -259,4 +261,4 @@ void ExceptionHandler::SetFastmemCallback(std::function cb) { impl->SetCallback(cb); } -} // namespace Dynarmic::Backend::X64 +} // namespace Dynarmic::Backend