[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.
This commit is contained in:
Justin C. Miller
2024-04-29 01:07:18 -07:00
parent 70af5a31cd
commit 7322df98f5
4 changed files with 71 additions and 34 deletions

View File

@@ -5,6 +5,52 @@ extern exit
extern __init_libj6 extern __init_libj6
extern __init_libc 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 ; Put the address of the given symbol in rax
; This macro is the same as in util/got.inc, ; This macro is the same as in util/got.inc,
; but crt0 can't have a dep on libutil ; but crt0 can't have a dep on libutil
@@ -31,6 +77,8 @@ _libc_crt0_start:
lookup_GOT __init_libc lookup_GOT __init_libc
call rax call rax
call __run_global_ctors
mov rdi, 0 mov rdi, 0
mov rsi, rsp mov rsi, rsp
mov rdx, 0 ; TODO: actually parse stack for argc, argv, envp mov rdx, 0 ; TODO: actually parse stack for argc, argv, envp

View File

@@ -1,33 +1,6 @@
#include <stddef.h> #include <stddef.h>
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 extern "C" void
__init_libc() __init_libc()
{ {
run_global_ctors();
} }

View File

@@ -17,6 +17,8 @@
extern "C" void _ldso_plt_lookup(); extern "C" void _ldso_plt_lookup();
extern image_list all_images; 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 // Can't use strcmp because it's from another library, and
// this needs to be used as part of relocation or symbol lookup // this needs to be used as part of relocation or symbol lookup
@@ -327,9 +329,7 @@ image::parse_rela_table(const util::counted<const rela> &table, image_list &ctx)
void void
image::relocate(image_list &ctx) image::relocate(image_list &ctx)
{ {
if (relocated) if (!relocated) {
return;
parse_rela_table(dynrel, ctx); parse_rela_table(dynrel, ctx);
parse_rela_table(jmprel, ctx); parse_rela_table(jmprel, ctx);
@@ -338,6 +338,21 @@ image::relocate(image_list &ctx)
relocated = true; 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 * image_list::item_type *
image_list::find_image(const char *name) image_list::find_image(const char *name)
{ {

View File

@@ -28,6 +28,7 @@ struct image
gnu_hash_table const *gnu_hash = nullptr; gnu_hash_table const *gnu_hash = nullptr;
bool relocated = false; bool relocated = false;
bool ctors = false;
/// Look up a string table entry in this image's string table. /// Look up a string table entry in this image's string table.
const char * string(unsigned index) const { const char * string(unsigned index) const {