[lld] r266908 - ELF: Template LinkerScript class.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 20 13:13:41 PDT 2016


Author: ruiu
Date: Wed Apr 20 15:13:41 2016
New Revision: 266908

URL: http://llvm.org/viewvc/llvm-project?rev=266908&view=rev
Log:
ELF: Template LinkerScript class.

Originally, linker scripts were basically an alternative way to specify
options to the command line options. But as we add more features to hanlde
symbols and sections, many member functions needed to be templated.
Now most the members are templated. It is probably time to template the
entire class.

Previously, LinkerScript is an executor of the linker script as well as
a storage of linker script configurations. This is not suitable to template
the class because when we are reading linker script files, we don't know
the ELF type yet, so we can't instantiate ELF-templated classes.

In this patch, I defined a new class, ScriptConfiguration, to store
linker script configurations. ScriptParser writes parse results to it,
and LinkerScript uses them.

Differential Revision: http://reviews.llvm.org/D19302

Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Apr 20 15:13:41 2016
@@ -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 Pat
 
   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::Inpu
 
 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;
 

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Apr 20 15:13:41 2016
@@ -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<String
 }
 
 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<OutputSectionBas
 }
 
 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::getFille
 // 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::
   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::readLocationCounterVa
 
 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::readOutputSectionDesc
       return;
     }
     Tok = Tok.substr(3);
-    Script->Filler[OutSec] = parseHex(Tok);
+    Opt.Filler[OutSec] = parseHex(Tok);
     next();
   }
 }
@@ -532,32 +535,13 @@ static bool isUnderSysroot(StringRef Pat
   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<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> *> &);
+template class elf::LinkerScript<ELF32LE>;
+template class elf::LinkerScript<ELF32BE>;
+template class elf::LinkerScript<ELF64LE>;
+template class elf::LinkerScript<ELF64BE>;

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Apr 20 15:13:41 2016
@@ -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

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Wed Apr 20 15:13:41 2016
@@ -126,7 +126,7 @@ template <class ELFT> void elf::markLive
   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.

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Apr 20 15:13:41 2016
@@ -908,7 +908,7 @@ static void fill(uint8_t *Buf, size_t Si
 }
 
 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) {

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=266908&r1=266907&r2=266908&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Apr 20 15:13:41 2016
@@ -220,8 +220,8 @@ template <class ELFT> void Writer<ELFT>:
   } 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(OutputSectio
                             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(Shar
 
 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<EL
 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>:
 // 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();




More information about the llvm-commits mailing list