LibC: implement and call __cxa_finalize() on exit()

This allows global destructors to be actually called
This commit is contained in:
Bananymous 2023-10-30 11:10:08 +02:00
parent 0b5fcb3f88
commit 7c6832cee4
3 changed files with 39 additions and 24 deletions

View File

@ -1,35 +1,37 @@
#include <icxxabi.h>
#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 (*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;
}
}

10
libc/include/icxxabi.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <sys/cdefs.h>
__BEGIN_DECLS
int __cxa_atexit(void (*func)(void*), void* data, void* dso_handle);
void __cxa_finalize(void* func);
__END_DECLS

View File

@ -7,6 +7,8 @@
#include <sys/syscall.h>
#include <unistd.h>
#include <icxxabi.h>
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();