From e34395915d7075e665bdd9ebe899ea380c8f87ef Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 4 Jan 2024 21:02:51 +0100 Subject: [PATCH] libc+tests+tools: Call global constructors in userspace code --- libc/src/arch/x86_64/crt0.S | 9 +++++++- libc/src/init.cpp | 10 ++++++++ tests/CMakeLists.txt | 1 + tests/libc/TestGlobalCtors.cpp | 42 ++++++++++++++++++++++++++++++++++ tools/setup-binutils.sh | 2 +- tools/setup-gcc.sh | 2 +- 6 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 tests/libc/TestGlobalCtors.cpp diff --git a/libc/src/arch/x86_64/crt0.S b/libc/src/arch/x86_64/crt0.S index a128c99a..4652c8aa 100644 --- a/libc/src/arch/x86_64/crt0.S +++ b/libc/src/arch/x86_64/crt0.S @@ -3,6 +3,8 @@ .global _start .extern exit .extern libc_init +.extern _init +.extern _fini _start: # Set up end of the stack frame linked list. movq $0, %rbp @@ -26,6 +28,11 @@ _start: # Run main call main + # Store the exit code before calling _fini. + push %rax + + call _fini + # Terminate the process with the exit code. - movl %eax, %edi + pop %rdi call exit diff --git a/libc/src/init.cpp b/libc/src/init.cpp index e8fe79b9..f4129e96 100644 --- a/libc/src/init.cpp +++ b/libc/src/init.cpp @@ -7,6 +7,14 @@ extern char** environ; extern "C" FILE* _fdopen_impl(int, const char*, int); extern "C" void _init_stdio(); +typedef void initfunc_t(void); +extern initfunc_t *__init_array_start[], *__init_array_end[]; + +static void handle_init_array(void) +{ + for (initfunc_t** p = __init_array_start; p != __init_array_end; p++) (*p)(); +} + extern "C" { void libc_init(int argc, char** argv, int envc, char** envp) @@ -19,5 +27,7 @@ extern "C" stdin = _fdopen_impl(STDIN_FILENO, "r", _IOLBF); stdout = _fdopen_impl(STDOUT_FILENO, "w", _IOLBF); stderr = _fdopen_impl(STDERR_FILENO, "w", _IONBF); + + handle_init_array(); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 72d0856a..ca38a569 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -23,6 +23,7 @@ luna_test(libluna/TestSharedPtr.cpp TestSharedPtr) luna_test(libc/TestScanf.cpp TestScanf) luna_test(libc/TestString.cpp TestString) luna_test(libc/TestEnv.cpp TestEnv) +luna_test(libc/TestGlobalCtors.cpp TestGlobalCtors) luna_app(run-tests.cpp run-tests) endif() diff --git a/tests/libc/TestGlobalCtors.cpp b/tests/libc/TestGlobalCtors.cpp new file mode 100644 index 00000000..af56fbe3 --- /dev/null +++ b/tests/libc/TestGlobalCtors.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +struct TestStruct +{ + TestStruct(const char* name) : m_name(name) + { + // Just to make sure this constructor doesn't get optimized out + time_t t = time(NULL); + ctime(&t); + } + + const char* name() + { + return m_name; + } + + private: + const char* m_name; +}; + +TestStruct g_struct("Example Struct"); + +TestResult test_successful_global_constructor() +{ + validate(g_struct.name()); + + validate(!strcmp(g_struct.name(), "Example Struct")); + + test_success; +} + +Result test_main() +{ + test_prelude; + + run_test(test_successful_global_constructor); + + return {}; +} diff --git a/tools/setup-binutils.sh b/tools/setup-binutils.sh index d1a389fc..c7dfa3bd 100755 --- a/tools/setup-binutils.sh +++ b/tools/setup-binutils.sh @@ -39,7 +39,7 @@ unset CXX unset LD unset AR -../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror --enable-warn-rwx-segments=no +../binutils-$LUNA_BINUTILS_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --disable-werror --enable-warn-rwx-segments=no --enable-initfini-array echo Building Binutils... diff --git a/tools/setup-gcc.sh b/tools/setup-gcc.sh index 84250367..3e4618ad 100755 --- a/tools/setup-gcc.sh +++ b/tools/setup-gcc.sh @@ -51,7 +51,7 @@ unset CXX unset LD unset AR -../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++ +../gcc-$LUNA_GCC_VERSION_REQUIRED/configure --prefix="$BUILD_PREFIX" --target=$BUILD_TARGET --disable-nls --with-sysroot=$BUILD_SYSROOT --enable-languages=c,c++ --enable-initfini-array echo Building GCC...