Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -44,13 +44,31 @@ // 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 }; +enum SectionsCommandKind { OutputSectionKind, AssignmentKind, PhdrsKind }; + +struct SectionsCommand; + +struct PhdrsCmd { + std::vector Phdrs; +}; + +struct OutputSectionCmd { + StringRef Name; + std::vector Commands; +}; + +struct AssignmentCmd { + StringRef Name; + std::vector Expr; +}; struct SectionsCommand { + SectionsCommand(SectionsCommandKind Kind) : Kind(Kind) {} SectionsCommandKind Kind; - std::vector Expr; - StringRef Name; - std::vector Phdrs; + + OutputSectionCmd OutputSection; + AssignmentCmd Assignment; + PhdrsCmd Phdrs; }; struct PhdrsCommand { Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -259,7 +259,8 @@ for (OutputSectionBase *Sec : Sections) { StringRef Name = Sec->getName(); if (getSectionIndex(Name) == INT_MAX) - Opt.Commands.push_back({SectionKind, {}, Name, {}}); + Opt.Commands.emplace(Opt.Commands.end(), SectionsCommand(OutputSectionKind)) + ->OutputSection.Name = Name; } // Assign addresses as instructed by linker script SECTIONS sub-commands. @@ -269,12 +270,13 @@ for (SectionsCommand &Cmd : Opt.Commands) { if (Cmd.Kind == AssignmentKind) { - uint64_t Val = evalExpr(Cmd.Expr, Dot); + AssignmentCmd &A = Cmd.Assignment; + uint64_t Val = evalExpr(A.Expr, Dot); - if (Cmd.Name == ".") { + if (A.Name == ".") { Dot = Val; } else { - auto *D = cast>(Symtab::X->find(Cmd.Name)); + auto *D = cast>(Symtab::X->find(A.Name)); D->Value = Val; } continue; @@ -283,9 +285,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); + assert(Cmd.Kind == OutputSectionKind); for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.Name) + if (Sec->getName() != Cmd.OutputSection.Name) continue; if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { @@ -412,12 +414,11 @@ // 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; + return N.Kind == OutputSectionKind && N.OutputSection.Name == Name; }); return I == End ? INT_MAX : (I - Begin); } @@ -435,10 +436,13 @@ 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); + for (SectionsCommand &Cmd : Opt.Commands) { + if (Cmd.Kind != AssignmentKind) + continue; + AssignmentCmd &A = Cmd.Assignment; + if (A.Name != "." && Symtab::X->find(A.Name) == nullptr) + Symtab::X->addAbsolute(A.Name, STV_DEFAULT); + } } template bool LinkerScript::hasPhdrsCommands() { @@ -452,11 +456,17 @@ std::vector LinkerScript::getPhdrIndicesForSection(StringRef Name) { for (SectionsCommand &Cmd : Opt.Commands) { - if (Cmd.Kind != SectionKind || Cmd.Name != Name) + if (Cmd.Kind != OutputSectionKind || Cmd.OutputSection.Name != Name) continue; + auto I = llvm::find_if(Cmd.OutputSection.Commands, [](SectionsCommand &C) { + return C.Kind == PhdrsKind; + }); + if (I == Cmd.OutputSection.Commands.end()) + return {}; + std::vector Indices; - for (StringRef PhdrName : Cmd.Phdrs) { + for (StringRef PhdrName : I->Phdrs.Phdrs) { auto ItPhdr = std::find_if(Opt.PhdrsCommands.rbegin(), Opt.PhdrsCommands.rend(), [&](PhdrsCommand &Cmd) { return Cmd.Name == PhdrName; }); @@ -702,15 +712,21 @@ expect("."); expect("="); std::vector Expr = readSectionsCommandExpr(); - if (Expr.empty()) + if (Expr.empty()) { error("error in location counter expression"); - else - Opt.Commands.push_back({AssignmentKind, std::move(Expr), ".", {}}); + return; + } + + Opt.Commands.push_back(SectionsCommand(AssignmentKind)); + Opt.Commands.back().Assignment = { ".", std::move(Expr) }; } void ScriptParser::readOutputSectionDescription(StringRef OutSec) { - Opt.Commands.push_back({SectionKind, {}, OutSec, {}}); - SectionsCommand &Cmd = Opt.Commands.back(); + OutputSectionCmd &S = Opt.Commands.emplace(Opt.Commands.end(), + SectionsCommand(OutputSectionKind)) + ->OutputSection; + + S.Name = OutSec; expect(":"); expect("{"); @@ -734,7 +750,9 @@ setError("unknown command " + Tok); } } - Cmd.Phdrs = readOutputSectionPhdrs(); + + S.Commands.emplace(S.Commands.end(), SectionsCommand(PhdrsKind)) + ->Phdrs.Phdrs = readOutputSectionPhdrs(); StringRef Tok = peek(); if (Tok.startswith("=")) { @@ -751,10 +769,13 @@ void ScriptParser::readSymbolAssignment(StringRef Name) { expect("="); std::vector Expr = readSectionsCommandExpr(); - if (Expr.empty()) + if (Expr.empty()) { error("error in symbol assignment expression"); - else - Opt.Commands.push_back({AssignmentKind, std::move(Expr), Name, {}}); + return; + } + + Opt.Commands.push_back(SectionsCommand(AssignmentKind)); + Opt.Commands.back().Assignment = {Name, std::move(Expr)}; } std::vector ScriptParser::readSectionsCommandExpr() {