[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:
@@ -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
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,15 +329,28 @@ 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(jmprel, ctx);
|
||||||
|
|
||||||
parse_rela_table(dynrel, ctx);
|
got[1] = reinterpret_cast<uintptr_t>(this);
|
||||||
parse_rela_table(jmprel, ctx);
|
got[2] = reinterpret_cast<uintptr_t>(&_ldso_plt_lookup);
|
||||||
|
relocated = true;
|
||||||
|
}
|
||||||
|
|
||||||
got[1] = reinterpret_cast<uintptr_t>(this);
|
if (!ctors) {
|
||||||
got[2] = reinterpret_cast<uintptr_t>(&_ldso_plt_lookup);
|
uintptr_t pre_init_start = lookup("__preinit_array_start");
|
||||||
relocated = true;
|
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 *
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user