5export module zxfoundation.base.cxxrtse.cxxabi;
6import zxfoundation.base.types;
7import zxfoundation.sys.syschk.core;
8import zxfoundation.sys.printk.core;
9import zxfoundation.sync.qspinlock.core;
10import arch.s390x.cpu.processor;
11import arch.s390x.cpu.clock;
12import arch.s390x.cpu.sync;
13import lib.static_vector;
17using zxfoundation::sys::printk::pinfo;
21constexpr usize CXA_ATEXIT_MAX = 256;
24 void (*destructor)(
void*);
29lib::static_vector<AtExitEntry, CXA_ATEXIT_MAX> g_atexit_table{};
31alignas(4) zxfoundation::sync::qspinlock::qspinlock g_atexit_lock{};
32auto atexit_lock()
noexcept ->
void { g_atexit_lock.lock(); }
33auto atexit_unlock()
noexcept ->
void { g_atexit_lock.unlock(); }
39extern void (*__init_array_start[])()
__attribute__((weak));
41extern void (*__init_array_end[])()
__attribute__((weak));
43extern void (*__fini_array_start[])()
__attribute__((weak));
45extern void (*__fini_array_end[])()
__attribute__((weak));
47extern void *__dso_handle
__attribute__((weak));
53auto __cxa_atexit(
void (*destructor)(
void*),
void* obj,
void* dso) ->
int {
54 if (!destructor)
return 0;
56 const bool ok = g_atexit_table.push_back({ destructor, obj, dso }).has_value();
58 if (!ok) [[unlikely]] zxfoundation::sys::syschk::syschk_fatal(lib::kernel_error::from_generic(lib::generic_error::internal_error),
59 "cxxrtse: __cxa_atexit: oom trying to handle atexit.");
63auto __cxa_finalize(
void* dso) ->
void {
65 const usize snap = g_atexit_table.size();
68 for (
long i =
static_cast<
long>(snap) - 1; i >= 0; --i) {
70 AtExitEntry e = g_atexit_table[
static_cast<usize>(i)];
71 if (!e.destructor || (dso && e.dso != dso)) { atexit_unlock();
continue; }
72 g_atexit_table[
static_cast<usize>(i)].destructor =
nullptr;
78static constexpr u64 GUARD_INITIALIZED = 1ULL << 0;
79static constexpr u64 GUARD_IN_PROGRESS = 1ULL << 1;
81auto __cxa_guard_acquire(u64* g) ->
int {
82 if (__atomic_load_n(g, __ATOMIC_ACQUIRE) & GUARD_INITIALIZED)
return 0;
85 if (__atomic_compare_exchange_n(g, &expected,
93 while (!(__atomic_load_n(g, __ATOMIC_ACQUIRE) & GUARD_INITIALIZED))
94 arch::s390x::cpu::sync::cpu_relax();
98auto __cxa_guard_release(u64* g) ->
void {
99 __atomic_store_n(g, GUARD_INITIALIZED, __ATOMIC_RELEASE);
102auto __cxa_guard_abort(u64* g) ->
void {
103 __atomic_store_n(g, 0ULL, __ATOMIC_RELEASE);
106[[noreturn]]
auto __cxa_pure_virtual() ->
void {
107 zxfoundation::sys::syschk::syschk_fatal(
108 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
109 "cxxabi: __cxa_pure_virtual(): call to pure virtual function. "
110 "Object is being used before its derived constructor completed "
111 "or the vtable is corrupt."
115[[noreturn]]
auto __cxa_deleted_virtual() ->
void {
116 zxfoundation::sys::syschk::syschk_fatal(
117 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
118 "cxxabi: __cxa_deleted_virtual(): call to explicitly deleted virtual function. "
119 "The vtable is corrupt or an invalid base pointer was used."
123[[noreturn]]
auto __cxa_bad_typeid() ->
void {
124 zxfoundation::sys::syschk::syschk_fatal(
125 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
126 "cxxabi: __cxa_bad_typeid(): typeid applied to a null pointer. "
127 "A pre-compiled object file likely contains RTTI usage."
131[[noreturn]]
auto __cxa_throw(
void *,
void *,
void (*)(
void *)) ->
void {
132 zxfoundation::sys::syschk::syschk_fatal(
133 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
134 "cxxabi: __cxa_throw(3): C++ exception thrown in a no-exception kernel context. "
135 "A pre-compiled object file likely "
136 "contains exception-throwing code that is incompatible with FoundationKit."
140[[noreturn]]
auto __cxa_rethrow() ->
void {
141 zxfoundation::sys::syschk::syschk_fatal(
142 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
143 "cxxabi: __cxa_rethrow(): rethrow attempted in a no-exception context. "
147auto __cxa_begin_catch(
void*) ->
void* {
148 zxfoundation::sys::syschk::syschk_fatal(
149 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
150 "cxxabi: __cxa_begin_catch(): catch block entered in a no-exception context."
154auto __cxa_end_catch() ->
void {
155 zxfoundation::sys::syschk::syschk_fatal(
156 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
157 "cxxabi: __cxa_end_catch(): end-catch reached in a no-exception context."
161auto __cxa_allocate_exception(u64) ->
void* {
162 zxfoundation::sys::syschk::syschk_fatal(
163 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
164 "cxxabi: __cxa_allocate_exception(): exception object allocation attempted "
165 "in a no-exception context."
169auto __cxa_free_exception(
void*) ->
void* {
170 zxfoundation::sys::syschk::syschk_fatal(
171 lib::kernel_error::from_generic(lib::generic_error::code::internal_error),
172 "cxxabi: __cxa_free_exception(): exception object deallocation attempted "
173 "in a no-exception context."
179u64 __stack_chk_guard = 0x595A465353500001ULL;
181[[gnu::no_stack_protector, noreturn]]
auto __stack_chk_fail() ->
void {
182 zxfoundation::sys::syschk::syschk_fatal(
183 lib::kernel_error::from_memory(lib::memory_error::ssp_check_fail),
184 "cxxrtse: stack smashing detected"
186 __builtin_unreachable();
193namespace zxfoundation::base::cxxrtse::cxxabi {
199 [[gnu::no_stack_protector]]
void ssp_init()
noexcept {
201 arch::s390x::cpu::clock::stck() ^ 0xC0FFEE00FACADE42ULL;
206 [[nodiscard]]
auto stack_guard()
noexcept -> u64 {
207 return __stack_chk_guard;
210 void run_global_constructor()
noexcept {
211 if (&__init_array_end ==
nullptr) [[unlikely]] {
212 pinfo(
"cxxabi: __init_array_start or __init_array_end "
213 "symbols are missing. No global constructors will be called. "
214 "Check the kernel linker script.");
218 const auto count =
static_cast<usize>(
219 __init_array_end - __init_array_start);
221 pinfo(
"cxxabi: running {} global constructors.", count);
223 for (usize i = 0; i < count; ++i) {
224 void (*fn)() = __init_array_start[i];
225 if (fn ==
nullptr) [[unlikely]] {
226 pinfo(
"cxxabi: null constructor pointer at index {}. "
227 "Possible linker script alignment issue. Skipping.", i);
233 pinfo(
"cxxabi: all constructors completed.");
236 void run_fini_array()
noexcept {
237 if (!&__fini_array_end) [[unlikely]] {
238 pinfo(
"cxxabi: __fini_array_start or __fini_array_end "
239 "symbols are missing. No fini_array functions will be called.");
243 const auto count =
static_cast<usize>(
244 __fini_array_end - __fini_array_start);
246 pinfo(
"cxxabi: running {} fini_array entries (reverse order).", count);
249 for (usize i = count; i > 0; --i) {
250 void (*fn)() = __fini_array_start[i - 1];
251 if (fn ==
nullptr) [[unlikely]] {
252 pinfo(
"cxxabi: null fini_array pointer at index {}. Skipping.",
259 pinfo(
"cxxabi: all fini_array entries completed.");
262 void run_global_destructors()
noexcept {
263 pinfo(
"cxxabi: running all registered atexit destructors.");
264 __cxa_finalize(
nullptr);
266 pinfo(
"cxxabi: all destructors completed.");