Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -41,16 +41,36 @@ StringRef SectionPattern; }; -// This enum represents what we can observe in SECTIONS tag of script: -// ExprKind is a location counter change, like ". = . + 0x1000" -// SectionKind is a description of output section, like ".data :..." -enum SectionsCommandKind { SectionKind, AssignmentKind }; +// 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 DescriptionKind for now. +enum SectionsCommandKind { AssignmentKind, OutputSectionKind }; + +struct BaseCommand { + BaseCommand(int K) : Kind(K) {} + int Kind; +}; -struct SectionsCommand { - SectionsCommandKind Kind; +struct SymbolAssignment : BaseCommand { + SymbolAssignment(StringRef Name, std::vector &Expr) + : BaseCommand(AssignmentKind), Name(Name), Expr(std::move(Expr)) {} + static bool classof(const BaseCommand *C); + StringRef Name; std::vector Expr; +}; + +struct OutputSectionCommand : BaseCommand { + OutputSectionCommand(StringRef Name) + : BaseCommand(OutputSectionKind), Name(Name) {} + static bool classof(const BaseCommand *C); StringRef Name; std::vector Phdrs; + std::vector Filler; }; struct PhdrsCommand { @@ -69,7 +89,7 @@ llvm::StringMap> Filler; // Used to assign addresses to sections. - std::vector Commands; + std::vector> Commands; // Used to assign sections to headers. std::vector PhdrsCommands; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -39,6 +39,14 @@ ScriptConfiguration *elf::ScriptConfig; +bool SymbolAssignment::classof(const BaseCommand *C) { + return C->Kind == AssignmentKind; +}; + +bool OutputSectionCommand::classof(const BaseCommand *C) { + return C->Kind == OutputSectionKind; +}; + // 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 @@ -259,7 +267,7 @@ for (OutputSectionBase *Sec : Sections) { StringRef Name = Sec->getName(); if (getSectionIndex(Name) == INT_MAX) - Opt.Commands.push_back({SectionKind, {}, Name, {}}); + Opt.Commands.push_back(llvm::make_unique(Name)); } // Assign addresses as instructed by linker script SECTIONS sub-commands. @@ -267,14 +275,14 @@ uintX_t MinVA = std::numeric_limits::max(); uintX_t ThreadBssOffset = 0; - for (SectionsCommand &Cmd : Opt.Commands) { - if (Cmd.Kind == AssignmentKind) { - uint64_t Val = evalExpr(Cmd.Expr, Dot); + for (const std::unique_ptr &Base : Opt.Commands) { + if (auto *Cmd = dyn_cast(Base.get())) { + uint64_t Val = evalExpr(Cmd->Expr, Dot); + if (Cmd->Name == ".") { - if (Cmd.Name == ".") { Dot = Val; } else { - auto *D = cast>(Symtab::X->find(Cmd.Name)); + auto *D = cast>(Symtab::X->find(Cmd->Name)); D->Value = Val; } continue; @@ -283,9 +291,9 @@ // 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. - assert(Cmd.Kind == SectionKind); + auto *Cmd = cast(Base.get()); for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.Name) + if (Sec->getName() != Cmd->Name) continue; if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { @@ -412,13 +420,16 @@ // SECTIONS commands. Sections are laid out as the same order as they // were in the script. If a given name did not appear in the script, // it returns INT_MAX, so that it will be laid out at end of file. -template -int LinkerScript::getSectionIndex(StringRef Name) { +template int LinkerScript::getSectionIndex(StringRef Name) { auto Begin = Opt.Commands.begin(); auto End = Opt.Commands.end(); - auto I = std::find_if(Begin, End, [&](SectionsCommand &N) { - return N.Kind == SectionKind && N.Name == Name; - }); + auto I = + std::find_if(Begin, End, [&](const std::unique_ptr &Base) { + if (auto *Cmd = dyn_cast(Base.get())) + if (Cmd->Name == Name) + return true; + return false; + }); return I == End ? INT_MAX : (I - Begin); } @@ -433,12 +444,11 @@ return I < J ? -1 : 1; } -template -void LinkerScript::addScriptedSymbols() { - for (SectionsCommand &Cmd : Opt.Commands) - if (Cmd.Kind == AssignmentKind) - if (Cmd.Name != "." && Symtab::X->find(Cmd.Name) == nullptr) - Symtab::X->addAbsolute(Cmd.Name, STV_DEFAULT); +template void LinkerScript::addScriptedSymbols() { + for (const std::unique_ptr &Base : Opt.Commands) + if (auto *Cmd = dyn_cast(Base.get())) + if (Cmd->Name != "." && Symtab::X->find(Cmd->Name) == nullptr) + Symtab::X->addAbsolute(Cmd->Name, STV_DEFAULT); } template bool LinkerScript::hasPhdrsCommands() { @@ -451,15 +461,16 @@ template std::vector LinkerScript::getPhdrIndicesForSection(StringRef Name) { - for (SectionsCommand &Cmd : Opt.Commands) { - if (Cmd.Kind != SectionKind || Cmd.Name != Name) + for (const std::unique_ptr &Base : Opt.Commands) { + auto *Cmd = dyn_cast(Base.get()); + if (!Cmd || Cmd->Name != Name) continue; std::vector Indices; - for (StringRef PhdrName : Cmd.Phdrs) { + for (StringRef PhdrName : Cmd->Phdrs) { auto ItPhdr = std::find_if(Opt.PhdrsCommands.rbegin(), Opt.PhdrsCommands.rend(), - [&](PhdrsCommand &Cmd) { return Cmd.Name == PhdrName; }); + [&](PhdrsCommand &P) { return P.Name == PhdrName; }); if (ItPhdr == Opt.PhdrsCommands.rend()) error("section header '" + PhdrName + "' is not listed in PHDRS"); else @@ -705,12 +716,12 @@ if (Expr.empty()) error("error in location counter expression"); else - Opt.Commands.push_back({AssignmentKind, std::move(Expr), ".", {}}); + Opt.Commands.push_back(llvm::make_unique(".", Expr)); } void ScriptParser::readOutputSectionDescription(StringRef OutSec) { - Opt.Commands.push_back({SectionKind, {}, OutSec, {}}); - SectionsCommand &Cmd = Opt.Commands.back(); + OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec); + Opt.Commands.emplace_back(Cmd); expect(":"); expect("{"); @@ -734,7 +745,7 @@ setError("unknown command " + Tok); } } - Cmd.Phdrs = readOutputSectionPhdrs(); + Cmd->Phdrs = readOutputSectionPhdrs(); StringRef Tok = peek(); if (Tok.startswith("=")) { @@ -754,7 +765,7 @@ if (Expr.empty()) error("error in symbol assignment expression"); else - Opt.Commands.push_back({AssignmentKind, std::move(Expr), Name, {}}); + Opt.Commands.push_back(llvm::make_unique(Name, Expr)); } std::vector ScriptParser::readSectionsCommandExpr() {