From da0e5b885b25cf4ded0fa89b965dc6979ac02ca9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 29 Jan 2022 14:45:58 -0800 Subject: [PATCH] [ELF] Refactor -z combreloc * `RelocationBaseSection::addReloc` increases `numRelativeRelocs`, which duplicates the work done by RelocationSection::writeTo. * --pack-dyn-relocs=android has inappropropriate DT_RELACOUNT. AndroidPackedRelocationSection does not necessarily place relative relocations in the front and DT_RELACOUNT might cause semantics error (though our implementation doesn't and Android bionic doesn't use DT_RELACOUNT anyway.) Move `llvm::partition` to a new function `partitionRels` and compute `numRelativeRelocs` there. Now `RelocationBaseSection::addReloc` is trivial and can be moved to the header to enable inlining. The rest of DynamicReloc and `-z combreloc` handling is moved to the non-template `RelocationBaseSection::computeRels` to decrease code size. My x86-64 lld executable is 44+KiB smaller. While here, rename `sort` to `combreloc`. --- lld/ELF/SyntheticSections.cpp | 74 ++++++++++++------------ lld/ELF/SyntheticSections.h | 14 ++--- lld/ELF/Writer.cpp | 7 ++- lld/test/ELF/pack-dyn-relocs.s | 100 +++++++++++++++++---------------- 4 files changed, 101 insertions(+), 94 deletions(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f125e3f0a51a8..575a5afb84c18 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1589,9 +1589,11 @@ uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const { RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag, - int32_t sizeDynamicTag) + int32_t sizeDynamicTag, + bool combreloc) : SyntheticSection(SHF_ALLOC, type, config->wordsize, name), - dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {} + dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag), + combreloc(combreloc) {} void RelocationBaseSection::addSymbolReloc(RelType dynType, InputSectionBase &isec, @@ -1640,10 +1642,13 @@ void RelocationBaseSection::addReloc(DynamicReloc::Kind kind, RelType dynType, addReloc({dynType, &inputSec, offsetInSec, kind, sym, addend, expr}); } -void RelocationBaseSection::addReloc(const DynamicReloc &reloc) { - if (reloc.type == target->relativeRel) - ++numRelativeRelocs; - relocs.push_back(reloc); +void RelocationBaseSection::partitionRels() { + if (!combreloc) + return; + const RelType relativeRel = target->relativeRel; + numRelativeRelocs = + llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }) - + relocs.begin(); } void RelocationBaseSection::finalizeContents() { @@ -1667,20 +1672,6 @@ void RelocationBaseSection::finalizeContents() { } } -RelrBaseSection::RelrBaseSection() - : SyntheticSection(SHF_ALLOC, - config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, - config->wordsize, ".relr.dyn") {} - -template -static void encodeDynamicReloc(typename ELFT::Rela *p, - const DynamicReloc &rel) { - p->r_offset = rel.r_offset; - p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL); - if (config->isRela) - p->r_addend = rel.addend; -} - void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) { r_offset = getOffset(); r_sym = getSymIndex(symtab); @@ -1688,27 +1679,15 @@ void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) { kind = AddendOnly; // Catch errors } -template -RelocationSection::RelocationSection(StringRef name, bool sort) - : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, - config->isRela ? DT_RELA : DT_REL, - config->isRela ? DT_RELASZ : DT_RELSZ), - sort(sort) { - this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); -} - -template void RelocationSection::writeTo(uint8_t *buf) { +void RelocationBaseSection::computeRels() { SymbolTableBaseSection *symTab = getPartition().dynSymTab.get(); - parallelForEach(relocs, [symTab](DynamicReloc &rel) { rel.computeRaw(symTab); }); // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset // is to make results easier to read. - if (sort) { - const RelType relativeRel = target->relativeRel; - auto nonRelative = - llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }); + if (combreloc) { + auto nonRelative = relocs.begin() + numRelativeRelocs; parallelSort(relocs.begin(), nonRelative, [&](auto &a, auto &b) { return a.r_offset < b.r_offset; }); // Non-relative relocations are few, so don't bother with parallelSort. @@ -1716,20 +1695,41 @@ template void RelocationSection::writeTo(uint8_t *buf) { return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset); }); } +} + +template +RelocationSection::RelocationSection(StringRef name, bool combreloc) + : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, + config->isRela ? DT_RELA : DT_REL, + config->isRela ? DT_RELASZ : DT_RELSZ, combreloc) { + this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); +} +template void RelocationSection::writeTo(uint8_t *buf) { + computeRels(); for (const DynamicReloc &rel : relocs) { - encodeDynamicReloc(reinterpret_cast(buf), rel); + auto *p = reinterpret_cast(buf); + p->r_offset = rel.r_offset; + p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL); + if (config->isRela) + p->r_addend = rel.addend; buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } } +RelrBaseSection::RelrBaseSection() + : SyntheticSection(SHF_ALLOC, + config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, + config->wordsize, ".relr.dyn") {} + template AndroidPackedRelocationSection::AndroidPackedRelocationSection( StringRef name) : RelocationBaseSection( name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL, - config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { + config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ, + /*combreloc=*/false) { this->entsize = 1; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 9f4073048ce57..410639128e077 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -515,11 +515,11 @@ template class DynamicSection final : public SyntheticSection { class RelocationBaseSection : public SyntheticSection { public: RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag, - int32_t sizeDynamicTag); + int32_t sizeDynamicTag, bool combreloc); /// Add a dynamic relocation without writing an addend to the output section. /// This overload can be used if the addends are written directly instead of /// using relocations on the input section (e.g. MipsGotSection::writeTo()). - void addReloc(const DynamicReloc &reloc); + void addReloc(const DynamicReloc &reloc) { relocs.push_back(reloc); } /// Add a dynamic relocation against \p sym with an optional addend. void addSymbolReloc(RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym, int64_t addend = 0, @@ -541,6 +541,7 @@ class RelocationBaseSection : public SyntheticSection { bool isNeeded() const override { return !relocs.empty(); } size_t getSize() const override { return relocs.size() * this->entsize; } size_t getRelativeRelocCount() const { return numRelativeRelocs; } + void partitionRels(); void finalizeContents() override; static bool classof(const SectionBase *d) { return SyntheticSection::classof(d) && @@ -551,7 +552,9 @@ class RelocationBaseSection : public SyntheticSection { SmallVector relocs; protected: - size_t numRelativeRelocs = 0; + void computeRels(); + size_t numRelativeRelocs = 0; // used by -z combreloc + bool combreloc; }; template @@ -560,11 +563,8 @@ class RelocationSection final : public RelocationBaseSection { using Elf_Rela = typename ELFT::Rela; public: - RelocationSection(StringRef name, bool sort); + RelocationSection(StringRef name, bool combreloc); void writeTo(uint8_t *buf) override; - -private: - bool sort; }; template diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 69fcad390d614..8d44589706cbc 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2086,11 +2086,16 @@ template void Writer::finalizeSections() { // Dynamic section must be the last one in this list and dynamic // symbol table section (dynSymTab) must be the first one. for (Partition &part : partitions) { + if (part.relaDyn) { + // Compute DT_RELACOUNT to be used by part.dynamic. + part.relaDyn->partitionRels(); + finalizeSynthetic(part.relaDyn.get()); + } + finalizeSynthetic(part.dynSymTab.get()); finalizeSynthetic(part.gnuHashTab.get()); finalizeSynthetic(part.hashTab.get()); finalizeSynthetic(part.verDef.get()); - finalizeSynthetic(part.relaDyn.get()); finalizeSynthetic(part.relrDyn.get()); finalizeSynthetic(part.ehFrameHdr.get()); finalizeSynthetic(part.verSym.get()); diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s index eed26d824906e..da97e388c3d0c 100644 --- a/lld/test/ELF/pack-dyn-relocs.s +++ b/lld/test/ELF/pack-dyn-relocs.s @@ -77,15 +77,17 @@ /// by the larger groups of relative relocations (i.e. the 8 and 9 followed /// by the 7.) // ANDROID32: Section ({{.+}}) .rel.dyn { +// ANDROID32-NEXT: 0x3024C R_ARM_RELATIVE - +// ANDROID32-NEXT: 0x30250 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30254 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30258 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x3025C R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30260 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30264 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30268 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x3026C R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x30270 R_ARM_RELATIVE - +// ANDROID32-NEXT: 0x30294 R_ARM_RELATIVE - +// ANDROID32-NEXT: 0x30298 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x3029C R_ARM_RELATIVE - // ANDROID32-NEXT: 0x302A0 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x302A4 R_ARM_RELATIVE - @@ -93,26 +95,25 @@ // ANDROID32-NEXT: 0x302AC R_ARM_RELATIVE - // ANDROID32-NEXT: 0x302B0 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x302B4 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x302B8 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x302BC R_ARM_RELATIVE - + +// ANDROID32-NEXT: 0x30270 R_ARM_RELATIVE - +// ANDROID32-NEXT: 0x30274 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30278 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x3027C R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30280 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30284 R_ARM_RELATIVE - // ANDROID32-NEXT: 0x30288 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x3028C R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x30290 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x302C1 R_ARM_RELATIVE - -// ANDROID32-NEXT: 0x30274 R_ARM_ABS32 bar2 -// ANDROID32-NEXT: 0x30298 R_ARM_ABS32 bar2 +// ANDROID32-NEXT: 0x302B9 R_ARM_RELATIVE - + +// ANDROID32-NEXT: 0x3026C R_ARM_ABS32 bar2 +// ANDROID32-NEXT: 0x30290 R_ARM_ABS32 bar2 +// ANDROID32-NEXT: 0x302BD R_ARM_ABS32 bar2 +// ANDROID32-NEXT: 0x302C1 R_ARM_ABS32 bar2 // ANDROID32-NEXT: 0x302C5 R_ARM_ABS32 bar2 // ANDROID32-NEXT: 0x302C9 R_ARM_ABS32 bar2 // ANDROID32-NEXT: 0x302CD R_ARM_ABS32 bar2 -// ANDROID32-NEXT: 0x302D1 R_ARM_ABS32 bar2 -// ANDROID32-NEXT: 0x302D5 R_ARM_ABS32 bar2 - -// ANDROID32-NEXT: 0x30294 R_ARM_ABS32 zed2 0x0 +// ANDROID32-NEXT: 0x3028C R_ARM_ABS32 zed2 // ANDROID32-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32.o %t.a32.so -o %t4.a32 @@ -225,6 +226,7 @@ // UNPACKED64-NEXT: 0x30760 R_AARCH64_RELATIVE - 0x9 // UNPACKED64-NEXT: 0x30769 R_AARCH64_RELATIVE - 0xA + // UNPACKED64-NEXT: 0x306D0 R_AARCH64_ABS64 bar2 0x1 // UNPACKED64-NEXT: 0x30718 R_AARCH64_ABS64 bar2 0x0 // UNPACKED64-NEXT: 0x30771 R_AARCH64_ABS64 bar2 0x0 @@ -259,42 +261,42 @@ // ANDROID64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]] // ANDROID64: Section ({{.+}}) .rela.dyn { -// ANDROID64-NEXT: 0x303F0 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x303F8 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x30400 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x30408 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x30410 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x30418 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x30420 R_AARCH64_RELATIVE - 0x7 -// ANDROID64-NEXT: 0x30428 R_AARCH64_RELATIVE - 0x8 - -// ANDROID64-NEXT: 0x30480 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x30488 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x30490 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x30498 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x304A0 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x304A8 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x304B0 R_AARCH64_RELATIVE - 0x7 -// ANDROID64-NEXT: 0x304B8 R_AARCH64_RELATIVE - 0x8 -// ANDROID64-NEXT: 0x304C0 R_AARCH64_RELATIVE - 0x9 - -// ANDROID64-NEXT: 0x30438 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x30440 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x30448 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x30450 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x30458 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x30460 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x30468 R_AARCH64_RELATIVE - 0x7 -// ANDROID64-NEXT: 0x304C9 R_AARCH64_RELATIVE - 0xA - -// ANDROID64-NEXT: 0x30478 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304D1 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304D9 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304F1 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x30430 R_AARCH64_ABS64 bar2 0x1 -// ANDROID64-NEXT: 0x30470 R_AARCH64_ABS64 zed2 0x0 -// ANDROID64-NEXT: 0x304E1 R_AARCH64_ABS64 bar2 0x1 -// ANDROID64-NEXT: 0x304E9 R_AARCH64_ABS64 bar2 0x1 +// ANDROID64-NEXT: 0x303E0 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x303E8 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x303F0 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x303F8 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x30400 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x30408 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x30410 R_AARCH64_RELATIVE - 0x7 +// ANDROID64-NEXT: 0x30418 R_AARCH64_RELATIVE - 0x8 +// ANDROID64-NEXT: 0x30470 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x30478 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x30480 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x30488 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x30490 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x30498 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x304A0 R_AARCH64_RELATIVE - 0x7 +// ANDROID64-NEXT: 0x304A8 R_AARCH64_RELATIVE - 0x8 +// ANDROID64-NEXT: 0x304B0 R_AARCH64_RELATIVE - 0x9 + +// ANDROID64-NEXT: 0x30428 R_AARCH64_RELATIVE - 0x1 +// ANDROID64-NEXT: 0x30430 R_AARCH64_RELATIVE - 0x2 +// ANDROID64-NEXT: 0x30438 R_AARCH64_RELATIVE - 0x3 +// ANDROID64-NEXT: 0x30440 R_AARCH64_RELATIVE - 0x4 +// ANDROID64-NEXT: 0x30448 R_AARCH64_RELATIVE - 0x5 +// ANDROID64-NEXT: 0x30450 R_AARCH64_RELATIVE - 0x6 +// ANDROID64-NEXT: 0x30458 R_AARCH64_RELATIVE - 0x7 + +// ANDROID64-NEXT: 0x304B9 R_AARCH64_RELATIVE - 0xA + +// ANDROID64-NEXT: 0x30468 R_AARCH64_ABS64 bar2 0x0 +// ANDROID64-NEXT: 0x304C1 R_AARCH64_ABS64 bar2 0x0 +// ANDROID64-NEXT: 0x304C9 R_AARCH64_ABS64 bar2 0x0 +// ANDROID64-NEXT: 0x304E1 R_AARCH64_ABS64 bar2 0x0 +// ANDROID64-NEXT: 0x30420 R_AARCH64_ABS64 bar2 0x1 +// ANDROID64-NEXT: 0x30460 R_AARCH64_ABS64 zed2 0x0 +// ANDROID64-NEXT: 0x304D1 R_AARCH64_ABS64 bar2 0x1 +// ANDROID64-NEXT: 0x304D9 R_AARCH64_ABS64 bar2 0x1 // ANDROID64-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64.o %t.a64.so -o %t4.a64