Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -254,7 +254,6 @@ ExprValue getSymbolValue(StringRef Name, const Twine &Loc); void addOrphanSections(); - void removeEmptyCommands(); void adjustSectionsBeforeSorting(); void adjustSectionsAfterSorting(); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -752,21 +752,12 @@ } } -void LinkerScript::removeEmptyCommands() { - // It is common practice to use very generic linker scripts. So for any - // given run some of the output sections in the script will be empty. - // We could create corresponding empty output sections, but that would - // clutter the output. - // We instead remove trivially empty sections. The bfd linker seems even - // more aggressive at removing them. - llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { - if (auto *Sec = dyn_cast(Base)) - return !Sec->Live; +static bool isAllSectionDescription(const OutputSection &Cmd) { + // We do not remove empty sections that are explicitly + // assigned to any segment. + if (!Cmd.Phdrs.empty()) return false; - }); -} -static bool isAllSectionDescription(const OutputSection &Cmd) { for (BaseCommand *Base : Cmd.SectionCommands) if (!isa(*Base)) return false; @@ -796,7 +787,7 @@ // the previous sections. Only a few flags are needed to keep the impact low. uint64_t Flags = SHF_ALLOC; - for (BaseCommand *Cmd : SectionCommands) { + for (BaseCommand *&Cmd : SectionCommands) { auto *Sec = dyn_cast(Cmd); if (!Sec) continue; @@ -805,20 +796,25 @@ continue; } - if (isAllSectionDescription(*Sec)) - continue; - - Sec->Live = true; - Sec->Flags = Flags; + if (!isAllSectionDescription(*Sec)) + Sec->Flags = Flags; + else + Cmd = nullptr; } + + // It is common practice to use very generic linker scripts. So for any + // given run some of the output sections in the script will be empty. + // We could create corresponding empty output sections, but that would + // clutter the output. + // We instead remove trivially empty sections. The bfd linker seems even + // more aggressive at removing them. + llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; }); } void LinkerScript::adjustSectionsAfterSorting() { // Try and find an appropriate memory region to assign offsets in. for (BaseCommand *Base : SectionCommands) { if (auto *Sec = dyn_cast(Base)) { - if (!Sec->Live) - continue; if (!Sec->LMARegionName.empty()) { if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName)) Sec->LMARegion = M; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -937,8 +937,7 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) { if (auto *Sec = dyn_cast(B)) - if (Sec->Live) - return getRankProximityAux(A, Sec); + return getRankProximityAux(A, Sec); return -1; } @@ -984,20 +983,16 @@ int Proximity = getRankProximity(Sec, *I); for (; I != E; ++I) { auto *CurSec = dyn_cast(*I); - if (!CurSec || !CurSec->Live) + if (!CurSec) continue; if (getRankProximity(Sec, CurSec) != Proximity || Sec->SortRank < CurSec->SortRank) break; } - auto IsLiveSection = [](BaseCommand *Cmd) { - auto *OS = dyn_cast(Cmd); - return OS && OS->Live; - }; - + auto IsOutputSec = [](BaseCommand *Cmd) { return isa(Cmd); }; auto J = std::find_if(llvm::make_reverse_iterator(I), - llvm::make_reverse_iterator(B), IsLiveSection); + llvm::make_reverse_iterator(B), IsOutputSec); I = J.base(); // As a special case, if the orphan section is the last section, put @@ -1005,7 +1000,7 @@ // This matches bfd's behavior and is convenient when the linker script fully // specifies the start of the file, but doesn't care about the end (the non // alloc sections for example). - auto NextSec = std::find_if(I, E, IsLiveSection); + auto NextSec = std::find_if(I, E, IsOutputSec); if (NextSec == E) return E; @@ -1077,8 +1072,6 @@ static void sortSection(OutputSection *Sec, const DenseMap &Order) { - if (!Sec->Live) - return; StringRef Name = Sec->Name; // Sort input sections by section name suffixes for @@ -1186,7 +1179,7 @@ auto E = Script->SectionCommands.end(); auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) { if (auto *Sec = dyn_cast(Base)) - return Sec->Live && Sec->SectionIndex == INT_MAX; + return Sec->SectionIndex == INT_MAX; return false; }); @@ -1505,7 +1498,6 @@ removeUnusedSyntheticSections(); sortSections(); - Script->removeEmptyCommands(); // Now that we have the final list, create a list of all the // OutputSections for convenience. Index: test/ELF/linkerscript/implicit-program-header.s =================================================================== --- test/ELF/linkerscript/implicit-program-header.s +++ test/ELF/linkerscript/implicit-program-header.s @@ -15,7 +15,7 @@ # CHECK: Segment Sections... # CHECK-NEXT: 00 .text .dynsym .hash .dynstr .dynamic -# CHECK-NEXT: 01 .foo +# CHECK-NEXT: 01 .bar .foo .quad 0 .section .foo,"ax" Index: test/ELF/linkerscript/orphan-phdrs.s =================================================================== --- test/ELF/linkerscript/orphan-phdrs.s +++ test/ELF/linkerscript/orphan-phdrs.s @@ -18,6 +18,7 @@ # CHECK: Section Headers # CHECK: .text # CHECK-NEXT: .orphan +# CHECK-NEXT: .empty # CHECK-NEXT: .rw # CHECK: Segment Sections