Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -686,6 +686,8 @@ // Try and find an appropriate memory region to assign offsets in. for (BaseCommand *Base : Opt.Commands) { if (auto *Sec = dyn_cast(Base)) { + if (!Sec->Live) + continue; Sec->MemRegion = findMemoryRegion(Sec); // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (Sec->AlignExpr) @@ -722,8 +724,6 @@ DefPhdrs = Sec->Phdrs; } } - - removeEmptyCommands(); } static OutputSection *findFirstSection(PhdrEntry *Load) { Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1071,8 +1071,7 @@ } template void Writer::sortSections() { - if (Script->Opt.HasSections) - Script->adjustSectionsBeforeSorting(); + Script->adjustSectionsBeforeSorting(); // Don't sort if using -r. It is not necessary and we want to preserve the // relative order for SHF_LINK_ORDER sections. @@ -1200,24 +1199,25 @@ if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable) continue; - std::vector::iterator Empty = OS->Commands.end(); - for (auto I = OS->Commands.begin(), E = OS->Commands.end(); I != E; ++I) { - BaseCommand *B = *I; + // SS is an unused synthetic section. Remove it from output section command. + for (BaseCommand *B : OS->Commands) { if (auto *ISD = dyn_cast(B)) { - llvm::erase_if(ISD->Sections, - [=](InputSection *IS) { return IS == SS; }); - if (ISD->Sections.empty()) - Empty = I; + auto It = llvm::find(ISD->Sections, SS); + if (It == ISD->Sections.end()) + continue; + ISD->Sections.erase(It); + break; } } - if (Empty != OS->Commands.end()) - OS->Commands.erase(Empty); - // If there are no other sections in the output section, remove it from the - // output. - if (OS->Commands.empty()) - llvm::erase_if(Script->Opt.Commands, - [&](BaseCommand *Cmd) { return Cmd == OS; }); + // If output section now contains no any other input sections + // and no other commands, mark is as dead. + bool IsEmpty = llvm::all_of(OS->Commands, [](BaseCommand *B) { + auto *ISD = dyn_cast(B); + return ISD && ISD->Sections.empty(); + }); + if (IsEmpty) + OS->Live = false; } } @@ -1326,6 +1326,7 @@ removeUnusedSyntheticSections(); sortSections(); + Script->removeEmptyCommands(); // Now that we have the final list, create a list of all the // OutputSections for convenience. Index: test/ELF/linkerscript/unused-synthetic.s =================================================================== --- test/ELF/linkerscript/unused-synthetic.s +++ test/ELF/linkerscript/unused-synthetic.s @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: echo "SECTIONS { \ -# RUN: .got : { *(.got) } \ +# RUN: .got : { *(.got) *(.got) } \ # RUN: .plt : { *(.plt) } \ # RUN: .text : { *(.text) } \ # RUN: }" > %t.script