diff options
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 69 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.h | 35 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 4 |
3 files changed, 59 insertions, 49 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 7ebd9b52819..bb75a4b12d9 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -47,6 +47,10 @@ bool OutputSectionCommand::classof(const BaseCommand *C) { 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 @@ -195,16 +199,8 @@ uint64_t ExprParser::parseExpr1(uint64_t Lhs, int MinPrec) { uint64_t ExprParser::parseExpr() { return parseExpr1(parsePrimary(), 0); } template <class ELFT> -StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) { - for (SectionRule &R : Opt.Sections) - if (globMatch(R.SectionPattern, S->getSectionName())) - return R.Dest; - return ""; -} - -template <class ELFT> bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) { - return !S || !S->Live || getOutputSection(S) == "/DISCARD/"; + return !S || !S->Live; } template <class ELFT> @@ -215,9 +211,17 @@ bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) { return false; } +static bool match(StringRef Pattern, ArrayRef<StringRef> Arr) { + for (StringRef S : Arr) + if (globMatch(S, Pattern)) + return true; + return false; +} + template <class ELFT> std::vector<OutputSectionBase<ELFT> *> LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { + typedef const std::unique_ptr<ObjectFile<ELFT>> ObjectFile; std::vector<OutputSectionBase<ELFT> *> Result; // Add input section to output section. If there is no output section yet, @@ -234,18 +238,34 @@ LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { // 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<ObjectFile<ELFT>> &F : - Symtab<ELFT>::X->getObjectFiles()) - for (InputSectionBase<ELFT> *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<BaseCommand> &Base : Opt.Commands) { + auto *OutCmd = dyn_cast<OutputSectionCommand>(Base.get()); + if (!OutCmd) + continue; + + for (const std::unique_ptr<BaseCommand> &Cmd : OutCmd->Commands) { + auto *InCmd = dyn_cast<InputSectionDescription>(Cmd.get()); + if (!InCmd) + continue; + + for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) { + for (InputSectionBase<ELFT> *S : F->getSections()) { + if (isDiscarded(S) || S->OutSec) + continue; + + if (match(S->getSectionName(), InCmd->Patterns)) { + if (OutCmd->Name == "/DISCARD/") + S->Live = false; + else + AddInputSec(S, OutCmd->Name); + } + } + } + } + } // Add all other input sections, which are not listed in script. - for (const std::unique_ptr<ObjectFile<ELFT>> &F : - Symtab<ELFT>::X->getObjectFiles()) + for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) for (InputSectionBase<ELFT> *S : F->getSections()) if (!isDiscarded(S)) { if (!S->OutSec) @@ -735,17 +755,20 @@ void ScriptParser::readOutputSectionDescription(StringRef OutSec) { while (!Error && !skip("}")) { StringRef Tok = next(); if (Tok == "*") { + auto *InCmd = new InputSectionDescription(); + Cmd->Commands.emplace_back(InCmd); expect("("); while (!Error && !skip(")")) - Opt.Sections.emplace_back(OutSec, next()); + InCmd->Patterns.push_back(next()); } else if (Tok == "KEEP") { expect("("); expect("*"); expect("("); + auto *InCmd = new InputSectionDescription(); + Cmd->Commands.emplace_back(InCmd); while (!Error && !skip(")")) { - StringRef Sec = next(); - Opt.Sections.emplace_back(OutSec, Sec); - Opt.KeptSections.push_back(Sec); + Opt.KeptSections.push_back(peek()); + InCmd->Patterns.push_back(next()); } expect(")"); } else { diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 311bd0bef51..c4fa455f265 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -31,26 +31,14 @@ class ScriptParser; template <class ELFT> class InputSectionBase; template <class ELFT> 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 is used to implement linker script SECTIONS command. +// https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS +enum SectionsCommandKind { + AssignmentKind, + OutputSectionKind, + InputSectionKind }; -// 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) -// * An ENTRY command. -// * A symbol assignment. -// * An output section description. -// * An overlay description. -// We support only AssignmentKind and OutputSectionKind for now. -enum SectionsCommandKind { AssignmentKind, OutputSectionKind }; - struct BaseCommand { BaseCommand(int K) : Kind(K) {} virtual ~BaseCommand() {} @@ -70,10 +58,17 @@ struct OutputSectionCommand : BaseCommand { : BaseCommand(OutputSectionKind), Name(Name) {} static bool classof(const BaseCommand *C); StringRef Name; + std::vector<std::unique_ptr<BaseCommand>> Commands; std::vector<StringRef> Phdrs; std::vector<uint8_t> Filler; }; +struct InputSectionDescription : BaseCommand { + InputSectionDescription() : BaseCommand(InputSectionKind) {} + static bool classof(const BaseCommand *C); + std::vector<StringRef> Patterns; +}; + struct PhdrsCommand { StringRef Name; unsigned Type; @@ -84,9 +79,6 @@ struct PhdrsCommand { // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { - // SECTIONS commands. - std::vector<SectionRule> Sections; - // Used to assign addresses to sections. std::vector<std::unique_ptr<BaseCommand>> Commands; @@ -114,7 +106,6 @@ public: std::vector<OutputSectionBase<ELFT> *> createSections(OutputSectionFactory<ELFT> &Factory); - StringRef getOutputSection(InputSectionBase<ELFT> *S); ArrayRef<uint8_t> getFiller(StringRef Name); bool isDiscarded(InputSectionBase<ELFT> *S); bool shouldKeep(InputSectionBase<ELFT> *S); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 021459a59e8..9e5cf23b833 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -90,10 +90,6 @@ private: template <class ELFT> StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) { - StringRef Dest = Script<ELFT>::X->getOutputSection(S); - if (!Dest.empty()) - return Dest; - StringRef Name = S->getSectionName(); for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", |

