diff --git a/libc/icxxabi.cpp b/libc/icxxabi.cpp index fb234e60..5484137a 100644 --- a/libc/icxxabi.cpp +++ b/libc/icxxabi.cpp @@ -1,35 +1,37 @@ +#include + #define ATEXIT_MAX_FUNCS 128 -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned uarch_t; - struct atexit_func_entry_t { - /* - * Each member is at least 4 bytes large. Such that each entry is 12bytes. - * 128 * 12 = 1.5KB exact. - **/ - void (*destructor_func)(void *); - void *obj_ptr; - void *dso_handle; + void (*destructor)(void*); + void* data; + void* dso_handle; }; -atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; -uarch_t __atexit_func_count = 0; +static atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; +static int __atexit_func_count = 0; -int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) +int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle) { - if (__atexit_func_count >= ATEXIT_MAX_FUNCS) {return -1;}; - __atexit_funcs[__atexit_func_count].destructor_func = f; - __atexit_funcs[__atexit_func_count].obj_ptr = objptr; - __atexit_funcs[__atexit_func_count].dso_handle = dso; + if (__atexit_func_count >= ATEXIT_MAX_FUNCS) + return -1;; + __atexit_funcs[__atexit_func_count].destructor = func; + __atexit_funcs[__atexit_func_count].data = data; + __atexit_funcs[__atexit_func_count].dso_handle = dso_handle; __atexit_func_count++; - return 0; /*I would prefer if functions returned 1 on success, but the ABI says...*/ + return 0; }; -#ifdef __cplusplus -}; -#endif +void __cxa_finalize(void* func) +{ + for (int i = __atexit_func_count - 1; i >= 0; i--) + { + if (func && func != __atexit_funcs[i].destructor) + continue; + if (__atexit_funcs[i].destructor == nullptr) + continue; + __atexit_funcs[i].destructor(__atexit_funcs[i].data); + __atexit_funcs[i].destructor = nullptr; + } +} diff --git a/libc/include/icxxabi.h b/libc/include/icxxabi.h new file mode 100644 index 00000000..68840a90 --- /dev/null +++ b/libc/include/icxxabi.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +__BEGIN_DECLS + +int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle); +void __cxa_finalize(void* func); + +__END_DECLS diff --git a/libc/stdlib.cpp b/libc/stdlib.cpp index 4d5e9570..d9bd9ab3 100644 --- a/libc/stdlib.cpp +++ b/libc/stdlib.cpp @@ -7,6 +7,8 @@ #include #include +#include + extern "C" char** environ; extern "C" void _fini(); @@ -21,6 +23,7 @@ void abort(void) void exit(int status) { fflush(nullptr); + __cxa_finalize(nullptr); _fini(); _exit(status); ASSERT_NOT_REACHED();