aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-07-24 12:28:23 +0000
committerFelix Morgner <felix.morgner@ost.ch>2025-07-24 12:28:23 +0000
commitf62b05c93c6c539d899d2656c0638d404a036f1a (patch)
tree971236e6732e0341f96f16d3e200270a68f22397
parent2ebf8d525e6a030efc8ca23bcbdf92c2d0cb8985 (diff)
downloadteachos-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.txt3
-rw-r--r--arch/x86_64/scripts/kernel.ld40
-rw-r--r--arch/x86_64/src/boot/crti.s13
-rw-r--r--arch/x86_64/src/boot/crtn.s9
-rw-r--r--arch/x86_64/src/boot/entry64.s4
-rw-r--r--arch/x86_64/src/boot/initialize_runtime.cpp24
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);
+ }
+}