fix(libc): fix exception matching + foreign exception handling

This commit is contained in:
boykopovar 2026-09-05 20:13:14 +03:00
parent 36c874e296
commit f449ebb636
6 changed files with 189 additions and 94 deletions

View File

@ -1,5 +1,4 @@
#include "exception/Runtime.hpp"
#include <thread>
#include <cstddef>
#include <cxxabi.h>
#include <cstdint>
@ -15,46 +14,8 @@
#include <functional>
#include <unwind.h>
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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char> initialized(bytes[0]);
std::atomic_ref<unsigned char> 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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char>(bytes[0]).store(1, std::memory_order_release);
std::atomic_ref<unsigned char>(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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char>(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;

View File

@ -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"

View File

@ -0,0 +1,44 @@
#include "Runtime.hpp"
#include <thread>
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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char> initialized(bytes[0]);
std::atomic_ref<unsigned char> 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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char>(bytes[0]).store(1, std::memory_order_release);
std::atomic_ref<unsigned char>(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<unsigned char*>(guardObject);
std::atomic_ref<unsigned char>(bytes[1]).store(0, std::memory_order_release);
}
}

View File

@ -3,11 +3,16 @@
namespace LibcException {
inline std::atomic<void(*)()> 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<class Visitor>
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<const __cxxabiv1::__si_class_type_info*>(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<const __cxxabiv1::__vmi_class_type_info*>(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<const unsigned char* const*>(object);
std::memcpy(&offset, vtable + offset, sizeof(offset));
if (location.object) {
auto* vtable = *static_cast<const unsigned char* const*>(location.object);
std::memcpy(&offset, vtable + offset, sizeof(offset));
} else {
next.identity = reinterpret_cast<std::uintptr_t>(base.__base_type);
offset = 0;
}
}
void* adjusted = object ? static_cast<unsigned char*>(object) + offset : nullptr;
Bases(base.__base_type, adjusted, search, depth + 1);
if (location.object) next.object = static_cast<unsigned char*>(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<const __cxxabiv1::__pbase_type_info*>(caught->__pointee),
static_cast<const __cxxabiv1::__pbase_type_info*>(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<const __cxxabiv1::__pointer_type_info*>(caught);
auto* t = static_cast<const __cxxabiv1::__pointer_type_info*>(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<const __cxxabiv1::__pointer_type_info*>(caught),
static_cast<const __cxxabiv1::__pointer_type_info*>(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<const __cxxabiv1::__pointer_to_member_type_info*>(caught);
auto* t = static_cast<const __cxxabiv1::__pointer_to_member_type_info*>(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<std::uintptr_t>(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<const std::uintptr_t* const*>(source);
auto* complete = const_cast<unsigned char*>(static_cast<const unsigned char*>(source)) + static_cast<std::intptr_t>(vtable[-2]);
auto* dynamicType = reinterpret_cast<const std::type_info*>(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) {

View File

@ -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<const ExceptionVtable*>(object->vtable) - 0;
auto* table = static_cast<const ExceptionVtable*>(object->vtable);
auto* complete = reinterpret_cast<const ExceptionVtable*>(reinterpret_cast<const unsigned char*>(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); }

View File

@ -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<Word>(__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<std::uintptr_t>(__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;