LibC: Rework constructor/destructor calling

constructors are now called in _init_libc instead of crt0

destructors are now registered with atexit() instead of called manually
This commit is contained in:
Bananymous 2025-04-15 22:29:26 +03:00
parent 066ed7e4a1
commit cf59f89bfb
4 changed files with 46 additions and 37 deletions

View File

@ -3,9 +3,9 @@
.global _start
_start:
pushl $0
pushl %edi
pushl %esi
pushl %edx
pushl %esi
pushl %edi
# STACK LAYOUT
# null
@ -15,27 +15,21 @@ _start:
xorl %ebp, %ebp
# init libc (envp already as argument)
pushl $__fini_array_end
pushl $__fini_array_start
pushl $_fini
pushl $__init_array_end
pushl $__init_array_start
pushl $_init
pushl %edx
call _init_libc
# call global constructors
movl $_init, %eax
testl %eax, %eax
jz 1f
call *%eax
1:
addl $(4 * 8), %esp
movl $__init_array_start, %ebx
jmp 2f
1: call *(%ebx)
addl $4, %ebx
2: cmpl $__init_array_end, %ebx
jne 1b
# call main
movl 0(%esp), %eax
xchgl %eax, 8(%esp)
movl %eax, (%esp)
# argc, argv, envp already on stack
call main
subl $12, %esp

View File

@ -17,21 +17,18 @@ _start:
# init libc
movq 0(%rsp), %rdi
pushq $__fini_array_end
pushq $__fini_array_start
pushq $_fini
pushq $__init_array_end
pushq $__init_array_start
pushq $_init
call _init_libc
# call global constructors
movq $_init, %rax
testq %rax, %rax
jz 1f
call *%rax
1:
movq $__init_array_start, %rbx
jmp 2f
1: call *(%rbx)
addq $8, %rbx
2: cmpq $__init_array_end, %rbx
jne 1b
addq $(6 * 8), %rsp
# call main
movq 16(%rsp), %rdi

View File

@ -23,8 +23,6 @@ char** __environ;
weak_alias(__environ, environ);
static bool s_environ_malloced = false;
extern "C" __attribute__((weak)) void _fini();
void abort(void)
{
sigset_t set;
@ -43,7 +41,6 @@ void exit(int status)
{
fflush(nullptr);
__cxa_finalize(nullptr);
if (_fini) _fini();
_exit(status);
ASSERT_NOT_REACHED();
}

View File

@ -16,12 +16,33 @@
#include <termios.h>
#include <unistd.h>
struct init_funcs_t
{
void (*func)();
void (**array_start)();
void (**array_end)();
};
extern "C" char** environ;
extern "C" void _init_libc(char** _environ)
extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t fini_funcs)
{
if (::environ == nullptr)
::environ = environ;
// call global constructors
if (init_funcs.func)
init_funcs.func();
const size_t init_array_count = init_funcs.array_end - init_funcs.array_start;
for (size_t i = 0; i < init_array_count; i++)
init_funcs.array_start[i]();
// register global destructors
const size_t fini_array_count = fini_funcs.array_end - fini_funcs.array_start;
for (size_t i = 0; i < fini_array_count; i++)
atexit(fini_funcs.array_start[i]);
if (fini_funcs.func)
atexit(fini_funcs.func);
}
void _exit(int status)