Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -159,8 +159,6 @@ // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; - void filter(); - int getSectionIndex(StringRef Name); std::vector getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -256,27 +256,42 @@ } template +static bool matchConstraints(ArrayRef *> Sections, + ConstraintKind Kind) { + return !llvm::any_of(Sections, [=](InputSectionBase *Sec) { + bool Writable = Sec->getSectionHdr()->sh_flags & SHF_WRITE; + bool RO = (Kind == ConstraintKind::ReadOnly); + bool RW = (Kind == ConstraintKind::ReadWrite); + return (RO && Writable) || (RW && !Writable); + }); +} + +template void LinkerScript::createSections( OutputSectionFactory &Factory) { OutputSectionBuilder Builder(Factory, OutputSections); - auto Add = [&](StringRef OutputName, const InputSectionDescription *Cmd) { - std::vector *> Sections = getInputSections(Cmd); - if (OutputName == "/DISCARD/") { + auto Add = [&](const OutputSectionCommand *OutCmd, + const InputSectionDescription *InCmd) { + std::vector *> Sections = getInputSections(InCmd); + if (OutCmd->Name == "/DISCARD/") { for (InputSectionBase *S : Sections) { S->Live = false; reportDiscarded(S); } return; } - if (Cmd->SortInner) + if (!matchConstraints(Sections, OutCmd->Constraint)) + return; + + if (InCmd->SortInner) std::stable_sort(Sections.begin(), Sections.end(), - getComparator(Cmd->SortInner)); - if (Cmd->SortOuter) + getComparator(InCmd->SortInner)); + if (InCmd->SortOuter) std::stable_sort(Sections.begin(), Sections.end(), - getComparator(Cmd->SortOuter)); + getComparator(InCmd->SortOuter)); for (InputSectionBase *S : Sections) - Builder.addSection(OutputName, S); + Builder.addSection(OutCmd->Name, S); }; for (const std::unique_ptr &Base1 : Opt.Commands) @@ -285,7 +300,7 @@ if (auto *Assignment = dyn_cast(Base2.get())) Builder.addSymbol(Assignment); else - Add(Cmd->Name, cast(Base2.get())); + Add(Cmd, cast(Base2.get())); Builder.flushSection(); } else if (auto *Cmd2 = dyn_cast(Base1.get())) { @@ -298,41 +313,9 @@ for (InputSectionBase *S : F->getSections()) if (!isDiscarded(S) && !S->OutSec) Builder.addSection(getOutputSectionName(S), S); - - // Remove from the output all the sections which did not meet - // the optional constraints. - filter(); Builder.finalize(); } -template -static inline void removeElementsIf(R &Range, const T &Pred) { - Range.erase(std::remove_if(Range.begin(), Range.end(), Pred), Range.end()); -} - -// Process ONLY_IF_RO and ONLY_IF_RW. -template void LinkerScript::filter() { - // In this loop, we remove output sections if they don't satisfy - // requested properties. - for (const std::unique_ptr &Base : Opt.Commands) { - auto *Cmd = dyn_cast(Base.get()); - if (!Cmd || Cmd->Name == "/DISCARD/") - continue; - - if (Cmd->Constraint == ConstraintKind::NoConstraint) - continue; - - bool RO = (Cmd->Constraint == ConstraintKind::ReadOnly); - bool RW = (Cmd->Constraint == ConstraintKind::ReadWrite); - - removeElementsIf(*OutputSections, [&](OutputSectionBase *S) { - bool Writable = (S->getFlags() & SHF_WRITE); - return S->getName() == Cmd->Name && - ((RO && Writable) || (RW && !Writable)); - }); - } -} - template void assignOffsets(OutputSectionBase *Sec) { // Non-zero size means we have assigned offsets earlier in // OutputSectionBuilder::finalize @@ -355,7 +338,7 @@ I->OutSecOff = Off; Off += I->getSize(); } - // Update section size inside for-loop, so that SIZEOF + // Update section size inside for-loop, so that SIZEOF // works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } Sec->setSize(Off); Index: test/ELF/linkerscript/linkerscript-multi-sections-constraint.s =================================================================== --- test/ELF/linkerscript/linkerscript-multi-sections-constraint.s +++ test/ELF/linkerscript/linkerscript-multi-sections-constraint.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; .aaa : ONLY_IF_RO { *(.aaa.*) } \ +# RUN: . = 0x2000; .aaa : ONLY_IF_RW { *(.aaa.*) } } " > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .aaa 00000010 0000000000002000 DATA +# CHECK-NEXT: 2 .text 00000001 0000000000002010 TEXT DATA +# CHECK-NEXT: 3 .symtab 00000030 0000000000000000 +# CHECK-NEXT: 4 .shstrtab 00000026 0000000000000000 +# CHECK-NEXT: 5 .strtab 00000008 0000000000000000 + +.global _start +_start: + nop + +.section .aaa.1, "aw" +.quad 1 + +.section .aaa.2, "aw" +.quad 1 Index: test/ELF/linkerscript/linkerscript-sections-constraint.s =================================================================== --- test/ELF/linkerscript/linkerscript-sections-constraint.s +++ test/ELF/linkerscript/linkerscript-sections-constraint.s @@ -13,22 +13,20 @@ # BASE-NEXT: 2 .readable 00000004 0000000000000204 DATA # RUN: echo "SECTIONS { \ -# RUN: .writable : ONLY_IF_RO { *(.writable) } \ -# RUN: .readable : ONLY_IF_RW { *(.readable) }}" > %t.script -# RUN: ld.lld -o %t1 --script %t.script %t -# RUN: llvm-objdump -section-headers %t1 | \ -# RUN: FileCheck -check-prefix=NOSECTIONS %s -# NOSECTIONS: Sections: -# NOSECTIONS-NOT: .writable -# NOSECTIONS-NOT: .readable - -# RUN: echo "SECTIONS { \ -# RUN: .foo : ONLY_IF_RO { *(.foo.*) }}" > %t.script -# RUN: ld.lld -o %t1 --script %t.script %t -# RUN: llvm-objdump -section-headers %t1 | \ -# RUN: FileCheck -check-prefix=NOSECTIONS2 %s -# NOSECTIONS2: Sections: -# NOSECTIONS2-NOT: .foo +# RUN: .foo : ONLY_IF_RO { *(.foo.*) } \ +# RUN: .writable : ONLY_IF_RW { *(.writable) } \ +# RUN: .readable : ONLY_IF_RO { *(.readable) }}" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t2 | \ +# RUN: FileCheck -check-prefix=NO1 %s +# NO1: Sections: +# NO1-NEXT: Idx Name Size Address Type +# NO1-NEXT: 0 00000000 0000000000000000 +# NO1-NEXT: 1 .writable 00000004 0000000000000200 DATA +# NO1-NEXT: 2 .readable 00000004 0000000000000204 DATA +# NO1-NEXT: 3 .text 00000001 0000000000000208 TEXT DATA +# NO1-NEXT: 4 .foo.2 00000004 0000000000000209 DATA +# NO1-NEXT: 5 .foo.1 00000004 000000000000020d TEXT DATA .global _start _start: