Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -134,6 +134,9 @@ // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; + std::vector *> + filter(std::vector *> &Sections); + int getSectionIndex(StringRef Name); std::vector getPhdrIndicesForSection(StringRef Name); void dispatchAssignment(SymbolAssignment *Cmd); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -80,26 +80,15 @@ LinkerScript::createSections(OutputSectionFactory &Factory) { typedef const std::unique_ptr> ObjectFile; std::vector *> Result; - DenseSet *> Removed; // Add input section to output section. If there is no output section yet, // then create it and add to output section list. - auto AddInputSec = [&](InputSectionBase *C, StringRef Name, - ConstraintKind Constraint) { + auto AddInputSec = [&](InputSectionBase *C, StringRef Name) { OutputSectionBase *Sec; bool IsNew; std::tie(Sec, IsNew) = Factory.create(C, Name); if (IsNew) Result.push_back(Sec); - if ((!(C->getSectionHdr()->sh_flags & SHF_WRITE)) && - Constraint == ReadWrite) { - Removed.insert(Sec); - return; - } - if ((C->getSectionHdr()->sh_flags & SHF_WRITE) && Constraint == ReadOnly) { - Removed.insert(Sec); - return; - } Sec->addSection(C); }; @@ -125,7 +114,7 @@ if (OutCmd->Name == "/DISCARD/") S->Live = false; else - AddInputSec(S, OutCmd->Name, OutCmd->Constraint); + AddInputSec(S, OutCmd->Name); } } } @@ -137,18 +126,48 @@ for (InputSectionBase *S : F->getSections()) { if (!isDiscarded(S)) { if (!S->OutSec) - AddInputSec(S, getOutputSectionName(S), NoConstraint); + AddInputSec(S, getOutputSectionName(S)); } else reportDiscarded(S, F); } - // Remove from the output all the sections which did not met the constraints. - Result.erase(std::remove_if(Result.begin(), Result.end(), - [&](OutputSectionBase *Sec) { - return Removed.count(Sec); - }), - Result.end()); - return Result; + // Remove from the output all the sections which did not meet + // the optional constraints. + return filter(Result); +} + +// Process ONLY_IF_RO and ONLY_IF_RW. +template +std::vector *> +LinkerScript::filter(std::vector *> &Sections) { + // Sections and OutputSectionCommands are parallel arrays. + // In this loop, we remove output sections if they don't satisfy + // requested properties. + auto It = Sections.begin(); + for (const std::unique_ptr &Base : Opt.Commands) { + auto *Cmd = dyn_cast(Base.get()); + if (!Cmd) + continue; + + OutputSectionBase *Sec = *It; + switch (Cmd->Constraint) { + case ConstraintKind::NoConstraint: + ++It; + continue; + case ConstraintKind::ReadOnly: + if (Sec->getFlags() & SHF_WRITE) + break; + ++It; + continue; + case ConstraintKind::ReadWrite: + if (!(Sec->getFlags() & SHF_WRITE)) + break; + ++It; + continue; + } + Sections.erase(It); + } + return Sections; } template