From a4c519b262e8029c62d672ff478fe4f2d77d451f Mon Sep 17 00:00:00 2001 From: owner Date: Sat, 26 Sep 2026 13:01:53 -0600 Subject: [PATCH] fix(exceptions): interpose libstdc++ ABI on Linux so the project's own unwinder drives it On native Linux these PRX shared libraries and their test executables dynamically link real libstdc++/libgcc, so a plain throw went through the system's __cxa_throw/_Unwind_RaiseException. That still invoked this project's own __gxx_personality_v0_nid_postfix (the CIE's personality pointer is a raw function address, agnostic to which unwinder is walking the stack), but handed it libgcc's incompatible private _Unwind_Context layout, corrupting every field Personality.cpp reads and aborting with no exception message. Fix: OwnPersonality() now recognises the bare __gxx_personality_v0 wrapper on Linux too (previously Windows-only), and Exports.cpp exports the real ABI names (__cxa_throw, __cxa_begin_catch/end_catch, __cxa_rethrow, __cxa_allocate/free_exception, __cxa_call_terminate, __cxa_get_exception_ptr, __cxa_current_exception_type, __cxa_init_primary_exception, the std:: terminate/uncaught_exception(s) mangled names, and the core _Unwind_* entry points) via the existing GCC_GLOBAL_ALIAS assembler-alias mechanism, so ELF symbol interposition makes this project's own implementation win process-wide over libgcc_s.so.1/libstdc++.so.6. __cxa_init_primary_exception is newly implemented; GCC 13's inline std::make_exception_ptr needs it and nothing provided it before. Fixes 7 previously-aborting tests: guest_rendering_wait, guest_buffer_reuse, guest_shader_link, guest_system_exit_parameters, guest_once, guest_memory, guest_search. Co-Authored-By: Claude Sonnet 5 --- core/libs/prx/libc/src/exception/Exports.cpp | 22 +++++++++++++++++--- core/libs/prx/libc/src/exception/Runtime.cpp | 12 +++++++++++ core/libs/prx/libc/src/exception/Unwind.cpp | 4 ++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/core/libs/prx/libc/src/exception/Exports.cpp b/core/libs/prx/libc/src/exception/Exports.cpp index 2c7f8be9df..802fad44a8 100644 --- a/core/libs/prx/libc/src/exception/Exports.cpp +++ b/core/libs/prx/libc/src/exception/Exports.cpp @@ -20,9 +20,25 @@ GCC_GLOBAL_ALIAS(__cxa_end_catch_nid_no_patch_cut, __cxa_end_catch_nid_postfix); GCC_GLOBAL_ALIAS(__cxa_rethrow_nid_no_patch_cut, __cxa_rethrow_nid_postfix); GCC_GLOBAL_ALIAS(__gxx_personality_v0_nid_no_patch_cut, __gxx_personality_v0_nid_postfix); GCC_GLOBAL_ALIAS(_Unwind_Resume_nid_no_patch_cut, _Unwind_Resume_nid_postfix); -GCC_LOCAL_ALIAS(__cxa_free_exception, __cxa_free_exception_nid_postfix); -GCC_LOCAL_ALIAS(_ZSt9terminatev, _ZSt9terminatev_nid_postfix); -GCC_LOCAL_ALIAS(__cxa_call_terminate, __cxa_call_terminate_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_free_exception, __cxa_free_exception_nid_postfix); +GCC_GLOBAL_ALIAS(_ZSt9terminatev, _ZSt9terminatev_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_call_terminate, __cxa_call_terminate_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_allocate_exception, __cxa_allocate_exception_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_throw, __cxa_throw_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_init_primary_exception, __cxa_init_primary_exception_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_begin_catch, __cxa_begin_catch_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_end_catch, __cxa_end_catch_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_rethrow, __cxa_rethrow_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_get_exception_ptr, __cxa_get_exception_ptr_nid_postfix); +GCC_GLOBAL_ALIAS(__cxa_current_exception_type, __cxa_current_exception_type_nid_postfix); +GCC_GLOBAL_ALIAS(_ZSt13set_terminatePFvvE, _ZSt13set_terminatePFvvE_nid_postfix); +GCC_GLOBAL_ALIAS(_ZSt13get_terminatev, _ZSt13get_terminatev_nid_postfix); +GCC_GLOBAL_ALIAS(_ZSt18uncaught_exceptionv, __cxa_uncaught_exception_nid_postfix); +GCC_GLOBAL_ALIAS(_ZSt19uncaught_exceptionsv, __cxa_uncaught_exceptions_nid_postfix); +GCC_GLOBAL_ALIAS(_Unwind_Resume, _Unwind_Resume_nid_postfix); +GCC_GLOBAL_ALIAS(_Unwind_RaiseException, _Unwind_RaiseException_nid_postfix); +GCC_GLOBAL_ALIAS(_Unwind_Resume_or_Rethrow, _Unwind_Resume_or_Rethrow_nid_postfix); +GCC_GLOBAL_ALIAS(_Unwind_DeleteException, _Unwind_DeleteException_nid_postfix); #ifdef _WIN32 extern "C" { diff --git a/core/libs/prx/libc/src/exception/Runtime.cpp b/core/libs/prx/libc/src/exception/Runtime.cpp index 6e1c52cffb..90bc5c023f 100644 --- a/core/libs/prx/libc/src/exception/Runtime.cpp +++ b/core/libs/prx/libc/src/exception/Runtime.cpp @@ -221,6 +221,18 @@ void APS5_VABI __cxa_free_exception_nid_postfix(void* object) { InvokeTerminate(header->terminate); } +LibcException::Header* __cxa_init_primary_exception_nid_postfix(void* object, std::type_info* type, void (*destructor)(void*)) { + using namespace LibcException; + auto* header = FromObject(object); + header->type = type; + header->destructor = destructor; + header->terminate = terminateHandler.load(std::memory_order_acquire); + header->adjusted = object; + header->unwind.exception_class = PrimaryClass; + header->unwind.exception_cleanup = Cleanup; + return header; +} + void* APS5_VABI __cxa_begin_catch_nid_postfix(void* exception) { using namespace LibcException; auto* unwind = static_cast<_Unwind_Exception*>(exception); diff --git a/core/libs/prx/libc/src/exception/Unwind.cpp b/core/libs/prx/libc/src/exception/Unwind.cpp index 371803ac8c..6accabc61d 100644 --- a/core/libs/prx/libc/src/exception/Unwind.cpp +++ b/core/libs/prx/libc/src/exception/Unwind.cpp @@ -8,7 +8,7 @@ #if defined(__linux__) || defined(_WIN32) -#ifdef _WIN32 +#if defined(_WIN32) || defined(__linux__) extern "C" _Unwind_Reason_Code __gxx_personality_v0(int, _Unwind_Action, std::uint64_t, _Unwind_Exception*, _Unwind_Context*); #endif @@ -23,7 +23,7 @@ bool OwnPersonality(Word personality) { } #endif if (personality == reinterpret_cast(__gxx_personality_v0_nid_postfix)) return true; -#ifdef _WIN32 +#if defined(_WIN32) || defined(__linux__) if (personality == reinterpret_cast(__gxx_personality_v0)) return true; #endif return false;