Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -131,6 +131,11 @@ bool hasPhdrsCommands(); private: + std::vector>> getSectionMap(); + + std::vector *> + getInputSections(ArrayRef Patterns); + // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -74,65 +74,76 @@ return false; } +// Create a vector of (, ). +// For example, if a returned vector contains (".text" (".foo.*" ".bar.*")), +// input sections start with ".foo." or ".bar." should be added to +// ".text" section. +template +std::vector>> +LinkerScript::getSectionMap() { + std::vector>> Ret; + + for (const std::unique_ptr &Base1 : Opt.Commands) + if (auto *Cmd1 = dyn_cast(Base1.get())) + for (const std::unique_ptr &Base2 : Cmd1->Commands) + if (auto *Cmd2 = dyn_cast(Base2.get())) + Ret.emplace_back(Cmd1->Name, Cmd2->Patterns); + + return Ret; +} + +// Returns input sections filtered by given glob patterns. +template +std::vector *> +LinkerScript::getInputSections(ArrayRef Patterns) { + std::vector *> Ret; + for (const std::unique_ptr> &F : + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec && match(Patterns, S->getSectionName())) + Ret.push_back(S); + return Ret; +} + template std::vector *> LinkerScript::createSections(OutputSectionFactory &Factory) { - typedef const std::unique_ptr> ObjectFile; - std::vector *> Result; + std::vector *> Ret; // 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) { + auto Add = [&](InputSectionBase *C, StringRef Name) { OutputSectionBase *Sec; bool IsNew; std::tie(Sec, IsNew) = Factory.create(C, Name); if (IsNew) - Result.push_back(Sec); + Ret.push_back(Sec); Sec->addSection(C); }; - // Select input sections matching rule and add them to corresponding - // output section. Section rules are processed in order they're listed - // in script, so correct input section order is maintained by design. - for (const std::unique_ptr &Base : Opt.Commands) { - auto *OutCmd = dyn_cast(Base.get()); - if (!OutCmd) - continue; - - for (const std::unique_ptr &Cmd : OutCmd->Commands) { - auto *InCmd = dyn_cast(Cmd.get()); - if (!InCmd) + for (auto &P : getSectionMap()) { + StringRef OutputName = P.first; + ArrayRef InputPatterns = P.second; + for (InputSectionBase *S : getInputSections(InputPatterns)) { + if (OutputName == "/DISCARD/") { + S->Live = false; + reportDiscarded(S); continue; - - for (ObjectFile &F : Symtab::X->getObjectFiles()) { - for (InputSectionBase *S : F->getSections()) { - if (isDiscarded(S) || S->OutSec) - continue; - - if (match(InCmd->Patterns, S->getSectionName())) { - if (OutCmd->Name == "/DISCARD/") - S->Live = false; - else - AddInputSec(S, OutCmd->Name); - } - } } + Add(S, OutputName); } } // Add all other input sections, which are not listed in script. - for (ObjectFile &F : Symtab::X->getObjectFiles()) - for (InputSectionBase *S : F->getSections()) { - if (!isDiscarded(S)) { - if (!S->OutSec) - AddInputSec(S, getOutputSectionName(S)); - } else - reportDiscarded(S); - } + for (const std::unique_ptr> &F : + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec) + Add(S, getOutputSectionName(S)); // Remove from the output all the sections which did not meet // the optional constraints. - return filter(Result); + return filter(Ret); } // Process ONLY_IF_RO and ONLY_IF_RW.