From: Tulio A M Mendes Date: Fri, 3 Apr 2026 19:52:58 +0000 (-0300) Subject: feat(ulibc): add __libc_init_array/__libc_fini_array and update crt0.S X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=3c7f1480fede1343d98cb4cdb27ba4a94052b466;p=AdrOS.git feat(ulibc): add __libc_init_array/__libc_fini_array and update crt0.S Add constructor/destructor support to ulibc: - New file init_fini.c: implements __libc_init_array() to run .preinit_array and .init_array global constructors, and __libc_fini_array() to run .fini_array global destructors. - Updated crt0.S: calls __libc_init_array before main and __libc_fini_array after main returns (matching Newlib crt0 behavior). Also uses 'environ' symbol (POSIX) and adds .note.GNU-stack for NX compatibility. --- diff --git a/user/ulibc/src/crt0.S b/user/ulibc/src/crt0.S index 8e33b023..cadc2028 100644 --- a/user/ulibc/src/crt0.S +++ b/user/ulibc/src/crt0.S @@ -21,7 +21,9 @@ .global _start .extern main .extern exit -.extern __environ +.extern environ +.extern __libc_init_array +.extern __libc_fini_array _start: /* Set up user data segments */ @@ -41,16 +43,33 @@ _start: shl $2, %edx add %ecx, %edx /* edx = envp */ - /* Store envp in __environ global (weak, may not exist) */ - mov %edx, __environ + /* Store envp in environ global */ + mov %edx, environ + + /* Save argc/argv/envp across init_array call */ + push %edx /* envp */ + push %ecx /* argv */ + push %eax /* argc */ + + /* Run global constructors / init_array */ + call __libc_init_array + + /* Restore argc/argv/envp and call main */ + pop %eax /* argc */ + pop %ecx /* argv */ + pop %edx /* envp */ - /* Call main(argc, argv, envp) */ push %edx /* envp */ push %ecx /* argv */ push %eax /* argc */ call main add $12, %esp + /* Run global destructors / fini_array */ + push %eax /* save main return value */ + call __libc_fini_array + pop %eax + /* exit(main return value) */ push %eax call exit diff --git a/user/ulibc/src/init_fini.c b/user/ulibc/src/init_fini.c new file mode 100644 index 00000000..d409d043 --- /dev/null +++ b/user/ulibc/src/init_fini.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +/* + * __libc_init_array / __libc_fini_array — run global constructors/destructors + * + * These iterate over .preinit_array, .init_array, and .fini_array sections + * created by the linker. Required for __attribute__((constructor)), + * __attribute__((destructor)), and C++ static initializers. + * + * The symbols __preinit_array_start, __init_array_start, __init_array_end, + * __fini_array_start, __fini_array_end are defined by the linker script. + * _init() and _fini() come from crti.o/crtn.o (GCC CRT files). + */ + +#include + +typedef void (*init_func)(void); + +extern init_func __preinit_array_start[]; +extern init_func __preinit_array_end[]; +extern init_func __init_array_start[]; +extern init_func __init_array_end[]; +extern init_func __fini_array_start[]; +extern init_func __fini_array_end[]; + +extern void _init(void); +extern void _fini(void); + +void __libc_init_array(void) { + size_t count, i; + + count = (size_t)(__preinit_array_end - __preinit_array_start); + for (i = 0; i < count; i++) + __preinit_array_start[i](); + + _init(); + + count = (size_t)(__init_array_end - __init_array_start); + for (i = 0; i < count; i++) + __init_array_start[i](); +} + +void __libc_fini_array(void) { + size_t count; + + count = (size_t)(__fini_array_end - __fini_array_start); + while (count-- > 0) + __fini_array_start[count](); + + _fini(); +}