Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -31,16 +31,6 @@ template class InputSectionBase; template class OutputSectionBase; -// This class represents each rule in SECTIONS command. -struct SectionRule { - SectionRule(StringRef D, StringRef S) - : Dest(D), SectionPattern(S) {} - - StringRef Dest; - - StringRef SectionPattern; -}; - // This enum represents what we can observe in SECTIONS tag of script. // Each sections-command may of be one of the following: // (https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS) @@ -49,7 +39,11 @@ // * An output section description. // * An overlay description. // We support only AssignmentKind and OutputSectionKind for now. -enum SectionsCommandKind { AssignmentKind, OutputSectionKind }; +enum SectionsCommandKind { + AssignmentKind, + OutputSectionKind, + InputSectionKind +}; struct BaseCommand { BaseCommand(int K) : Kind(K) {} @@ -70,10 +64,18 @@ : BaseCommand(OutputSectionKind), Name(Name) {} static bool classof(const BaseCommand *C); StringRef Name; + std::vector> Commands; std::vector Phdrs; std::vector Filler; }; +struct InputSectionDescription : BaseCommand { + InputSectionDescription() : BaseCommand(InputSectionKind) {} + static bool classof(const BaseCommand *C); + std::vector Patterns; + bool Keep = false; +}; + struct PhdrsCommand { StringRef Name; unsigned Type; @@ -83,9 +85,6 @@ // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { - // SECTIONS commands. - std::vector Sections; - // Used to assign addresses to sections. std::vector> Commands; @@ -95,10 +94,6 @@ bool DoLayout = false; llvm::BumpPtrAllocator Alloc; - - // List of section patterns specified with KEEP commands. They will - // be kept even if they are unused and --gc-sections is specified. - std::vector KeptSections; }; extern ScriptConfiguration *ScriptConfig; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -47,6 +47,10 @@ return C->Kind == OutputSectionKind; } +bool InputSectionDescription::classof(const BaseCommand *C) { + return C->Kind == InputSectionKind; +} + // This is an operator-precedence parser to parse and evaluate // a linker script expression. For each linker script arithmetic // expression (e.g. ". = . + 0x1000"), a new instance of ExprParser @@ -196,9 +200,13 @@ template StringRef LinkerScript::getOutputSection(InputSectionBase *S) { - for (SectionRule &R : Opt.Sections) - if (globMatch(R.SectionPattern, S->getSectionName())) - return R.Dest; + for (const std::unique_ptr &Base : Opt.Commands) + if (auto *OutSec = dyn_cast(Base.get())) + for (const std::unique_ptr &Cmd : OutSec->Commands) + if (auto *InSec = dyn_cast(Cmd.get())) + for (StringRef P : InSec->Patterns) + if (globMatch(P, S->getSectionName())) + return OutSec->Name; return ""; } @@ -209,9 +217,14 @@ template bool LinkerScript::shouldKeep(InputSectionBase *S) { - for (StringRef Pat : Opt.KeptSections) - if (globMatch(Pat, S->getSectionName())) - return true; + for (const std::unique_ptr &Base : Opt.Commands) + if (auto *OutSec = dyn_cast(Base.get())) + for (const std::unique_ptr &Cmd : OutSec->Commands) + if (auto *InSec = dyn_cast(Cmd.get())) + if (InSec->Keep) + for (StringRef P : InSec->Patterns) + if (globMatch(P, S->getSectionName())) + return true; return false; } @@ -234,14 +247,14 @@ // 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 (SectionRule &R : Opt.Sections) - for (const std::unique_ptr> &F : - Symtab::X->getObjectFiles()) - for (InputSectionBase *S : F->getSections()) - if (!isDiscarded(S) && !S->OutSec && - globMatch(R.SectionPattern, S->getSectionName())) - // Add single input section to output section. - AddInputSec(S, R.Dest); + for (const std::unique_ptr> &F : + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec) { + StringRef OutSec = getOutputSection(S); + if (!OutSec.empty()) + AddInputSec(S, getOutputSection(S)); + } // Add all other input sections, which are not listed in script. for (const std::unique_ptr> &F : @@ -729,18 +742,20 @@ while (!Error && !skip("}")) { StringRef Tok = next(); if (Tok == "*") { + InputSectionDescription *IS = new InputSectionDescription(); + Cmd->Commands.emplace_back(IS); expect("("); while (!Error && !skip(")")) - Opt.Sections.emplace_back(OutSec, next()); + IS->Patterns.push_back(next()); } else if (Tok == "KEEP") { expect("("); expect("*"); expect("("); - while (!Error && !skip(")")) { - StringRef Sec = next(); - Opt.Sections.emplace_back(OutSec, Sec); - Opt.KeptSections.push_back(Sec); - } + InputSectionDescription *IS = new InputSectionDescription(); + IS->Keep = true; + Cmd->Commands.emplace_back(IS); + while (!Error && !skip(")")) + IS->Patterns.push_back(next()); expect(")"); } else { setError("unknown command " + Tok);