Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -36,6 +36,7 @@ #include "ScriptParser.h" #include "Strings.h" #include "SymbolTable.h" +#include "SyntheticSections.h" #include "Target.h" #include "Threads.h" #include "Writer.h" @@ -1000,15 +1001,16 @@ for (BinaryFile *F : Symtab.getBinaryFiles()) for (InputSectionBase *S : F->getSections()) InputSections.push_back(cast(S)); + if (!Config->Relocatable) + InputSections.push_back(createCommentSection()); - // Do size optimizations: garbage collection and identical code folding. + // Do size optimizations: garbage collection, merging of SHF_MERGE sections + // and identical code folding. if (Config->GcSections) markLive(); - if (Config->ICF) - doIcf(); - // MergeInputSection::splitIntoPieces needs to be called before - // any call of MergeInputSection::getOffset. Do that. + // splitIntoPieces needs to be called on each MergeInputSection before calling + // mergeSections(). Do that first. parallelForEach(InputSections.begin(), InputSections.end(), [](InputSectionBase *S) { if (!S->Live) @@ -1018,6 +1020,10 @@ if (auto *MS = dyn_cast(S)) MS->splitIntoPieces(); }); + mergeSections(); + + if (Config->ICF) + doIcf(); // Write the result to the file. writeResult(); Index: lld/ELF/SyntheticSections.h =================================================================== --- lld/ELF/SyntheticSections.h +++ lld/ELF/SyntheticSections.h @@ -651,7 +651,6 @@ void finalizeTailMerge(); void finalizeNoTailMerge(); - bool Finalized = false; llvm::StringTableBuilder Builder; std::vector Sections; }; @@ -748,6 +747,7 @@ template InputSection *createCommonSection(); InputSection *createInterpSection(); template MergeInputSection *createCommentSection(); +void mergeSections(); SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, uint64_t Size, InputSectionBase *Section); Index: lld/ELF/SyntheticSections.cpp =================================================================== --- lld/ELF/SyntheticSections.cpp +++ lld/ELF/SyntheticSections.cpp @@ -2133,7 +2133,6 @@ Builder(StringTableBuilder::RAW, Alignment) {} void MergeSyntheticSection::addSection(MergeInputSection *MS) { - assert(!Finalized); MS->Parent = this; Sections.push_back(MS); } @@ -2178,9 +2177,6 @@ } void MergeSyntheticSection::finalizeContents() { - if (Finalized) - return; - Finalized = true; if (shouldTailMerge()) finalizeTailMerge(); else @@ -2188,11 +2184,52 @@ } size_t MergeSyntheticSection::getSize() const { - // We should finalize string builder to know the size. - const_cast(this)->finalizeContents(); return Builder.getSize(); } +// This function scans over the input sections and creates mergeable synthetic +// sections. It removes MergeInputSections from the input section array and adds +// new synthetic sections at the location of the first input section that it +// replaces. It then finalizes each synthetic section in order to compute an +// output offset for each piece of each input section. +void elf::mergeSections() { + std::vector MergeSections; + for (InputSectionBase *&S : InputSections) { + MergeInputSection *MS = dyn_cast(S); + if (!MS) + continue; + + // We do not want to handle sections that are not alive, so just remove + // them instead of trying to merge. + if (!MS->Live) + continue; + + StringRef OutsecName = getOutputSectionName(MS->Name); + uint64_t Flags = MS->Flags & ~(uint64_t)SHF_GROUP; + uint32_t Alignment = std::max(MS->Alignment, MS->Entsize); + + auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { + return Sec->Name == OutsecName && Sec->Flags == Flags && + Sec->Alignment == Alignment; + }); + if (I == MergeSections.end()) { + MergeSyntheticSection *Syn = + make(OutsecName, MS->Type, Flags, Alignment); + MergeSections.push_back(Syn); + I = std::prev(MergeSections.end()); + S = Syn; + } else { + S = nullptr; + } + (*I)->addSection(MS); + } + for (auto *MS : MergeSections) + MS->finalizeContents(); + + std::vector &V = InputSections; + V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); +} + MipsRldMapSection::MipsRldMapSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -137,46 +137,6 @@ Phdrs.erase(I, Phdrs.end()); } -// This function scans over the input sections and creates mergeable -// synthetic sections. It removes MergeInputSections from array and -// adds new synthetic ones. Each synthetic section is added to the -// location of the first input section it replaces. -static void combineMergableSections() { - std::vector MergeSections; - for (InputSectionBase *&S : InputSections) { - MergeInputSection *MS = dyn_cast(S); - if (!MS) - continue; - - // We do not want to handle sections that are not alive, so just remove - // them instead of trying to merge. - if (!MS->Live) - continue; - - StringRef OutsecName = getOutputSectionName(MS->Name); - uint64_t Flags = MS->Flags & ~(uint64_t)SHF_GROUP; - uint32_t Alignment = std::max(MS->Alignment, MS->Entsize); - - auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { - return Sec->Name == OutsecName && Sec->Flags == Flags && - Sec->Alignment == Alignment; - }); - if (I == MergeSections.end()) { - MergeSyntheticSection *Syn = - make(OutsecName, MS->Type, Flags, Alignment); - MergeSections.push_back(Syn); - I = std::prev(MergeSections.end()); - S = Syn; - } else { - S = nullptr; - } - (*I)->addSection(MS); - } - - std::vector &V = InputSections; - V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); -} - template static void combineEhFrameSections() { for (InputSectionBase *&S : InputSections) { EhInputSection *ES = dyn_cast(S); @@ -205,7 +165,6 @@ // Create linker-synthesized sections such as .got or .plt. // Such sections are of type input section. createSyntheticSections(); - combineMergableSections(); if (!Config->Relocatable) combineEhFrameSections(); @@ -340,9 +299,6 @@ InX::Interp = nullptr; } - if (!Config->Relocatable) - Add(createCommentSection()); - if (Config->Strip != StripPolicy::All) { InX::StrTab = make(".strtab", false); InX::SymTab = make>(*InX::StrTab);