[lld] r260591 - ELF: Create LinkerScript class to move code out of Writer.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 11 13:18:00 PST 2016


Author: ruiu
Date: Thu Feb 11 15:17:59 2016
New Revision: 260591

URL: http://llvm.org/viewvc/llvm-project?rev=260591&view=rev
Log:
ELF: Create LinkerScript class to move code out of Writer.

Previously, we had code for linker scripts in Writer. This patch
separates that as LinkerScript class. The class provides a few
functions to query linker scripts and is also a container of some
linker-script-specific information.

Hopefully, Writer will only implement the default behavior and let
the new class handle gotchas regarding linker scripts.

Added:
    lld/trunk/ELF/LinkerScript.h
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Thu Feb 11 15:17:59 2016
@@ -48,7 +48,6 @@ struct Configuration {
   llvm::StringRef SoName;
   llvm::StringRef Sysroot;
   std::string RPath;
-  llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
   std::vector<llvm::StringRef> SearchPaths;
   std::vector<llvm::StringRef> Undefined;
   bool AllowMultipleDefinition;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Feb 11 15:17:59 2016
@@ -11,6 +11,7 @@
 #include "Config.h"
 #include "Error.h"
 #include "InputFiles.h"
+#include "LinkerScript.h"
 #include "SymbolTable.h"
 #include "Target.h"
 #include "Writer.h"
@@ -34,8 +35,10 @@ bool elf2::link(ArrayRef<const char *> A
   ErrorOS = &Error;
   Configuration C;
   LinkerDriver D;
+  LinkerScript LS;
   Config = &C;
   Driver = &D;
+  Script = &LS;
   Driver->main(Args.slice(1));
   return !HasError;
 }
@@ -292,6 +295,7 @@ void LinkerDriver::createFiles(opt::Inpu
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
   SymbolTable<ELFT> Symtab;
   Target.reset(createTarget());
+  Script->finalize();
 
   if (!Config->Shared) {
     // Add entry symbol.

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Feb 11 15:17:59 2016
@@ -13,6 +13,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "LinkerScript.h"
 #include "Config.h"
 #include "Driver.h"
 #include "SymbolTable.h"
@@ -25,10 +26,36 @@ using namespace llvm;
 using namespace lld;
 using namespace lld::elf2;
 
-namespace {
-class LinkerScript {
+LinkerScript *elf2::Script;
+
+void LinkerScript::finalize() {
+  for (const std::pair<StringRef, std::vector<StringRef>> &P : Sections)
+    for (StringRef S : P.second)
+      RevSections[S] = P.first;
+}
+
+StringRef LinkerScript::getOutputSection(StringRef S) {
+  return RevSections.lookup(S);
+}
+
+bool LinkerScript::isDiscarded(StringRef S) {
+  return RevSections.lookup(S) == "/DISCARD/";
+}
+
+int LinkerScript::compareSections(StringRef A, StringRef B) {
+  auto I = Sections.find(A);
+  auto E = Sections.end();
+  if (I == E)
+    return 0;
+  auto J = Sections.find(B);
+  if (J == E)
+    return 0;
+  return I < J ? -1 : 1;
+}
+
+class elf2::ScriptParser {
 public:
-  LinkerScript(BumpPtrAllocator *A, StringRef S, bool B)
+  ScriptParser(BumpPtrAllocator *A, StringRef S, bool B)
       : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
   void run();
 
@@ -62,9 +89,8 @@ private:
   size_t Pos = 0;
   bool IsUnderSysroot;
 };
-}
 
-void LinkerScript::run() {
+void ScriptParser::run() {
   while (!atEOF()) {
     StringRef Tok = next();
     if (Tok == ";")
@@ -95,7 +121,7 @@ void LinkerScript::run() {
 }
 
 // We don't want to record cascading errors. Keep only the first one.
-void LinkerScript::setError(const Twine &Msg) {
+void ScriptParser::setError(const Twine &Msg) {
   if (Error)
     return;
   error(Msg);
@@ -103,7 +129,7 @@ void LinkerScript::setError(const Twine
 }
 
 // Split S into linker script tokens.
-std::vector<StringRef> LinkerScript::tokenize(StringRef S) {
+std::vector<StringRef> ScriptParser::tokenize(StringRef S) {
   std::vector<StringRef> Ret;
   for (;;) {
     S = skipSpace(S);
@@ -136,7 +162,7 @@ std::vector<StringRef> LinkerScript::tok
 }
 
 // Skip leading whitespace characters or /**/-style comments.
-StringRef LinkerScript::skipSpace(StringRef S) {
+StringRef ScriptParser::skipSpace(StringRef S) {
   for (;;) {
     if (S.startswith("/*")) {
       size_t E = S.find("*/", 2);
@@ -155,9 +181,9 @@ StringRef LinkerScript::skipSpace(String
 }
 
 // An errneous token is handled as if it were the last token before EOF.
-bool LinkerScript::atEOF() { return Error || Tokens.size() == Pos; }
+bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; }
 
-StringRef LinkerScript::next() {
+StringRef ScriptParser::next() {
   if (Error)
     return "";
   if (atEOF()) {
@@ -167,7 +193,7 @@ StringRef LinkerScript::next() {
   return Tokens[Pos++];
 }
 
-bool LinkerScript::skip(StringRef Tok) {
+bool ScriptParser::skip(StringRef Tok) {
   if (Error)
     return false;
   if (atEOF()) {
@@ -180,7 +206,7 @@ bool LinkerScript::skip(StringRef Tok) {
   return true;
 }
 
-void LinkerScript::expect(StringRef Expect) {
+void ScriptParser::expect(StringRef Expect) {
   if (Error)
     return;
   StringRef Tok = next();
@@ -188,7 +214,7 @@ void LinkerScript::expect(StringRef Expe
     setError(Expect + " expected, but got " + Tok);
 }
 
-void LinkerScript::addFile(StringRef S) {
+void ScriptParser::addFile(StringRef S) {
   if (IsUnderSysroot && S.startswith("/")) {
     SmallString<128> Path;
     (Config->Sysroot + S).toStringRef(Path);
@@ -218,7 +244,7 @@ void LinkerScript::addFile(StringRef S)
   }
 }
 
-void LinkerScript::readAsNeeded() {
+void ScriptParser::readAsNeeded() {
   expect("(");
   bool Orig = Config->AsNeeded;
   Config->AsNeeded = true;
@@ -231,7 +257,7 @@ void LinkerScript::readAsNeeded() {
   Config->AsNeeded = Orig;
 }
 
-void LinkerScript::readEntry() {
+void ScriptParser::readEntry() {
   // -e <symbol> takes predecence over ENTRY(<symbol>).
   expect("(");
   StringRef Tok = next();
@@ -240,7 +266,7 @@ void LinkerScript::readEntry() {
   expect(")");
 }
 
-void LinkerScript::readExtern() {
+void ScriptParser::readExtern() {
   expect("(");
   while (!Error) {
     StringRef Tok = next();
@@ -250,7 +276,7 @@ void LinkerScript::readExtern() {
   }
 }
 
-void LinkerScript::readGroup() {
+void ScriptParser::readGroup() {
   expect("(");
   while (!Error) {
     StringRef Tok = next();
@@ -264,7 +290,7 @@ void LinkerScript::readGroup() {
   }
 }
 
-void LinkerScript::readInclude() {
+void ScriptParser::readInclude() {
   StringRef Tok = next();
   auto MBOrErr = MemoryBuffer::getFile(Tok);
   if (!MBOrErr) {
@@ -277,7 +303,7 @@ void LinkerScript::readInclude() {
   Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
 }
 
-void LinkerScript::readOutput() {
+void ScriptParser::readOutput() {
   // -o <file> takes predecence over OUTPUT(<file>).
   expect("(");
   StringRef Tok = next();
@@ -286,14 +312,14 @@ void LinkerScript::readOutput() {
   expect(")");
 }
 
-void LinkerScript::readOutputArch() {
+void ScriptParser::readOutputArch() {
   // Error checking only for now.
   expect("(");
   next();
   expect(")");
 }
 
-void LinkerScript::readOutputFormat() {
+void ScriptParser::readOutputFormat() {
   // Error checking only for now.
   expect("(");
   next();
@@ -310,29 +336,27 @@ void LinkerScript::readOutputFormat() {
   expect(")");
 }
 
-void LinkerScript::readSearchDir() {
+void ScriptParser::readSearchDir() {
   expect("(");
   Config->SearchPaths.push_back(next());
   expect(")");
 }
 
-void LinkerScript::readSections() {
+void ScriptParser::readSections() {
   expect("{");
   while (!Error && !skip("}"))
     readOutputSectionDescription();
 }
 
-void LinkerScript::readOutputSectionDescription() {
-  StringRef Name = next();
-  std::vector<StringRef> &InputSections = Config->OutputSections[Name];
-
+void ScriptParser::readOutputSectionDescription() {
+  std::vector<StringRef> &V = Script->Sections[next()];
   expect(":");
   expect("{");
   while (!Error && !skip("}")) {
     next(); // Skip input file name.
     expect("(");
     while (!Error && !skip(")"))
-      InputSections.push_back(next());
+      V.push_back(next());
   }
 }
 
@@ -348,5 +372,5 @@ static bool isUnderSysroot(StringRef Pat
 // Entry point. The other functions or classes are private to this file.
 void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
   StringRef Path = MB.getBufferIdentifier();
-  LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
+  ScriptParser(A, MB.getBuffer(), isUnderSysroot(Path)).run();
 }

Added: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=260591&view=auto
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (added)
+++ lld/trunk/ELF/LinkerScript.h Thu Feb 11 15:17:59 2016
@@ -0,0 +1,45 @@
+//===- LinkerScript.h -------------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_LINKER_SCRIPT_H
+#define LLD_ELF_LINKER_SCRIPT_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
+
+namespace lld {
+namespace elf2 {
+
+class ScriptParser;
+
+class LinkerScript {
+  friend class ScriptParser;
+
+public:
+  StringRef getOutputSection(StringRef InputSection);
+  bool isDiscarded(StringRef InputSection);
+  int compareSections(StringRef A, StringRef B);
+  void finalize();
+
+private:
+  // Map for SECTIONS command. The key is output section name
+  // and a value is a list of input section names.
+  llvm::MapVector<StringRef, std::vector<StringRef>> Sections;
+
+  // Inverse map of Sections.
+  llvm::DenseMap<StringRef, StringRef> RevSections;
+};
+
+extern LinkerScript *Script;
+
+} // namespace elf2
+} // namespace lld
+
+#endif

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=260591&r1=260590&r2=260591&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Feb 11 15:17:59 2016
@@ -9,6 +9,7 @@
 
 #include "Writer.h"
 #include "Config.h"
+#include "LinkerScript.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Target.h"
@@ -68,7 +69,6 @@ private:
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
   void createPhdrs();
   void assignAddresses();
-  void buildSectionMap();
   void fixAbsoluteSymbols();
   bool openFile();
   void writeHeader();
@@ -111,8 +111,6 @@ private:
   uintX_t FileSize;
   uintX_t SectionHeaderOff;
 
-  llvm::StringMap<llvm::StringRef> InputToOutputSection;
-
   // Flag to force GOT to be in output if we have relocations
   // that relies on its address.
   bool HasGotOffRel = false;
@@ -190,7 +188,6 @@ template <class ELFT> void elf2::writeRe
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
-  buildSectionMap();
   if (!Config->DiscardAll)
     copyLocalSymbols();
   addReservedSymbols();
@@ -595,10 +592,14 @@ template <class ELFT> static bool isRelr
 
 // Output section ordering is determined by this function.
 template <class ELFT>
-static bool compareOutputSections(OutputSectionBase<ELFT> *A,
-                                  OutputSectionBase<ELFT> *B) {
+static bool compareSections(OutputSectionBase<ELFT> *A,
+                            OutputSectionBase<ELFT> *B) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
+  int Comp = Script->compareSections(A->getName(), B->getName());
+  if (Comp != 0)
+    return Comp < 0;
+
   uintX_t AFlags = A->getFlags();
   uintX_t BFlags = B->getFlags();
 
@@ -721,9 +722,9 @@ void Writer<ELFT>::addCopyRelSymbols(std
 
 template <class ELFT>
 StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
-  auto It = InputToOutputSection.find(S);
-  if (It != std::end(InputToOutputSection))
-    return It->second;
+  StringRef Out = Script->getOutputSection(S);
+  if (!Out.empty())
+    return Out;
 
   for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
                       ".init_array.", ".fini_array.", ".ctors.", ".dtors."})
@@ -742,24 +743,9 @@ void reportDiscarded(InputSectionBase<EL
 }
 
 template <class ELFT>
-bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
-  if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
-    return true;
-  return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
-}
-
-template <class ELFT>
-static bool compareSections(OutputSectionBase<ELFT> *A,
-                            OutputSectionBase<ELFT> *B) {
-  auto ItA = Config->OutputSections.find(A->getName());
-  auto ItEnd = std::end(Config->OutputSections);
-  if (ItA == ItEnd)
-    return compareOutputSections(A, B);
-  auto ItB = Config->OutputSections.find(B->getName());
-  if (ItB == ItEnd)
-    return compareOutputSections(A, B);
-
-  return std::distance(ItA, ItB) > 0;
+bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
+  return !S || !S->isLive() || S == &InputSection<ELFT>::Discarded ||
+         Script->isDiscarded(S->getSectionName());
 }
 
 // The beginning and the ending of .rel[a].plt section are marked
@@ -1487,13 +1473,6 @@ template <class ELFT> void Writer<ELFT>:
       Sec->writeTo(Buf + Sec->getFileOff());
 }
 
-template <class ELFT> void Writer<ELFT>::buildSectionMap() {
-  for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
-       Config->OutputSections)
-    for (StringRef Name : OutSec.second)
-      InputToOutputSection[Name] = OutSec.first;
-}
-
 template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
 template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
 template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);




More information about the llvm-commits mailing list