diff options
-rw-r--r-- | src/patchelf.cc | 20 | ||||
-rw-r--r-- | src/patchelf.h | 27 |
2 files changed, 25 insertions, 22 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc index a4388f9..db18837 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -2013,20 +2013,10 @@ void ElfFile<ElfFileParamNames>::rebuildGnuHashTable(span<char> strTab, span<Elf if (versyms) reorderSpan(versyms, old2new); - auto fixRelocationTable = [&old2new, firstSymIdx, this] <class ER> (auto& hdr) + auto remapSymbolId = [&old2new, firstSymIdx] (auto& oldSymIdx) { - auto rela = getSectionSpan<ER>(hdr); - for (auto& r : rela) - { - auto info = rdi(r.r_info); - auto oldSymIdx = rel_getSymId(info); - if (oldSymIdx >= firstSymIdx) - { - auto newSymIdx = old2new[oldSymIdx - firstSymIdx] + firstSymIdx; - if (newSymIdx != oldSymIdx) - wri(r.r_info, rel_setSymId(info, newSymIdx)); - } - } + return oldSymIdx >= firstSymIdx ? old2new[oldSymIdx - firstSymIdx] + firstSymIdx + : oldSymIdx; }; for (unsigned int i = 1; i < rdi(hdr()->e_shnum); ++i) @@ -2034,9 +2024,9 @@ void ElfFile<ElfFileParamNames>::rebuildGnuHashTable(span<char> strTab, span<Elf auto& shdr = shdrs.at(i); auto shtype = rdi(shdr.sh_type); if (shtype == SHT_REL) - fixRelocationTable.template operator()<Elf_Rel>(shdr); + changeRelocTableSymIds<Elf_Rel>(shdr, remapSymbolId); else if (shtype == SHT_RELA) - fixRelocationTable.template operator()<Elf_Rela>(shdr); + changeRelocTableSymIds<Elf_Rela>(shdr, remapSymbolId); } // Update bloom filters diff --git a/src/patchelf.h b/src/patchelf.h index 8f96ec6..9fab18c 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -169,6 +169,13 @@ public: void renameDynamicSymbols(const std::unordered_map<std::string_view, std::string>&); + void clearSymbolVersions(const std::set<std::string> & syms); + + enum class ExecstackMode { print, set, clear }; + + void modifyExecstack(ExecstackMode op); + +private: struct GnuHashTable { using BloomWord = Elf_Addr; struct Header { @@ -215,14 +222,20 @@ public: return info; } + template<class ElfRelType, class RemapFn> + void changeRelocTableSymIds(const Elf_Shdr& shdr, RemapFn&& old2newSymId) + { + static_assert(std::is_same_v<ElfRelType, Elf_Rel> || std::is_same_v<ElfRelType, Elf_Rela>); - void clearSymbolVersions(const std::set<std::string> & syms); - - enum class ExecstackMode { print, set, clear }; - - void modifyExecstack(ExecstackMode op); - -private: + for (auto& r : getSectionSpan<ElfRelType>(shdr)) + { + auto info = rdi(r.r_info); + auto oldSymIdx = rel_getSymId(info); + auto newSymIdx = old2newSymId(oldSymIdx); + if (newSymIdx != oldSymIdx) + wri(r.r_info, rel_setSymId(info, newSymIdx)); + } + } /* Convert an integer in big or little endian representation (as specified by the ELF header) to this platform's integer |