From d36d67a336f299899a0329c981445588cf340bba Mon Sep 17 00:00:00 2001 From: Qwinci <32550582+Qwinci@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:56:48 +0200 Subject: [PATCH] options/rtdl: Unify late relocation code --- options/rtdl/generic/linker.cpp | 60 +++++++++++++-------------------- options/rtdl/generic/linker.hpp | 6 +++- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/options/rtdl/generic/linker.cpp b/options/rtdl/generic/linker.cpp index 92ebadb8f0..9f1a98bc01 100644 --- a/options/rtdl/generic/linker.cpp +++ b/options/rtdl/generic/linker.cpp @@ -776,43 +776,29 @@ SharedObject::SharedObject(const char *name, const char *path, frg::string { path, getAllocator() }, is_main_object, localScope, object_rts) {} -void processCopyRela(SharedObject *object, elf_rela *reloc) { - auto type = ELF_R_TYPE(reloc->r_info); - auto symbol_index = ELF_R_SYM(reloc->r_info); - - if(type != R_COPY) - return; - - uintptr_t rel_addr = object->baseAddress + reloc->r_offset; - - auto symbol = (elf_sym *)(object->baseAddress + object->symbolTableOffset - + symbol_index * sizeof(elf_sym)); - ObjectSymbol r(object, symbol); - frg::optional p = Scope::resolveGlobalOrLocal(*globalScope, object->localScope, r.getString(), object->objectRts, Scope::resolveCopy); - __ensure(p); - - memcpy((void *)rel_addr, (void *)p->virtualAddress(), symbol->st_size); -} - -void processCopyRel(SharedObject *object, elf_rel *reloc) { - auto type = ELF_R_TYPE(reloc->r_info); - auto symbol_index = ELF_R_SYM(reloc->r_info); - - if(type != R_COPY) - return; - - uintptr_t rel_addr = object->baseAddress + reloc->r_offset; +void processLateRelocation(Relocation rel) { + // resolve the symbol if there is a symbol + frg::optional p; + if(rel.symbol_index()) { + auto symbol = (elf_sym *)(rel.object()->baseAddress + rel.object()->symbolTableOffset + + rel.symbol_index() * sizeof(elf_sym)); + ObjectSymbol r(rel.object(), symbol); - auto symbol = (elf_sym *)(object->baseAddress + object->symbolTableOffset - + symbol_index * sizeof(elf_sym)); - ObjectSymbol r(object, symbol); - frg::optional p = Scope::resolveGlobalOrLocal(*globalScope, object->localScope, r.getString(), object->objectRts, Scope::resolveCopy); - __ensure(p); + p = Scope::resolveGlobalOrLocal(*globalScope, rel.object()->localScope, + r.getString(), rel.object()->objectRts, Scope::resolveCopy); + __ensure(p); + } - memcpy((void *)rel_addr, (void *)p->virtualAddress(), symbol->st_size); + switch(rel.type()) { + case R_COPY: + memcpy(rel.destination(), (void *)p->virtualAddress(), p->symbol()->st_size); + break; + default: + __ensure(!"Unknown late relocation type"); + } } -void processCopyRelocations(SharedObject *object) { +void processLateRelocations(SharedObject *object) { frg::optional rel_offset; frg::optional rel_length; @@ -847,12 +833,14 @@ void processCopyRelocations(SharedObject *object) { if(rela_offset && rela_length) { for(size_t offset = 0; offset < *rela_length; offset += sizeof(elf_rela)) { auto reloc = (elf_rela *)(object->baseAddress + *rela_offset + offset); - processCopyRela(object, reloc); + auto r = Relocation(object, reloc); + processLateRelocation(r); } } else if(rel_offset && rel_length) { for(size_t offset = 0; offset < *rel_length; offset += sizeof(elf_rel)) { auto reloc = (elf_rel *)(object->baseAddress + *rel_offset + offset); - processCopyRel(object, reloc); + auto r = Relocation(object, reloc); + processLateRelocation(r); } }else{ __ensure(!rela_offset && !rela_length); @@ -1315,7 +1303,7 @@ void Loader::linkObjects(SharedObject *root) { if(object->dynamic == nullptr) continue; - processCopyRelocations(object); + processLateRelocations(object); } for(auto object : _linkBfs) { diff --git a/options/rtdl/generic/linker.hpp b/options/rtdl/generic/linker.hpp index 7bff069418..620f5fc050 100644 --- a/options/rtdl/generic/linker.hpp +++ b/options/rtdl/generic/linker.hpp @@ -233,8 +233,12 @@ struct Relocation { __builtin_unreachable(); } + void *destination() { + return reinterpret_cast(object_->baseAddress + offset_); + } + void relocate(elf_addr addr) { - auto ptr = reinterpret_cast(object_->baseAddress + offset_); + auto ptr = destination(); memcpy(ptr, &addr, sizeof(addr)); }