DynamicLoader: Fix copy relocation and TLS initialization

This commit is contained in:
Bananymous 2026-03-04 23:02:41 +02:00
parent eeef945c25
commit acebe68dfa
1 changed files with 16 additions and 11 deletions

View File

@ -389,7 +389,7 @@ static void handle_tls_relocation(const LoadedElf& elf, const RelocT& reloc)
const auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + symbol_index * elf.syment); const auto& symbol = *reinterpret_cast<ElfNativeSymbol*>(elf.symtab + symbol_index * elf.syment);
const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name); const char* symbol_name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name);
if (symbol.st_shndx && ELF_ST_BIND(symbol.st_info) != STB_WEAK) if (ELF_ST_BIND(symbol.st_info) == STB_LOCAL && symbol.st_shndx)
symbol_offset = symbol.st_value; symbol_offset = symbol.st_value;
else else
{ {
@ -504,7 +504,7 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc, bo
CHECK_SYM(__dlsym); CHECK_SYM(__dlsym);
CHECK_SYM(__dladdr); CHECK_SYM(__dladdr);
#undef CHECK_SYM #undef CHECK_SYM
else if (symbol.st_shndx && ELF_ST_BIND(symbol.st_info) != STB_WEAK) else if (ELF_ST_BIND(symbol.st_info) == STB_LOCAL && symbol.st_shndx)
symbol_address = elf.base + symbol.st_value; symbol_address = elf.base + symbol.st_value;
else else
{ {
@ -647,14 +647,6 @@ static void relocate_elf(LoadedElf& elf, bool lazy_load)
return; return;
elf.is_relocating = true; elf.is_relocating = true;
// do copy relocations
if (elf.rel && elf.relent)
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent));
if (elf.rela && elf.relaent)
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent));
// relocate libraries // relocate libraries
for (size_t i = 0;; i++) for (size_t i = 0;; i++)
{ {
@ -1531,11 +1523,15 @@ void* __dlopen(const char* file, int mode)
if (!elf.is_relocating && !elf.is_calling_init) if (!elf.is_relocating && !elf.is_calling_init)
{ {
for (size_t i = old_loaded_count + 1; i < s_loaded_file_count; i++) for (size_t i = old_loaded_count; i < s_loaded_file_count; i++)
{ {
if (s_loaded_files[i].tls_header.p_type == PT_TLS) if (s_loaded_files[i].tls_header.p_type == PT_TLS)
{ {
s_dlerror_string = "TODO: __dlopen with TLS"; s_dlerror_string = "TODO: __dlopen with TLS";
// FIXME: leaks loaded files :)
s_loaded_file_count = old_loaded_count;
return nullptr; return nullptr;
} }
} }
@ -1717,6 +1713,15 @@ uintptr_t _entry(int argc, char* argv[], char* envp[])
const auto master_tls = initialize_master_tls(); const auto master_tls = initialize_master_tls();
relocate_elf(elf, true); relocate_elf(elf, true);
// do copy relocations
if (elf.rel && elf.relent)
for (size_t i = 0; i < elf.relsz / elf.relent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocation*>(elf.rel + i * elf.relent));
if (elf.rela && elf.relaent)
for (size_t i = 0; i < elf.relasz / elf.relaent; i++)
handle_copy_relocation(elf, *reinterpret_cast<ElfNativeRelocationA*>(elf.rela + i * elf.relaent));
initialize_tls(master_tls); initialize_tls(master_tls);
initialize_environ(envp); initialize_environ(envp);
call_init_funcs(elf, true); call_init_funcs(elf, true);