diff --git a/core/libs/prx/libc/src/CxxAbiSupport.cpp b/core/libs/prx/libc/src/CxxAbiSupport.cpp index 09bd9e680..63f934a8e 100644 --- a/core/libs/prx/libc/src/CxxAbiSupport.cpp +++ b/core/libs/prx/libc/src/CxxAbiSupport.cpp @@ -1,5 +1,4 @@ #include "exception/Runtime.hpp" -#include #include #include #include @@ -15,46 +14,8 @@ #include #include -namespace LibcGuard { -thread_local std::uint64_t* active[64] {}; -thread_local std::size_t depth {}; -} - extern "C" { -int __cxa_guard_acquire_nid_postfix(std::uint64_t* guardObject) { - auto* bytes = reinterpret_cast(guardObject); - std::atomic_ref initialized(bytes[0]); - std::atomic_ref lock(bytes[1]); - if (initialized.load(std::memory_order_acquire)) return 0; - for (std::size_t i = 0; i < LibcGuard::depth; ++i) - if (LibcGuard::active[i] == guardObject) LibcException::Terminate(); - for (;;) { - unsigned char expected = 0; - if (lock.compare_exchange_weak(expected, 1, std::memory_order_acquire)) break; - if (initialized.load(std::memory_order_acquire)) return 0; - std::this_thread::yield(); - } - if (initialized.load(std::memory_order_acquire)) { lock.store(0, std::memory_order_release); return 0; } - if (LibcGuard::depth == 64) LibcException::Terminate(); - LibcGuard::active[LibcGuard::depth++] = guardObject; - return 1; -} - -void __cxa_guard_release_nid_postfix(std::uint64_t* guardObject) { - if (!LibcGuard::depth || LibcGuard::active[LibcGuard::depth - 1] != guardObject) LibcException::Terminate(); - --LibcGuard::depth; - auto* bytes = reinterpret_cast(guardObject); - std::atomic_ref(bytes[0]).store(1, std::memory_order_release); - std::atomic_ref(bytes[1]).store(0, std::memory_order_release); -} -void __cxa_guard_abort_nid_postfix(std::uint64_t* guardObject) { - if (!LibcGuard::depth || LibcGuard::active[LibcGuard::depth - 1] != guardObject) LibcException::Terminate(); - --LibcGuard::depth; - auto* bytes = reinterpret_cast(guardObject); - std::atomic_ref(bytes[1]).store(0, std::memory_order_release); -} - void* __cxa_demangle_nid_postfix(const char* mangled, char* buf, std::size_t* len, int* status) { (void)mangled; (void)buf; (void)len; if (status) *status = -2; diff --git a/core/libs/prx/libc/src/exception/Exports.cpp b/core/libs/prx/libc/src/exception/Exports.cpp index a4aa368f5..1a2e26cad 100644 --- a/core/libs/prx/libc/src/exception/Exports.cpp +++ b/core/libs/prx/libc/src/exception/Exports.cpp @@ -1,10 +1,13 @@ #include "Unwind.cpp" #include "Runtime.cpp" -#include "Personality.cpp" #include "StandardExceptions.cpp" #include "ArraySupport.cpp" +#include "GuardSupport.cpp" + +extern "C" [[noreturn]] __attribute__((visibility("hidden"))) void LibcRuntimeAssertion(const char*, int, const char*, const char*) { std::abort(); } asm( +".local _ZSt21__glibcxx_assert_failPKciS0_S0_\n.set _ZSt21__glibcxx_assert_failPKciS0_S0_,LibcRuntimeAssertion\n" ".local __cxa_allocate_exception\n.set __cxa_allocate_exception,__cxa_allocate_exception_nid_postfix\n" ".local __cxa_free_exception\n.set __cxa_free_exception,__cxa_free_exception_nid_postfix\n" ".local __cxa_throw\n.set __cxa_throw,__cxa_throw_nid_postfix\n" diff --git a/core/libs/prx/libc/src/exception/GuardSupport.cpp b/core/libs/prx/libc/src/exception/GuardSupport.cpp new file mode 100644 index 000000000..1b6967cf9 --- /dev/null +++ b/core/libs/prx/libc/src/exception/GuardSupport.cpp @@ -0,0 +1,44 @@ +#include "Runtime.hpp" +#include + +namespace LibcGuard { +thread_local std::uint64_t* active[64] {}; +thread_local std::size_t depth {}; +} + +extern "C" { + +int __cxa_guard_acquire_nid_postfix(std::uint64_t* guardObject) { + auto* bytes = reinterpret_cast(guardObject); + std::atomic_ref initialized(bytes[0]); + std::atomic_ref lock(bytes[1]); + if (initialized.load(std::memory_order_acquire)) return 0; + for (std::size_t i = 0; i < LibcGuard::depth; ++i) + if (LibcGuard::active[i] == guardObject) LibcException::Terminate(); + for (;;) { + unsigned char expected = 0; + if (lock.compare_exchange_weak(expected, 1, std::memory_order_acquire)) break; + if (initialized.load(std::memory_order_acquire)) return 0; + std::this_thread::yield(); + } + if (initialized.load(std::memory_order_acquire)) { lock.store(0, std::memory_order_release); return 0; } + if (LibcGuard::depth == 64) LibcException::Terminate(); + LibcGuard::active[LibcGuard::depth++] = guardObject; + return 1; +} + +void __cxa_guard_release_nid_postfix(std::uint64_t* guardObject) { + if (!LibcGuard::depth || LibcGuard::active[LibcGuard::depth - 1] != guardObject) LibcException::Terminate(); + --LibcGuard::depth; + auto* bytes = reinterpret_cast(guardObject); + std::atomic_ref(bytes[0]).store(1, std::memory_order_release); + std::atomic_ref(bytes[1]).store(0, std::memory_order_release); +} +void __cxa_guard_abort_nid_postfix(std::uint64_t* guardObject) { + if (!LibcGuard::depth || LibcGuard::active[LibcGuard::depth - 1] != guardObject) LibcException::Terminate(); + --LibcGuard::depth; + auto* bytes = reinterpret_cast(guardObject); + std::atomic_ref(bytes[1]).store(0, std::memory_order_release); +} + +} diff --git a/core/libs/prx/libc/src/exception/Runtime.cpp b/core/libs/prx/libc/src/exception/Runtime.cpp index 8ea4aabb9..8d7b55e0b 100644 --- a/core/libs/prx/libc/src/exception/Runtime.cpp +++ b/core/libs/prx/libc/src/exception/Runtime.cpp @@ -3,11 +3,16 @@ namespace LibcException { inline std::atomic terminateHandler {std::abort}; -[[noreturn]] void Terminate() { - auto handler = terminateHandler.load(std::memory_order_acquire); +[[noreturn]] void InvokeTerminate(void (*handler)()) { try { if (handler) handler(); } catch (...) {} std::abort(); } +[[noreturn]] void Terminate() { InvokeTerminate(terminateHandler.load(std::memory_order_acquire)); } + +_Unwind_Exception* UnwindOf(Header* header) { + return Native(header->unwind.exception_class) ? &header->unwind : reinterpret_cast<_Unwind_Exception*>(header->landing); +} +void DeleteForeignHeader(Header* header) { header->~Header(); std::free(header); } void Release(void* object) { if (!object) return; @@ -46,34 +51,74 @@ struct Search { unsigned count {}; }; -void Bases(const std::type_info* type, void* object, Search& search, unsigned depth = 0) { - if (depth > 128 || !type) return; - if (Equal(type, search.wanted)) { - if (!search.count) { search.found = object; search.count = 1; } - else if (search.found != object) search.count = 2; - return; - } +struct BaseLocation { + void* object; + std::uintptr_t identity; +}; + +template +void VisitBases(const std::type_info* type, BaseLocation location, bool publicPath, Visitor& visitor, unsigned depth = 0) { + if (!type) return; + if (depth > 128) Terminate(); + visitor(type, location, publicPath); const char* kind = Kind(type); if (std::strcmp(kind, "N10__cxxabiv120__si_class_type_infoE") == 0) { auto* si = static_cast(type); - Bases(si->__base_type, object, search, depth + 1); + VisitBases(si->__base_type, location, publicPath, visitor, depth + 1); } else if (std::strcmp(kind, "N10__cxxabiv121__vmi_class_type_infoE") == 0) { auto* vmi = static_cast(type); for (unsigned i = 0; i < vmi->__base_count; ++i) { const auto& base = vmi->__base_info[i]; - if (!(base.__offset_flags & 2)) continue; auto offset = base.__offset_flags >> 8; + BaseLocation next = location; if (base.__offset_flags & 1) { - if (!object) continue; - auto* vtable = *static_cast(object); - std::memcpy(&offset, vtable + offset, sizeof(offset)); + if (location.object) { + auto* vtable = *static_cast(location.object); + std::memcpy(&offset, vtable + offset, sizeof(offset)); + } else { + next.identity = reinterpret_cast(base.__base_type); + offset = 0; + } } - void* adjusted = object ? static_cast(object) + offset : nullptr; - Bases(base.__base_type, adjusted, search, depth + 1); + if (location.object) next.object = static_cast(location.object) + offset; + else next.identity += offset; + VisitBases(base.__base_type, next, publicPath && (base.__offset_flags & 2), visitor, depth + 1); } } } +void Bases(const std::type_info* type, void* object, Search& search) { + std::uintptr_t identity = 0; + auto visitor = [&](const std::type_info* candidate, BaseLocation location, bool publicPath) { + if (!publicPath || !Equal(candidate, search.wanted)) return; + if (!search.count) { search.found = location.object; identity = location.identity; search.count = 1; } + else if (search.found != location.object || identity != location.identity) search.count = 2; + }; + VisitBases(type, {object, 0}, true, visitor); +} + +bool PointerMatch(const __cxxabiv1::__pbase_type_info* caught, const __cxxabiv1::__pbase_type_info* thrown, + void*& object, unsigned depth, bool constPath) { + if (depth > 64) return false; + unsigned added = (caught->__flags & 7) & ~(thrown->__flags & 7); + if (((thrown->__flags & 7) & ~(caught->__flags & 7)) || (depth && added && !constPath)) return false; + if ((caught->__flags & 0x60) & ~(thrown->__flags & 0x60)) return false; + if (Equal(caught->__pointee, thrown->__pointee)) return true; + if (std::strcmp(Kind(caught->__pointee), "N10__cxxabiv119__pointer_type_infoE") == 0 && + std::strcmp(Kind(thrown->__pointee), "N10__cxxabiv119__pointer_type_infoE") == 0) + return PointerMatch(static_cast(caught->__pointee), + static_cast(thrown->__pointee), object, + depth + 1, constPath && (caught->__flags & 1)); + if (depth) return false; + if (std::strcmp(caught->__pointee->name(), "v") == 0 && + std::strcmp(Kind(thrown->__pointee), "N10__cxxabiv120__function_type_infoE") != 0) return true; + Search search {caught->__pointee}; + Bases(thrown->__pointee, object, search); + if (search.count != 1) return false; + object = search.found; + return true; +} + bool Match(const std::type_info* caught, const std::type_info* thrown, void*& object) { if (!caught || Equal(caught, thrown)) return true; if (!thrown) return false; @@ -81,14 +126,18 @@ bool Match(const std::type_info* caught, const std::type_info* thrown, void*& ob const char* thrownKind = Kind(thrown); if (std::strcmp(caughtKind, "N10__cxxabiv119__pointer_type_infoE") == 0 && std::strcmp(thrownKind, "N10__cxxabiv119__pointer_type_infoE") == 0) { - auto* c = static_cast(caught); - auto* t = static_cast(thrown); - if ((t->__flags & 7) & ~(c->__flags & 7)) return false; - if (std::strcmp(c->__pointee->name(), "v") == 0 && std::strcmp(Kind(t->__pointee), "N10__cxxabiv120__function_type_infoE") != 0) return true; - Search search {c->__pointee}; - Bases(t->__pointee, object, search); - if (search.count == 1) { object = search.found; return true; } - return false; + return PointerMatch(static_cast(caught), + static_cast(thrown), object, 0, true); + } + if (std::strcmp(caughtKind, "N10__cxxabiv119__pointer_type_infoE") == 0 && std::strcmp(thrown->name(), "Dn") == 0) { + object = nullptr; + return true; + } + if (std::strcmp(caughtKind, "N10__cxxabiv129__pointer_to_member_type_infoE") == 0 && + std::strcmp(thrownKind, "N10__cxxabiv129__pointer_to_member_type_infoE") == 0) { + auto* c = static_cast(caught); + auto* t = static_cast(thrown); + return Equal(c->__context, t->__context) && PointerMatch(c, t, object, 0, true); } Search search {caught}; Bases(thrown, object, search); @@ -125,16 +174,29 @@ void __cxa_free_exception_nid_postfix(void* object) { header->unwind.exception_cleanup = Cleanup; ++globals.uncaught; _Unwind_RaiseException_nid_postfix(&header->unwind); - Terminate(); + __cxa_begin_catch_nid_postfix(&header->unwind); + InvokeTerminate(header->terminate); } void* __cxa_begin_catch_nid_postfix(void* exception) { using namespace LibcException; auto* unwind = static_cast<_Unwind_Exception*>(exception); - if (!unwind || !Native(unwind->exception_class)) Terminate(); - auto* header = FromUnwind(unwind); + if (!unwind) Terminate(); + Header* header; + if (Native(unwind->exception_class)) { + header = FromUnwind(unwind); + if (globals.uncaught) --globals.uncaught; + } else if (globals.caught && UnwindOf(globals.caught) == unwind) { + header = globals.caught; + } else { + void* storage = std::malloc(sizeof(Header)); + if (!storage) Terminate(); + header = new (storage) Header; + header->unwind.exception_class = unwind->exception_class; + header->landing = reinterpret_cast(unwind); + header->adjusted = unwind + 1; + } header->handlers = header->handlers < 0 ? -header->handlers + 1 : header->handlers + 1; - if (globals.uncaught) --globals.uncaught; if (globals.caught != header) { header->next = globals.caught; globals.caught = header; } return header->adjusted; } @@ -144,10 +206,15 @@ void __cxa_end_catch_nid_postfix() { auto* header = globals.caught; if (!header) return; if (header->handlers < 0) { - if (++header->handlers == 0) globals.caught = header->next; + if (++header->handlers == 0) { + globals.caught = header->next; + if (!Native(header->unwind.exception_class)) DeleteForeignHeader(header); + } } else if (--header->handlers == 0) { globals.caught = header->next; - _Unwind_DeleteException_nid_postfix(&header->unwind); + bool foreign = !Native(header->unwind.exception_class); + _Unwind_DeleteException_nid_postfix(UnwindOf(header)); + if (foreign) DeleteForeignHeader(header); } } @@ -156,17 +223,19 @@ void __cxa_end_catch_nid_postfix() { auto* header = globals.caught; if (!header) Terminate(); header->handlers = -header->handlers; - ++globals.uncaught; - _Unwind_RaiseException_nid_postfix(&header->unwind); - Terminate(); + if (Native(header->unwind.exception_class)) ++globals.uncaught; + _Unwind_RaiseException_nid_postfix(UnwindOf(header)); + __cxa_begin_catch_nid_postfix(UnwindOf(header)); + InvokeTerminate(header->terminate ? header->terminate : terminateHandler.load()); } void* __cxa_get_exception_ptr_nid_postfix(void* exception) { - return LibcException::FromUnwind(static_cast<_Unwind_Exception*>(exception))->adjusted; + auto* unwind = static_cast<_Unwind_Exception*>(exception); + return LibcException::Native(unwind->exception_class) ? LibcException::FromUnwind(unwind)->adjusted : unwind + 1; } std::type_info* __cxa_current_exception_type_nid_postfix() { using namespace LibcException; - return globals.caught ? Primary(globals.caught)->type : nullptr; + return globals.caught && Native(globals.caught->unwind.exception_class) ? Primary(globals.caught)->type : nullptr; } void* __cxa_get_globals_nid_postfix() { return &LibcException::globals; } void* __cxa_get_globals_fast_nid_postfix() { return &LibcException::globals; } @@ -187,7 +256,7 @@ void __cxa_increment_exception_refcount_nid_postfix(void* object) { void __cxa_decrement_exception_refcount_nid_postfix(void* object) { LibcException::Release(object); } void* __cxa_current_primary_exception_nid_postfix() { using namespace LibcException; - if (!globals.caught) return nullptr; + if (!globals.caught || !Native(globals.caught->unwind.exception_class)) return nullptr; void* object = Primary(globals.caught) + 1; __cxa_increment_exception_refcount_nid_postfix(object); return object; @@ -214,7 +283,8 @@ void __cxa_rethrow_primary_exception_nid_postfix(void* object) { __cxa_increment_exception_refcount_nid_postfix(object); ++globals.uncaught; _Unwind_RaiseException_nid_postfix(&header->unwind); - Terminate(); + __cxa_begin_catch_nid_postfix(&header->unwind); + InvokeTerminate(header->terminate); } void* __dynamic_cast_nid_postfix(const void* source, const __cxxabiv1::__class_type_info* sourceType, @@ -224,15 +294,29 @@ void* __dynamic_cast_nid_postfix(const void* source, const __cxxabiv1::__class_t auto* vtable = *static_cast(source); auto* complete = const_cast(static_cast(source)) + static_cast(vtable[-2]); auto* dynamicType = reinterpret_cast(vtable[-1]); - Search target {destinationType}; - Bases(dynamicType, complete, target); - if (target.count != 1) return nullptr; - Search downcast {sourceType}; - Bases(destinationType, target.found, downcast); - if (downcast.count == 1 && downcast.found == source) return target.found; - Search publicSource {sourceType}; - Bases(dynamicType, complete, publicSource); - return publicSource.count == 1 && publicSource.found == source ? target.found : nullptr; + Search downcastTarget {destinationType}; + auto visitor = [&](const std::type_info* candidate, BaseLocation location, bool) { + if (!Equal(candidate, destinationType)) return; + bool containsSource = false; + auto sourceVisitor = [&](const std::type_info* base, BaseLocation baseLocation, bool publicPath) { + if (publicPath && Equal(base, sourceType) && baseLocation.object == source) containsSource = true; + }; + VisitBases(candidate, location, true, sourceVisitor); + if (!containsSource) return; + if (!downcastTarget.count) { downcastTarget.found = location.object; downcastTarget.count = 1; } + else if (downcastTarget.found != location.object) downcastTarget.count = 2; + }; + VisitBases(dynamicType, {complete, 0}, true, visitor); + if (downcastTarget.count == 1) return downcastTarget.found; + bool sourceIsPublic = false; + auto sourceVisitor = [&](const std::type_info* candidate, BaseLocation location, bool publicPath) { + if (publicPath && Equal(candidate, sourceType) && location.object == source) sourceIsPublic = true; + }; + VisitBases(dynamicType, {complete, 0}, true, sourceVisitor); + if (!sourceIsPublic) return nullptr; + Search publicTarget {destinationType}; + Bases(dynamicType, complete, publicTarget); + return publicTarget.count == 1 ? publicTarget.found : nullptr; } [[noreturn]] void __cxa_call_terminate_nid_postfix(void* exception) { diff --git a/core/libs/prx/libc/src/exception/StandardExceptions.cpp b/core/libs/prx/libc/src/exception/StandardExceptions.cpp index c0fce7dc4..ae88b943f 100644 --- a/core/libs/prx/libc/src/exception/StandardExceptions.cpp +++ b/core/libs/prx/libc/src/exception/StandardExceptions.cpp @@ -72,9 +72,16 @@ void DeletePlain(ExceptionObject* object) { std::free(object); } void DestroyMessage(ExceptionObject* object) { ReleaseMessage(object->message); object->message = nullptr; } void DeleteMessage(ExceptionObject* object) { DestroyMessage(object); std::free(object); } const char* PlainWhat(const ExceptionObject* object) { - auto* table = static_cast(object->vtable) - 0; + auto* table = static_cast(object->vtable); auto* complete = reinterpret_cast(reinterpret_cast(table) - offsetof(ExceptionVtable, destroy)); - return complete->type->name; + const char* name = complete->type->name; + if (std::strcmp(name, "St9exception") == 0) return "std::exception"; + if (std::strcmp(name, "St8bad_cast") == 0) return "std::bad_cast"; + if (std::strcmp(name, "St10bad_typeid") == 0) return "std::bad_typeid"; + if (std::strcmp(name, "St9bad_alloc") == 0) return "std::bad_alloc"; + if (std::strcmp(name, "St20bad_array_new_length") == 0) return "std::bad_array_new_length"; + if (std::strcmp(name, "St17bad_function_call") == 0) return "std::bad_function_call"; + return name; } const char* MessageWhat(const ExceptionObject* object) { return object->message ? object->message : ""; } void Construct(ExceptionObject* object, const ExceptionVtable& table, const char* message) { @@ -235,8 +242,6 @@ void _ZNSt12system_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { void _ZNSt12system_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void _ZNSt12system_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } const char* _ZNKSt12system_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self) { return LibcException::MessageWhat(self); } -void _ZNSt12system_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVSt12system_error_nid_postfix, message); } -void _ZNSt12system_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVSt12system_error_nid_postfix, message); } void _ZNSt12system_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { LibcException::Copy(self, source, _ZTVSt12system_error_nid_postfix); } void _ZNSt12system_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { LibcException::Copy(self, source, _ZTVSt12system_error_nid_postfix); } LibcException::ExceptionObject* _ZNSt12system_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } @@ -247,8 +252,6 @@ void _ZNSt11regex_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { void _ZNSt11regex_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void _ZNSt11regex_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } const char* _ZNKSt11regex_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self) { return LibcException::MessageWhat(self); } -void _ZNSt11regex_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVSt11regex_error_nid_postfix, message); } -void _ZNSt11regex_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVSt11regex_error_nid_postfix, message); } void _ZNSt11regex_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { LibcException::Copy(self, source, _ZTVSt11regex_error_nid_postfix); } void _ZNSt11regex_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { LibcException::Copy(self, source, _ZTVSt11regex_error_nid_postfix); } LibcException::ExceptionObject* _ZNSt11regex_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } @@ -259,8 +262,6 @@ void _ZNSt8ios_base7failureD1Ev_nid_postfix(LibcException::ExceptionObject* self void _ZNSt8ios_base7failureD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void _ZNSt8ios_base7failureD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } const char* _ZNKSt8ios_base7failure4whatEv_nid_postfix(const LibcException::ExceptionObject* self) { return LibcException::MessageWhat(self); } -void _ZNSt8ios_base7failureC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVNSt8ios_base7failureE_nid_postfix, message); } -void _ZNSt8ios_base7failureC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message) { LibcException::Construct(self, _ZTVNSt8ios_base7failureE_nid_postfix, message); } [[noreturn]] void __cxa_bad_cast_nid_postfix() { LibcException::ThrowPlain(_ZTVSt8bad_cast_nid_postfix); } [[noreturn]] void __cxa_bad_typeid_nid_postfix() { LibcException::ThrowPlain(_ZTVSt10bad_typeid_nid_postfix); } diff --git a/core/libs/prx/libc/src/exception/Unwind.cpp b/core/libs/prx/libc/src/exception/Unwind.cpp index a78fe9e93..939f84818 100644 --- a/core/libs/prx/libc/src/exception/Unwind.cpp +++ b/core/libs/prx/libc/src/exception/Unwind.cpp @@ -303,6 +303,7 @@ _Unwind_Reason_Code PhaseTwo(_Unwind_Context context, _Unwind_Exception* excepti if (result != _URC_NO_REASON) return result; } else if (context.cfa == exception->private_2) actions = _Unwind_Action(actions | _UA_HANDLER_FRAME); if (frame.personality) { + if (frame.personality != reinterpret_cast(__gxx_personality_v0_nid_postfix)) return _URC_FATAL_PHASE2_ERROR; auto result = __gxx_personality_v0_nid_postfix(1, actions, exception->exception_class, exception, &context); if (result == _URC_INSTALL_CONTEXT) LibcRestoreRegisters(context.registers); if (result != _URC_CONTINUE_UNWIND) return _URC_FATAL_PHASE2_ERROR; @@ -331,6 +332,7 @@ _Unwind_Reason_Code _Unwind_RaiseException_nid_postfix(_Unwind_Exception* except LibcUnwind::Frame frame; LibcUnwind::Rules rules; if (!LibcUnwind::GetRules(context, frame, rules)) return _URC_END_OF_STACK; if (frame.personality) { + if (frame.personality != reinterpret_cast(__gxx_personality_v0_nid_postfix)) return _URC_FATAL_PHASE1_ERROR; auto result = __gxx_personality_v0_nid_postfix(1, _UA_SEARCH_PHASE, exception->exception_class, exception, &context); if (result == _URC_HANDLER_FOUND) { exception->private_2 = context.cfa;