Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -36,12 +36,14 @@ bool elf::link(ArrayRef Args, raw_ostream &Error) { HasError = false; ErrorOS = &Error; + Configuration C; LinkerDriver D; - LinkerScript LS; + ScriptConfiguration SC; Config = &C; Driver = &D; - Script = &LS; + ScriptConfig = &SC; + Driver->main(Args); return !HasError; } @@ -108,7 +110,7 @@ switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: - Script->read(MBRef); + readLinkerScript(MBRef); return; case file_magic::archive: if (WholeArchive) { @@ -415,8 +417,11 @@ template void LinkerDriver::link(opt::InputArgList &Args) { SymbolTable Symtab; + std::unique_ptr TI(createTarget()); Target = TI.get(); + LinkerScript LS; + Script::X = &LS; Config->Rela = ELFT::Is64Bits; Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -19,6 +19,10 @@ namespace lld { namespace elf { +// Parses a linker script. Calling this function updates +// Config and ScriptConfig. +void readLinkerScript(MemoryBufferRef MB); + class ScriptParser; template class InputSectionBase; template class OutputSectionBase; @@ -52,28 +56,8 @@ StringRef SectionName; }; -// This is a runner of the linker script. -class LinkerScript { - friend class ScriptParser; - -public: - // Parses a linker script. Calling this function may update - // this object and Config. - void read(MemoryBufferRef MB); - - template StringRef getOutputSection(InputSectionBase *S); - ArrayRef getFiller(StringRef Name); - template bool isDiscarded(InputSectionBase *S); - template bool shouldKeep(InputSectionBase *S); - template - void assignAddresses(std::vector *> &S); - int compareSections(StringRef A, StringRef B); - - bool DoLayout = false; - -private: - template SectionRule *find(InputSectionBase *S); - +// ScriptConfiguration holds linker script parse results. +struct ScriptConfiguration { // SECTIONS commands. std::vector Sections; @@ -86,10 +70,33 @@ // Used to assign addresses to sections. std::vector Commands; + bool DoLayout = false; + llvm::BumpPtrAllocator Alloc; }; -extern LinkerScript *Script; +extern ScriptConfiguration *ScriptConfig; + +// This is a runner of the linker script. +template class LinkerScript { +public: + StringRef getOutputSection(InputSectionBase *S); + ArrayRef getFiller(StringRef Name); + bool isDiscarded(InputSectionBase *S); + bool shouldKeep(InputSectionBase *S); + void assignAddresses(std::vector *> &S); + int compareSections(StringRef A, StringRef B); + +private: + SectionRule *find(InputSectionBase *S); + + ScriptConfiguration &Opt = *ScriptConfig; +}; + +// Variable template is a C++14 feature, so we can't template +// a global variable. Use a struct to workaround. +template struct Script { static LinkerScript *X; }; +template LinkerScript *Script::X; } // namespace elf } // namespace lld Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -33,7 +33,7 @@ using namespace lld; using namespace lld::elf; -LinkerScript *elf::Script; +ScriptConfiguration *elf::ScriptConfig; static uint64_t getInteger(StringRef S) { uint64_t V; @@ -147,25 +147,26 @@ } template -SectionRule *LinkerScript::find(InputSectionBase *S) { - for (SectionRule &R : Sections) +SectionRule *LinkerScript::find(InputSectionBase *S) { + for (SectionRule &R : Opt.Sections) if (R.match(S)) return &R; return nullptr; } template -StringRef LinkerScript::getOutputSection(InputSectionBase *S) { +StringRef LinkerScript::getOutputSection(InputSectionBase *S) { SectionRule *R = find(S); return R ? R->Dest : ""; } template -bool LinkerScript::isDiscarded(InputSectionBase *S) { +bool LinkerScript::isDiscarded(InputSectionBase *S) { return getOutputSection(S) == "/DISCARD/"; } -template bool LinkerScript::shouldKeep(InputSectionBase *S) { +template +bool LinkerScript::shouldKeep(InputSectionBase *S) { SectionRule *R = find(S); return R && R->Keep; } @@ -180,7 +181,7 @@ } template -void LinkerScript::assignAddresses( +void LinkerScript::assignAddresses( std::vector *> &Sections) { typedef typename ELFT::uint uintX_t; @@ -191,9 +192,9 @@ // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections. for (OutputSectionBase *Sec : Sections) { StringRef Name = Sec->getName(); - auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name); - if (I == SectionOrder.end()) - Commands.push_back({SectionKind, {}, Name}); + auto I = std::find(Opt.SectionOrder.begin(), Opt.SectionOrder.end(), Name); + if (I == Opt.SectionOrder.end()) + Opt.Commands.push_back({SectionKind, {}, Name}); } // Assign addresses as instructed by linker script SECTIONS sub-commands. @@ -201,7 +202,7 @@ uintX_t VA = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); - for (SectionsCommand &Cmd : Commands) { + for (SectionsCommand &Cmd : Opt.Commands) { if (Cmd.Kind == ExprKind) { VA = evaluate(Cmd.Expr, VA); continue; @@ -228,9 +229,10 @@ } } -ArrayRef LinkerScript::getFiller(StringRef Name) { - auto I = Filler.find(Name); - if (I == Filler.end()) +template +ArrayRef LinkerScript::getFiller(StringRef Name) { + auto I = Opt.Filler.find(Name); + if (I == Opt.Filler.end()) return {}; return I->second; } @@ -238,10 +240,11 @@ // A compartor to sort output sections. Returns -1 or 1 if both // A and B are mentioned in linker scripts. Otherwise, returns 0 // to use the default rule which is implemented in Writer.cpp. -int LinkerScript::compareSections(StringRef A, StringRef B) { - auto E = SectionOrder.end(); - auto I = std::find(SectionOrder.begin(), E, A); - auto J = std::find(SectionOrder.begin(), E, B); +template +int LinkerScript::compareSections(StringRef A, StringRef B) { + auto E = Opt.SectionOrder.end(); + auto I = std::find(Opt.SectionOrder.begin(), E, A); + auto J = std::find(Opt.SectionOrder.begin(), E, B); if (I == E || J == E) return 0; return I < J ? -1 : 1; @@ -275,12 +278,11 @@ return matchStr(SectionPattern, S->getSectionName()); } -class elf::ScriptParser final : public elf::ScriptParserBase { +class elf::ScriptParser : public ScriptParserBase { typedef void (ScriptParser::*Handler)(); public: - ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) - : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {} + ScriptParser(StringRef S, bool B) : ScriptParserBase(S), IsUnderSysroot(B) {} void run() override; @@ -303,8 +305,9 @@ void readOutputSectionDescription(); void readSectionPatterns(StringRef OutSec, bool Keep); - StringSaver Saver; const static StringMap Cmd; + ScriptConfiguration &Opt = *ScriptConfig; + StringSaver Saver = {ScriptConfig->Alloc}; bool IsUnderSysroot; }; @@ -460,7 +463,7 @@ } void ScriptParser::readSections() { - Script->DoLayout = true; + Opt.DoLayout = true; expect("{"); while (!Error && !skip("}")) { StringRef Tok = peek(); @@ -474,14 +477,14 @@ void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { expect("("); while (!Error && !skip(")")) - Script->Sections.emplace_back(OutSec, next(), Keep); + Opt.Sections.emplace_back(OutSec, next(), Keep); } void ScriptParser::readLocationCounterValue() { expect("."); expect("="); - Script->Commands.push_back({ExprKind, {}, ""}); - SectionsCommand &Cmd = Script->Commands.back(); + Opt.Commands.push_back({ExprKind, {}, ""}); + SectionsCommand &Cmd = Opt.Commands.back(); while (!Error) { StringRef Tok = next(); if (Tok == ";") @@ -494,8 +497,8 @@ void ScriptParser::readOutputSectionDescription() { StringRef OutSec = next(); - Script->SectionOrder.push_back(OutSec); - Script->Commands.push_back({SectionKind, {}, OutSec}); + Opt.SectionOrder.push_back(OutSec); + Opt.Commands.push_back({SectionKind, {}, OutSec}); expect(":"); expect("{"); while (!Error && !skip("}")) { @@ -518,7 +521,7 @@ return; } Tok = Tok.substr(3); - Script->Filler[OutSec] = parseHex(Tok); + Opt.Filler[OutSec] = parseHex(Tok); next(); } } @@ -532,32 +535,13 @@ return false; } -// Entry point. The other functions or classes are private to this file. -void LinkerScript::read(MemoryBufferRef MB) { +// Entry point. +void elf::readLinkerScript(MemoryBufferRef MB) { StringRef Path = MB.getBufferIdentifier(); - ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); + ScriptParser(MB.getBuffer(), isUnderSysroot(Path)).run(); } -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); -template StringRef LinkerScript::getOutputSection(InputSectionBase *); - -template bool LinkerScript::isDiscarded(InputSectionBase *); -template bool LinkerScript::isDiscarded(InputSectionBase *); -template bool LinkerScript::isDiscarded(InputSectionBase *); -template bool LinkerScript::isDiscarded(InputSectionBase *); - -template bool LinkerScript::shouldKeep(InputSectionBase *); -template bool LinkerScript::shouldKeep(InputSectionBase *); -template bool LinkerScript::shouldKeep(InputSectionBase *); -template bool LinkerScript::shouldKeep(InputSectionBase *); - -template void -LinkerScript::assignAddresses(std::vector *> &); -template void -LinkerScript::assignAddresses(std::vector *> &); -template void -LinkerScript::assignAddresses(std::vector *> &); -template void -LinkerScript::assignAddresses(std::vector *> &); +template class elf::LinkerScript; +template class elf::LinkerScript; +template class elf::LinkerScript; +template class elf::LinkerScript; Index: lld/trunk/ELF/MarkLive.cpp =================================================================== --- lld/trunk/ELF/MarkLive.cpp +++ lld/trunk/ELF/MarkLive.cpp @@ -126,7 +126,7 @@ for (const std::unique_ptr> &F : Symtab->getObjectFiles()) for (InputSectionBase *Sec : F->getSections()) if (Sec && Sec != &InputSection::Discarded) - if (isReserved(Sec) || Script->shouldKeep(Sec)) + if (isReserved(Sec) || Script::X->shouldKeep(Sec)) Enqueue(Sec); // Mark all reachable sections. Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -908,7 +908,7 @@ } template void OutputSection::writeTo(uint8_t *Buf) { - ArrayRef Filler = Script->getFiller(this->Name); + ArrayRef Filler = Script::X->getFiller(this->Name); if (!Filler.empty()) fill(Buf, this->getSize(), Filler); if (Config->Threads) { Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -220,8 +220,8 @@ } else { createPhdrs(); fixHeaders(); - if (Script->DoLayout) { - Script->assignAddresses(OutputSections); + if (ScriptConfig->DoLayout) { + Script::X->assignAddresses(OutputSections); } else { fixSectionAlignments(); assignAddresses(); @@ -776,7 +776,7 @@ OutputSectionBase *B) { typedef typename ELFT::uint uintX_t; - int Comp = Script->compareSections(A->getName(), B->getName()); + int Comp = Script::X->compareSections(A->getName(), B->getName()); if (Comp != 0) return Comp < 0; @@ -918,7 +918,7 @@ template StringRef Writer::getOutputSectionName(InputSectionBase *S) const { - StringRef Dest = Script->getOutputSection(S); + StringRef Dest = Script::X->getOutputSection(S); if (!Dest.empty()) return Dest; @@ -943,7 +943,7 @@ template bool Writer::isDiscarded(InputSectionBase *S) const { return !S || S == &InputSection::Discarded || !S->Live || - Script->isDiscarded(S); + Script::X->isDiscarded(S); } template @@ -1545,7 +1545,7 @@ // sections. These are special, we do not include them into output sections // list, but have them to simplify the code. template void Writer::fixHeaders() { - uintX_t BaseVA = Script->DoLayout ? 0 : Target->getVAStart(); + uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart(); Out::ElfHeader->setVA(BaseVA); Out::ElfHeader->setFileOffset(0); uintX_t Off = Out::ElfHeader->getSize();