Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/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" @@ -43,7 +44,6 @@ #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Object/Decompressor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Path.h" @@ -1001,24 +1001,20 @@ for (InputSectionBase *S : F->getSections()) InputSections.push_back(cast(S)); - // Do size optimizations: garbage collection and identical code folding. + // This adds a .comment section containing a version string. We have to add it + // before decompressAndMergeSections because the .comment section is a + // mergeable section. + if (!Config->Relocatable) + InputSections.push_back(createCommentSection()); + + // Do size optimizations: garbage collection, merging of SHF_MERGE sections + // and identical code folding. if (Config->GcSections) markLive(); + decompressAndMergeSections(); if (Config->ICF) doIcf(); - // MergeInputSection::splitIntoPieces needs to be called before - // any call of MergeInputSection::getOffset. Do that. - parallelForEach(InputSections.begin(), InputSections.end(), - [](InputSectionBase *S) { - if (!S->Live) - return; - if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) - S->uncompress(); - if (auto *MS = dyn_cast(S)) - MS->splitIntoPieces(); - }); - // Write the result to the file. writeResult(); } Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/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 decompressAndMergeSections(); SymbolBody *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, uint64_t Size, InputSectionBase *Section); Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -29,6 +29,7 @@ #include "lld/Config/Version.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MD5.h" @@ -2133,7 +2134,6 @@ Builder(StringTableBuilder::RAW, Alignment) {} void MergeSyntheticSection::addSection(MergeInputSection *MS) { - assert(!Finalized); MS->Parent = this; Sections.push_back(MS); } @@ -2178,9 +2178,6 @@ } void MergeSyntheticSection::finalizeContents() { - if (Finalized) - return; - Finalized = true; if (shouldTailMerge()) finalizeTailMerge(); else @@ -2188,11 +2185,65 @@ } size_t MergeSyntheticSection::getSize() const { - // We should finalize string builder to know the size. - const_cast(this)->finalizeContents(); return Builder.getSize(); } +// This function decompresses compressed sections and scans over the input +// sections to create 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::decompressAndMergeSections() { + // splitIntoPieces needs to be called on each MergeInputSection before calling + // finalizeContents(). Do that first. + parallelForEach(InputSections.begin(), InputSections.end(), + [](InputSectionBase *S) { + if (!S->Live) + return; + if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) + S->uncompress(); + if (auto *MS = dyn_cast(S)) + MS->splitIntoPieces(); + }); + + 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/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/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);