summaryrefslogtreecommitdiff
path: root/Userland/DynamicLoader
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-07-06 10:17:11 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-07 11:53:17 +0200
commit4591c0032871d1ff2682463cfffd94ca31f3ba2f (patch)
treeef2bfc961285a3779bb919bf12dd367f863f03f5 /Userland/DynamicLoader
parentc351b4ad0d148e08ce741061f3cfc38785c3186d (diff)
downloadserenity-4591c0032871d1ff2682463cfffd94ca31f3ba2f.zip
DynamicLoader: Don't use LibELF to do the initial relocations
Using LibELF to do the initial relocations doesn't work when building SerenityOS with Clang. We seem to be accessing a global symbol that hasn't been relocated yet somewhere along the path to ELF::DynamicObject::create().
Diffstat (limited to 'Userland/DynamicLoader')
-rw-r--r--Userland/DynamicLoader/main.cpp32
1 files changed, 25 insertions, 7 deletions
diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp
index 0712554cb8..6fecfbc60f 100644
--- a/Userland/DynamicLoader/main.cpp
+++ b/Userland/DynamicLoader/main.cpp
@@ -46,17 +46,35 @@ static void perform_self_relocations(auxv_t* auxvp)
if (!dynamic_section_addr)
exit(1);
- auto dynamic_object = ELF::DynamicObject::create({}, (VirtualAddress(base_address)), (VirtualAddress(dynamic_section_addr)));
+ FlatPtr relocation_section_addr = 0;
+ size_t relocation_table_size = 0;
+ size_t relocation_count = 0;
+ auto* dyns = reinterpret_cast<const ElfW(Dyn)*>(dynamic_section_addr);
+ for (unsigned i = 0;; ++i) {
+ auto& dyn = dyns[i];
+ if (dyn.d_tag == DT_NULL)
+ break;
+ if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELA)
+ relocation_section_addr = base_address + dyn.d_un.d_ptr;
+ else if (dyn.d_tag == DT_RELCOUNT || dyn.d_tag == DT_RELACOUNT)
+ relocation_count = dyn.d_un.d_val;
+ else if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+ relocation_table_size = dyn.d_un.d_val;
+ }
+ if (!relocation_section_addr || !relocation_table_size || !relocation_count)
+ exit(1);
- dynamic_object->relocation_section().for_each_relocation([base_address](auto& reloc) {
+ auto relocation_entry_size = relocation_table_size / relocation_count;
+ for (unsigned i = 0; i < relocation_count; ++i) {
+ size_t offset_in_section = i * relocation_entry_size;
+ auto* relocation = (ElfW(Rela)*)(relocation_section_addr + offset_in_section);
#if ARCH(I386)
- VERIFY(reloc.type() == R_386_RELATIVE);
+ VERIFY(ELF32_R_TYPE(relocation->r_info) == R_386_RELATIVE);
#else
- VERIFY(reloc.type() == R_X86_64_RELATIVE);
+ VERIFY(ELF64_R_TYPE(relocation->r_info) == R_X86_64_RELATIVE);
#endif
-
- *(FlatPtr*)reloc.address().as_ptr() += base_address;
- });
+ *(FlatPtr*)(base_address + relocation->r_offset) += base_address;
+ }
}
static void display_help()