From 7322df98f59c052dcca20caa63573e77f0a416d7 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 29 Apr 2024 01:07:18 -0700 Subject: [PATCH] [ld.so] Call all image global ctors, not just libc With the move to dynamic executables, crt0's _start was only ever calling libc's __init_libc, which only ran libc's init_array list. Now make crt0 itself (which is statically linked into every executable) call it's own init_array list and have ld.so call every other image's ctor lists. --- src/libraries/libc/arch/amd64/crt/crt0.s | 48 ++++++++++++++++++++++++ src/libraries/libc/arch/amd64/init.cpp | 27 ------------- src/user/ld.so/image.cpp | 29 ++++++++++---- src/user/ld.so/image.h | 1 + 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/libraries/libc/arch/amd64/crt/crt0.s b/src/libraries/libc/arch/amd64/crt/crt0.s index 299e8cf..05e5e29 100644 --- a/src/libraries/libc/arch/amd64/crt/crt0.s +++ b/src/libraries/libc/arch/amd64/crt/crt0.s @@ -5,6 +5,52 @@ extern exit extern __init_libj6 extern __init_libc +extern __preinit_array_start +extern __preinit_array_end +extern __init_array_start +extern __init_array_end + +global __run_ctor_list:function hidden (__run_ctor_list.end - __run_ctor_list) +__run_ctor_list: + push rbp + mov rbp, rsp + + push rbx + push r12 + mov rbx, rdi + mov r12, rsi +.start: + cmp rbx, r12 + je .fin + mov rax, [rbx] + call rax + add rbx, 8 + jmp .start +.fin: + + pop r12 + pop rbx + pop rbp + ret +.end: + +global __run_global_ctors:function hidden (__run_global_ctors.end - __run_global_ctors) +__run_global_ctors: + push rbp + mov rbp, rsp + + lea rdi, [rel __preinit_array_start] + lea rsi, [rel __preinit_array_end] + call __run_ctor_list + lea rdi, [rel __init_array_start] + lea rsi, [rel __init_array_end] + call __run_ctor_list + + pop rbp + ret +.end: + + ; Put the address of the given symbol in rax ; This macro is the same as in util/got.inc, ; but crt0 can't have a dep on libutil @@ -31,6 +77,8 @@ _libc_crt0_start: lookup_GOT __init_libc call rax + call __run_global_ctors + mov rdi, 0 mov rsi, rsp mov rdx, 0 ; TODO: actually parse stack for argc, argv, envp diff --git a/src/libraries/libc/arch/amd64/init.cpp b/src/libraries/libc/arch/amd64/init.cpp index 5f57c1a..973a4cc 100644 --- a/src/libraries/libc/arch/amd64/init.cpp +++ b/src/libraries/libc/arch/amd64/init.cpp @@ -1,33 +1,6 @@ #include -using cb = void (*)(void); -extern cb __preinit_array_start; -extern cb __preinit_array_end; -extern cb __init_array_start; -extern cb __init_array_end; - -namespace { - -void -run_ctor_list(cb *p, cb *end) -{ - while (p && end && p < end) { - if (p) (*p)(); - ++p; - } -} - -void -run_global_ctors() -{ - run_ctor_list(&__preinit_array_start, &__preinit_array_end); - run_ctor_list(&__init_array_start, &__init_array_end); -} - -} // namespace - extern "C" void __init_libc() { - run_global_ctors(); } diff --git a/src/user/ld.so/image.cpp b/src/user/ld.so/image.cpp index c60e60e..f52d358 100644 --- a/src/user/ld.so/image.cpp +++ b/src/user/ld.so/image.cpp @@ -17,6 +17,8 @@ extern "C" void _ldso_plt_lookup(); extern image_list all_images; +// From crt0, which ld.so also links +extern void __run_ctor_list(uintptr_t start, uintptr_t end); // Can't use strcmp because it's from another library, and // this needs to be used as part of relocation or symbol lookup @@ -327,15 +329,28 @@ image::parse_rela_table(const util::counted &table, image_list &ctx) void image::relocate(image_list &ctx) { - if (relocated) - return; + if (!relocated) { + parse_rela_table(dynrel, ctx); + parse_rela_table(jmprel, ctx); - parse_rela_table(dynrel, ctx); - parse_rela_table(jmprel, ctx); + got[1] = reinterpret_cast(this); + got[2] = reinterpret_cast(&_ldso_plt_lookup); + relocated = true; + } - got[1] = reinterpret_cast(this); - got[2] = reinterpret_cast(&_ldso_plt_lookup); - relocated = true; + if (!ctors) { + uintptr_t pre_init_start = lookup("__preinit_array_start"); + uintptr_t pre_init_end = lookup("__preinit_array_end"); + if (pre_init_start && pre_init_end) + __run_ctor_list(pre_init_start, pre_init_end); + + uintptr_t init_start = lookup("__init_array_start"); + uintptr_t init_end = lookup("__init_array_end"); + if (init_start && init_end) + __run_ctor_list(init_start, init_end); + + ctors = true; + } } image_list::item_type * diff --git a/src/user/ld.so/image.h b/src/user/ld.so/image.h index e1d04fb..a98ebc2 100644 --- a/src/user/ld.so/image.h +++ b/src/user/ld.so/image.h @@ -28,6 +28,7 @@ struct image gnu_hash_table const *gnu_hash = nullptr; bool relocated = false; + bool ctors = false; /// Look up a string table entry in this image's string table. const char * string(unsigned index) const {