Parcourir la source

DynamicLoader: Add RELA support for self-relocations

GCC doesn't seem to rely on those to work, but Clang does.
Gunnar Beutner il y a 4 ans
Parent
commit
2fc002f778
1 fichiers modifiés avec 7 ajouts et 1 suppressions
  1. 7 1
      Userland/DynamicLoader/main.cpp

+ 7 - 1
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;
     }
 }