diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-07-24 12:28:23 +0000 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-07-24 12:28:23 +0000 |
| commit | f62b05c93c6c539d899d2656c0638d404a036f1a (patch) | |
| tree | 971236e6732e0341f96f16d3e200270a68f22397 | |
| parent | 2ebf8d525e6a030efc8ca23bcbdf92c2d0cb8985 (diff) | |
| download | teachos-f62b05c93c6c539d899d2656c0638d404a036f1a.tar.xz teachos-f62b05c93c6c539d899d2656c0638d404a036f1a.zip | |
x86_64: implement robust C++ global initialization
Implement a comprehensive mechanism to ensure correct C++ runtime
initialization before the kernel main function is called. This replaces
the previous, incomplete reliance on an `_init` function.
The new design robustly handles both legacy `.ctors` and modern
`.init_array` initialization schemes used by the GNU toolchain. A single
C++ function, `invoke_global_constructors`, now iterates through both
arrays of function pointers to ensure all types of global initializers
are executed.
| -rw-r--r-- | arch/x86_64/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | arch/x86_64/scripts/kernel.ld | 40 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/crti.s | 13 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/crtn.s | 9 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/entry64.s | 4 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/initialize_runtime.cpp | 24 |
6 files changed, 36 insertions, 57 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 6bb9e53..58daa3b 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -35,9 +35,8 @@ target_sources("arch-x86_64" PRIVATE target_sources("arch-x86_64" PRIVATE "src/boot/boot32.S" - "src/boot/crti.s" - "src/boot/crtn.s" "src/boot/entry64.s" + "src/boot/initialize_runtime.cpp" "src/boot/multiboot.s" ) diff --git a/arch/x86_64/scripts/kernel.ld b/arch/x86_64/scripts/kernel.ld index 6ba8b80..064b8d7 100644 --- a/arch/x86_64/scripts/kernel.ld +++ b/arch/x86_64/scripts/kernel.ld @@ -68,33 +68,11 @@ SECTIONS . = ALIGN(4K); . += TEACHOS_VMA; - .init ALIGN(4K) : AT(ADDR(.init) - TEACHOS_VMA) - { - /* - * Make sure that the crt code is wrapped around the compiler generated - * initialization code. - */ - KEEP(*crti.s.o*(.init)) - KEEP(*(EXCLUDE_FILE (*crti.s.o* *crtn.s.o*) .init)) - KEEP(*crtn.s.o*(.init)) - } :text - - .fini ALIGN(4K) : AT(ADDR (.fini) - TEACHOS_VMA) - { - /* - * Make sure that the crt code is wrapped around the compiler generated - * finalizer code. - */ - KEEP(*crti.s.o*(.fini)) - KEEP(*(EXCLUDE_FILE (*crti.s.o* *crtn.s.o*) .fini)) - KEEP(*crtn.s.o*(.fini)) - } - .stl_text ALIGN(4K) : AT(ADDR (.stl_text) - TEACHOS_VMA) { *(.stl_text .stl_text*) KEEP(*libstdc++.a:*(.text .text.*)) - } + } :text .text ALIGN(4K) : AT(ADDR (.text) - TEACHOS_VMA) { @@ -114,18 +92,18 @@ SECTIONS .ctors ALIGN(4K) : AT (ADDR (.ctors) - TEACHOS_VMA) { - KEEP(*crtbegin.o(.ctors)) - KEEP(*(EXCLUDE_FILE (*crtend.o) .ctors)) + __ctors_start = .; KEEP(*(SORT(.ctors.*))) - KEEP(*crtend.o(.ctors)) + KEEP(*(.ctors)) + __ctors_end = .; } :data - .dtors ALIGN(4K) : AT (ADDR (.dtors) - TEACHOS_VMA) + .init_array ALIGN(4K) : AT (ADDR (.init_array) - TEACHOS_VMA) { - KEEP(*crtbegin.o(.dtors)) - KEEP(*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP(*(SORT(.dtors.*))) - KEEP(*crtend.o(.dtors)) + __init_array_start = .; + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*))) + KEEP(*(.init_array)) + __init_array_end = .; } .bss ALIGN(4K) : AT (ADDR (.bss) - TEACHOS_VMA) diff --git a/arch/x86_64/src/boot/crti.s b/arch/x86_64/src/boot/crti.s deleted file mode 100644 index 26878fe..0000000 --- a/arch/x86_64/src/boot/crti.s +++ /dev/null @@ -1,13 +0,0 @@ -.code64 - -.section .init -.global _init -_init: - push %rbp - movq %rsp, %rbp - -.section .fini -.global _fini -_fini: - push %rbp - movq %rsp, %rbp diff --git a/arch/x86_64/src/boot/crtn.s b/arch/x86_64/src/boot/crtn.s deleted file mode 100644 index 06fb7ce..0000000 --- a/arch/x86_64/src/boot/crtn.s +++ /dev/null @@ -1,9 +0,0 @@ -.code64 - -.section .init - popq %rbp - ret - -.section .fini - popq %rbp - ret diff --git a/arch/x86_64/src/boot/entry64.s b/arch/x86_64/src/boot/entry64.s index f575c50..110ced8 100644 --- a/arch/x86_64/src/boot/entry64.s +++ b/arch/x86_64/src/boot/entry64.s @@ -12,8 +12,8 @@ _entry64: xor %rax, %rax - call _init - + call invoke_global_constructors + call main 1: diff --git a/arch/x86_64/src/boot/initialize_runtime.cpp b/arch/x86_64/src/boot/initialize_runtime.cpp new file mode 100644 index 0000000..9a3df0e --- /dev/null +++ b/arch/x86_64/src/boot/initialize_runtime.cpp @@ -0,0 +1,24 @@ +#include <algorithm> +#include <functional> +#include <span> + +extern "C" +{ + using global_initializer = auto (*)() -> void; + + extern global_initializer __ctors_start; + extern global_initializer __ctors_end; + extern global_initializer __init_array_start; + extern global_initializer __init_array_end; + + auto invoke_global_constructors() -> void + { + auto constructors = std::span{&__ctors_start, &__ctors_end}; + auto initializers = std::span{&__init_array_start, &__init_array_end}; + + auto apply_invoke = [](auto invokable) { return std::invoke(invokable); }; + + std::ranges::for_each(constructors, apply_invoke); + std::ranges::for_each(initializers, apply_invoke); + } +} |
