1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:17:45 +00:00

DynamicLoader+LibELF: Move self-relocation code into a separate file

This commit is contained in:
Gunnar Beutner 2021-07-26 15:03:29 +02:00 committed by Andreas Kling
parent 3c616ae00f
commit daeb371180
4 changed files with 85 additions and 45 deletions

View file

@ -8,6 +8,7 @@
#include <LibC/unistd.h>
#include <LibELF/AuxiliaryVector.h>
#include <LibELF/DynamicLinker.h>
#include <LibELF/Relocation.h>
char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds..
@ -35,52 +36,8 @@ static void perform_self_relocations(auxv_t* auxvp)
}
}
VERIFY(found_base_address);
ElfW(Ehdr)* header = (ElfW(Ehdr)*)(base_address);
ElfW(Phdr)* pheader = (ElfW(Phdr)*)(base_address + header->e_phoff);
FlatPtr dynamic_section_addr = 0;
for (size_t i = 0; i < (size_t)header->e_phnum; ++i, ++pheader) {
if (pheader->p_type != PT_DYNAMIC)
continue;
dynamic_section_addr = pheader->p_vaddr + base_address;
}
if (!dynamic_section_addr)
if (!ELF::perform_relative_relocations(base_address))
exit(1);
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)
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);
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(ELF32_R_TYPE(relocation->r_info) == R_386_RELATIVE);
#else
VERIFY(ELF64_R_TYPE(relocation->r_info) == R_X86_64_RELATIVE);
#endif
if (use_addend)
*(FlatPtr*)(base_address + relocation->r_offset) = base_address + relocation->r_addend;
else
*(FlatPtr*)(base_address + relocation->r_offset) += base_address;
}
}
static void display_help()