diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 11 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 98 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 53 | ||||
-rw-r--r-- | lld/ELF/MarkLive.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 12 |
6 files changed, 87 insertions, 91 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index c71cfca7017..f72fa3dd28e 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -36,12 +36,14 @@ LinkerDriver *elf::Driver; bool elf::link(ArrayRef<const char *> 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 @@ void LinkerDriver::addFile(StringRef Path) { 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 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { SymbolTable<ELFT> Symtab; + std::unique_ptr<TargetInfo> TI(createTarget()); Target = TI.get(); + LinkerScript<ELFT> LS; + Script<ELFT>::X = &LS; Config->Rela = ELFT::Is64Bits; diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9a47ee6bccb..10008568d9f 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -33,7 +33,7 @@ using namespace llvm::object; 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 @@ static uint64_t evaluate(ArrayRef<StringRef> Tokens, uint64_t Dot) { } template <class ELFT> -SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { - for (SectionRule &R : Sections) +SectionRule *LinkerScript<ELFT>::find(InputSectionBase<ELFT> *S) { + for (SectionRule &R : Opt.Sections) if (R.match(S)) return &R; return nullptr; } template <class ELFT> -StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { +StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) { SectionRule *R = find(S); return R ? R->Dest : ""; } template <class ELFT> -bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { +bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) { return getOutputSection(S) == "/DISCARD/"; } -template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { +template <class ELFT> +bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) { SectionRule *R = find(S); return R && R->Keep; } @@ -180,7 +181,7 @@ findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) { } template <class ELFT> -void LinkerScript::assignAddresses( +void LinkerScript<ELFT>::assignAddresses( std::vector<OutputSectionBase<ELFT> *> &Sections) { typedef typename ELFT::uint uintX_t; @@ -191,9 +192,9 @@ void LinkerScript::assignAddresses( // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections. for (OutputSectionBase<ELFT> *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 @@ void LinkerScript::assignAddresses( uintX_t VA = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::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 @@ void LinkerScript::assignAddresses( } } -ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) { - auto I = Filler.find(Name); - if (I == Filler.end()) +template <class ELFT> +ArrayRef<uint8_t> LinkerScript<ELFT>::getFiller(StringRef Name) { + auto I = Opt.Filler.find(Name); + if (I == Opt.Filler.end()) return {}; return I->second; } @@ -238,10 +240,11 @@ ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) { // 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 <class ELFT> +int LinkerScript<ELFT>::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 @@ template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 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 @@ private: void readOutputSectionDescription(); void readSectionPatterns(StringRef OutSec, bool Keep); - StringSaver Saver; const static StringMap<Handler> Cmd; + ScriptConfiguration &Opt = *ScriptConfig; + StringSaver Saver = {ScriptConfig->Alloc}; bool IsUnderSysroot; }; @@ -460,7 +463,7 @@ void ScriptParser::readSearchDir() { } void ScriptParser::readSections() { - Script->DoLayout = true; + Opt.DoLayout = true; expect("{"); while (!Error && !skip("}")) { StringRef Tok = peek(); @@ -474,14 +477,14 @@ void ScriptParser::readSections() { 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::readLocationCounterValue() { 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 @@ void ScriptParser::readOutputSectionDescription() { return; } Tok = Tok.substr(3); - Script->Filler[OutSec] = parseHex(Tok); + Opt.Filler[OutSec] = parseHex(Tok); next(); } } @@ -532,32 +535,13 @@ static bool isUnderSysroot(StringRef Path) { 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(); -} - -template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); -template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); -template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); -template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); - -template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); -template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); -template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); -template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); - -template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); -template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); -template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); -template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); - -template void -LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &); -template void -LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &); -template void -LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &); -template void -LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &); + ScriptParser(MB.getBuffer(), isUnderSysroot(Path)).run(); +} + +template class elf::LinkerScript<ELF32LE>; +template class elf::LinkerScript<ELF32BE>; +template class elf::LinkerScript<ELF64LE>; +template class elf::LinkerScript<ELF64BE>; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 2deae33ef6e..bdc217e836a 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/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 ELFT> class InputSectionBase; template <class ELFT> class OutputSectionBase; @@ -52,28 +56,8 @@ struct SectionsCommand { 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 <class ELFT> StringRef getOutputSection(InputSectionBase<ELFT> *S); - ArrayRef<uint8_t> getFiller(StringRef Name); - template <class ELFT> bool isDiscarded(InputSectionBase<ELFT> *S); - template <class ELFT> bool shouldKeep(InputSectionBase<ELFT> *S); - template <class ELFT> - void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S); - int compareSections(StringRef A, StringRef B); - - bool DoLayout = false; - -private: - template <class ELFT> SectionRule *find(InputSectionBase<ELFT> *S); - +// ScriptConfiguration holds linker script parse results. +struct ScriptConfiguration { // SECTIONS commands. std::vector<SectionRule> Sections; @@ -86,10 +70,33 @@ private: // Used to assign addresses to sections. std::vector<SectionsCommand> Commands; + bool DoLayout = false; + llvm::BumpPtrAllocator Alloc; }; -extern LinkerScript *Script; +extern ScriptConfiguration *ScriptConfig; + +// This is a runner of the linker script. +template <class ELFT> class LinkerScript { +public: + StringRef getOutputSection(InputSectionBase<ELFT> *S); + ArrayRef<uint8_t> getFiller(StringRef Name); + bool isDiscarded(InputSectionBase<ELFT> *S); + bool shouldKeep(InputSectionBase<ELFT> *S); + void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S); + int compareSections(StringRef A, StringRef B); + +private: + SectionRule *find(InputSectionBase<ELFT> *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 <class ELFT> struct Script { static LinkerScript<ELFT> *X; }; +template <class ELFT> LinkerScript<ELFT> *Script<ELFT>::X; } // namespace elf } // namespace lld diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index ade0dceeb2c..155fe3f5823 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -126,7 +126,7 @@ template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) { for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles()) for (InputSectionBase<ELFT> *Sec : F->getSections()) if (Sec && Sec != &InputSection<ELFT>::Discarded) - if (isReserved(Sec) || Script->shouldKeep<ELFT>(Sec)) + if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec)) Enqueue(Sec); // Mark all reachable sections. diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index acbdd31cb1a..9052aec88f8 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -908,7 +908,7 @@ static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> A) { } template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) { - ArrayRef<uint8_t> Filler = Script->getFiller(this->Name); + ArrayRef<uint8_t> Filler = Script<ELFT>::X->getFiller(this->Name); if (!Filler.empty()) fill(Buf, this->getSize(), Filler); if (Config->Threads) { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 5d98ff7c99b..8fb71c53d6d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -220,8 +220,8 @@ template <class ELFT> void Writer<ELFT>::run() { } else { createPhdrs(); fixHeaders(); - if (Script->DoLayout) { - Script->assignAddresses(OutputSections); + if (ScriptConfig->DoLayout) { + Script<ELFT>::X->assignAddresses(OutputSections); } else { fixSectionAlignments(); assignAddresses(); @@ -776,7 +776,7 @@ static bool compareSections(OutputSectionBase<ELFT> *A, OutputSectionBase<ELFT> *B) { typedef typename ELFT::uint uintX_t; - int Comp = Script->compareSections(A->getName(), B->getName()); + int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName()); if (Comp != 0) return Comp < 0; @@ -918,7 +918,7 @@ void Writer<ELFT>::addCopyRelSymbol(SharedSymbol<ELFT> *SS) { template <class ELFT> StringRef Writer<ELFT>::getOutputSectionName(InputSectionBase<ELFT> *S) const { - StringRef Dest = Script->getOutputSection<ELFT>(S); + StringRef Dest = Script<ELFT>::X->getOutputSection(S); if (!Dest.empty()) return Dest; @@ -943,7 +943,7 @@ void reportDiscarded(InputSectionBase<ELFT> *IS, template <class ELFT> bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const { return !S || S == &InputSection<ELFT>::Discarded || !S->Live || - Script->isDiscarded(S); + Script<ELFT>::X->isDiscarded(S); } template <class ELFT> @@ -1545,7 +1545,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { // sections. These are special, we do not include them into output sections // list, but have them to simplify the code. template <class ELFT> void Writer<ELFT>::fixHeaders() { - uintX_t BaseVA = Script->DoLayout ? 0 : Target->getVAStart(); + uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart(); Out<ELFT>::ElfHeader->setVA(BaseVA); Out<ELFT>::ElfHeader->setFileOffset(0); uintX_t Off = Out<ELFT>::ElfHeader->getSize(); |