Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -330,6 +330,25 @@ } } +template +static OutputSectionBase * +findSection(OutputSectionCommand &Cmd, + ArrayRef *> Sections) { + for (OutputSectionBase *Sec : Sections) { + if (Sec->getName() != Cmd.Name) + continue; + if (Cmd.Constraint == ConstraintKind::NoConstraint) + return Sec; + + bool RO = (Cmd.Constraint == ConstraintKind::ReadOnly); + bool RW = (Cmd.Constraint == ConstraintKind::ReadWrite); + bool Writable = Sec->getFlags() & SHF_WRITE; + if ((RO && !Writable) || (RW && Writable)) + return Sec; + } + return nullptr; +} + template void LinkerScript::assignAddresses() { // Orphan sections are sections present in the input files which // are not explicitly placed into the output file by the linker script. @@ -362,39 +381,36 @@ continue; } - // Find all the sections with required name. There can be more than - // one section with such name, if the alignment, flags or type - // attribute differs. auto *Cmd = cast(Base.get()); - for (OutputSectionBase *Sec : *OutputSections) { - if (Sec->getName() != Cmd->Name) - continue; + OutputSectionBase *Sec = findSection(*Cmd, *OutputSections); + if (!Sec) + continue; - if (Cmd->AddrExpr) - Dot = Cmd->AddrExpr(Dot); + if (Cmd->AddrExpr) + Dot = Cmd->AddrExpr(Dot); - if (Cmd->AlignExpr) - Sec->updateAlignment(Cmd->AlignExpr(Dot)); + if (Cmd->AlignExpr) + Sec->updateAlignment(Cmd->AlignExpr(Dot)); - if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { - uintX_t TVA = Dot + ThreadBssOffset; - TVA = alignTo(TVA, Sec->getAlignment()); - Sec->setVA(TVA); - assignOffsets(Sec); - ThreadBssOffset = TVA - Dot + Sec->getSize(); - continue; - } + if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { + uintX_t TVA = Dot + ThreadBssOffset; + TVA = alignTo(TVA, Sec->getAlignment()); + Sec->setVA(TVA); + assignOffsets(Sec); + ThreadBssOffset = TVA - Dot + Sec->getSize(); + continue; + } - if (Sec->getFlags() & SHF_ALLOC) { - Dot = alignTo(Dot, Sec->getAlignment()); - Sec->setVA(Dot); - assignOffsets(Sec); - MinVA = std::min(MinVA, Dot); - Dot += Sec->getSize(); - continue; - } + if (!(Sec->getFlags() & SHF_ALLOC)) { Sec->assignOffsets(); + continue; } + + Dot = alignTo(Dot, Sec->getAlignment()); + Sec->setVA(Dot); + assignOffsets(Sec); + MinVA = std::min(MinVA, Dot); + Dot += Sec->getSize(); } // ELF and Program headers need to be right before the first section in 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 @@ -15,6 +15,21 @@ # CHECK-NEXT: 4 .shstrtab 00000026 0000000000000000 # CHECK-NEXT: 5 .strtab 00000008 0000000000000000 +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; .aaa : ONLY_IF_RW { *(.aaa.*) } \ +# RUN: . = 0x2000; .aaa : ONLY_IF_RO { *(.aaa.*) } } " > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=REV + +# REV: Sections: +# REV-NEXT: Idx Name Size Address Type +# REV-NEXT: 0 00000000 0000000000000000 +# REV-NEXT: 1 .aaa 00000010 0000000000001000 DATA +# REV-NEXT: 2 .text 00000001 0000000000002000 TEXT DATA +# REV-NEXT: 3 .symtab 00000030 0000000000000000 +# REV-NEXT: 4 .shstrtab 00000026 0000000000000000 +# REV-NEXT: 5 .strtab 00000008 0000000000000000 + .global _start _start: nop