.global _start
.extern main
.extern exit
-.extern __environ
+.extern environ
+.extern __libc_init_array
+.extern __libc_fini_array
_start:
/* Set up user data segments */
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
--- /dev/null
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * 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 <stddef.h>
+
+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();
+}