summaryrefslogtreecommitdiff
path: root/Userland/DynamicLoader/main.cpp
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-07-13 14:11:12 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-13 23:20:36 +0200
commit2fc002f77820fcbb5c1e97391a4ca589eac19e9d (patch)
tree3d85a55bdbf48f5979612c41706c5c2c2dd9d439 /Userland/DynamicLoader/main.cpp
parent42eb06f0459865ca9e6316012ab7d29cde6bdc05 (diff)
downloadserenity-2fc002f77820fcbb5c1e97391a4ca589eac19e9d.zip
DynamicLoader: Add RELA support for self-relocations
GCC doesn't seem to rely on those to work, but Clang does.
Diffstat (limited to 'Userland/DynamicLoader/main.cpp')
-rw-r--r--Userland/DynamicLoader/main.cpp8
1 files changed, 7 insertions, 1 deletions
diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp
index efee7a8f30..74d122f820 100644
--- a/Userland/DynamicLoader/main.cpp
+++ b/Userland/DynamicLoader/main.cpp
@@ -49,11 +49,14 @@ static void perform_self_relocations(auxv_t* auxvp)
FlatPtr relocation_section_addr = 0;
size_t relocation_table_size = 0;
size_t relocation_count = 0;
+ bool use_addend = false;
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_RELA)
+ use_addend = true;
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)
@@ -73,7 +76,10 @@ static void perform_self_relocations(auxv_t* auxvp)
#else
VERIFY(ELF64_R_TYPE(relocation->r_info) == R_X86_64_RELATIVE);
#endif
- *(FlatPtr*)(base_address + relocation->r_offset) += base_address;
+ if (use_addend)
+ *(FlatPtr*)(base_address + relocation->r_offset) = base_address + relocation->r_addend;
+ else
+ *(FlatPtr*)(base_address + relocation->r_offset) += base_address;
}
}