[lld] r225330 - [ELF] Remove {ELF,}GNULinkerScript.

Rui Ueyama ruiu at google.com
Tue Jan 6 17:13:08 PST 2015


Author: ruiu
Date: Tue Jan  6 19:13:08 2015
New Revision: 225330

URL: http://llvm.org/viewvc/llvm-project?rev=225330&view=rev
Log:
[ELF] Remove {ELF,}GNULinkerScript.

Instead of representing a linker script file as an "InputElement",
parse and evaluate scripts in the driver as we see them.

Linker scripts are not regular input files (regular file is one of
object, archive, or shared library file). They are more like
extended command line options. Linker script handling was needlessly
complicated because of that inappropriate abstraction (besides
excessive class hierarchy -- there is no such thing like ELF linker
script but we had two classes there for some reason.)

LinkerScript was one of a few remaining InputElement subclasses
that can be expanded to multiple files. With this patch, we are one
step closer to retire InputElement.

http://reviews.llvm.org/D6648

Modified:
    lld/trunk/include/lld/Driver/GnuLdInputGraph.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/GnuLdInputGraph.cpp

Modified: lld/trunk/include/lld/Driver/GnuLdInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/GnuLdInputGraph.h?rev=225330&r1=225329&r2=225330&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/GnuLdInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/GnuLdInputGraph.h Tue Jan  6 19:13:08 2015
@@ -21,7 +21,6 @@
 #include "lld/Core/InputGraph.h"
 #include "lld/Core/Resolver.h"
 #include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "lld/ReaderWriter/LinkerScript.h"
 
 namespace lld {
 
@@ -81,41 +80,6 @@ private:
   const Attributes _attributes;
 };
 
-/// \brief Parse GNU Linker scripts.
-class GNULdScript : public FileNode {
-public:
-  GNULdScript(ELFLinkingContext &ctx, StringRef userPath)
-      : FileNode(userPath), _elfLinkingContext(ctx), _linkerScript(nullptr) {}
-
-  /// \brief Parse the linker script.
-  std::error_code parse(const LinkingContext &, raw_ostream &) override;
-
-protected:
-  ELFLinkingContext &_elfLinkingContext;
-  std::unique_ptr<script::Parser> _parser;
-  std::unique_ptr<script::Lexer> _lexer;
-  script::LinkerScript *_linkerScript;
-};
-
-/// \brief Handle ELF style with GNU Linker scripts.
-class ELFGNULdScript : public GNULdScript {
-public:
-  ELFGNULdScript(ELFLinkingContext &ctx, StringRef userPath)
-      : GNULdScript(ctx, userPath) {}
-
-  std::error_code parse(const LinkingContext &ctx,
-                        raw_ostream &diagnostics) override;
-
-  bool getReplacements(InputGraph::InputElementVectorT &result) override {
-    for (std::unique_ptr<InputElement> &elt : _expandElements)
-      result.push_back(std::move(elt));
-    return true;
-  }
-
-private:
-  InputGraph::InputElementVectorT _expandElements;
-};
-
 } // namespace lld
 
 #endif

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=225330&r1=225329&r2=225330&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Jan  6 19:13:08 2015
@@ -15,6 +15,7 @@
 
 #include "lld/Driver/Driver.h"
 #include "lld/Driver/GnuLdInputGraph.h"
+#include "lld/ReaderWriter/LinkerScript.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
@@ -217,6 +218,54 @@ static bool isLinkerScript(StringRef pat
   return magic == llvm::sys::fs::file_magic::unknown;
 }
 
+static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
+  if (sysroot.empty())
+    return false;
+  while (!path.empty() && !llvm::sys::fs::equivalent(sysroot, path))
+    path = llvm::sys::path::parent_path(path);
+  return !path.empty();
+}
+
+static std::error_code
+evaluateLinkerScript(ELFLinkingContext &ctx, InputGraph *inputGraph,
+                     StringRef path, raw_ostream &diag) {
+  // Read the script file from disk and parse.
+  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
+      MemoryBuffer::getFileOrSTDIN(path);
+  if (std::error_code ec = mb.getError())
+    return ec;
+  if (ctx.logInputFiles())
+    diag << path << "\n";
+  auto lexer = llvm::make_unique<script::Lexer>(std::move(mb.get()));
+  auto parser = llvm::make_unique<script::Parser>(*lexer);
+  script::LinkerScript *script = parser->parse();
+  if (!script)
+    return LinkerScriptReaderError::parse_error;
+
+  // Evaluate script commands.
+  // Currently we only recognize GROUP() command.
+  bool sysroot = (!ctx.getSysroot().empty()
+                  && isPathUnderSysroot(ctx.getSysroot(), path));
+  for (const script::Command *c : script->_commands) {
+    auto *group = dyn_cast<script::Group>(c);
+    if (!group)
+      continue;
+    int numfiles = 0;
+    for (const script::Path &path : group->getPaths()) {
+      // TODO : Propagate Set WholeArchive/dashlPrefix
+      ELFFileNode::Attributes attr;
+      attr.setSysRooted(sysroot);
+      attr.setAsNeeded(path._asNeeded);
+      attr.setDashlPrefix(path._isDashlPrefix);
+      ++numfiles;
+      inputGraph->addInputElement(llvm::make_unique<ELFFileNode>(
+                                      ctx, ctx.allocateString(path._path), attr));
+    }
+    inputGraph->addInputElement(llvm::make_unique<GroupEnd>(numfiles));
+  }
+  return std::error_code();
+}
+
 bool GnuLdDriver::applyEmulation(llvm::Triple &triple,
                                  llvm::opt::InputArgList &args,
                                  raw_ostream &diagnostics) {
@@ -529,19 +578,19 @@ bool GnuLdDriver::parse(int argc, const
       }
       bool isScript =
           (!path.endswith(".objtxt") && isLinkerScript(realpath, diagnostics));
-      FileNode *inputNode = nullptr;
       if (isScript) {
-        inputNode = new ELFGNULdScript(*ctx, realpath);
-        if (inputNode->parse(*ctx, diagnostics)) {
-          diagnostics << path << ": Error parsing linker script\n";
+        std::error_code ec = evaluateLinkerScript(
+            *ctx, inputGraph.get(), realpath, diagnostics);
+        if (ec) {
+          diagnostics << path << ": Error parsing linker script: "
+                      << ec.message() << "\n";
           return false;
         }
-      } else {
-        inputNode = new ELFFileNode(*ctx, path, attributes);
+        break;
       }
-      std::unique_ptr<InputElement> inputFile(inputNode);
       ++numfiles;
-      inputGraph->addInputElement(std::move(inputFile));
+      inputGraph->addInputElement(
+          llvm::make_unique<ELFFileNode>(*ctx, path, attributes));
       break;
     }
 

Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=225330&r1=225329&r2=225330&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Tue Jan  6 19:13:08 2015
@@ -63,68 +63,3 @@ std::error_code ELFFileNode::parse(const
   }
   return ctx.registry().parseFile(std::move(mb.get()), _files);
 }
-
-/// \brief Parse the GnuLD Script
-std::error_code GNULdScript::parse(const LinkingContext &ctx,
-                                   raw_ostream &diagnostics) {
-  ErrorOr<StringRef> filePath = getPath(ctx);
-  if (std::error_code ec = filePath.getError())
-    return ec;
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-      MemoryBuffer::getFileOrSTDIN(*filePath);
-  if (std::error_code ec = mb.getError())
-    return ec;
-
-  if (ctx.logInputFiles())
-    diagnostics << *filePath << "\n";
-
-  _lexer.reset(new script::Lexer(std::move(mb.get())));
-  _parser.reset(new script::Parser(*_lexer.get()));
-
-  _linkerScript = _parser->parse();
-
-  if (!_linkerScript)
-    return LinkerScriptReaderError::parse_error;
-
-  return std::error_code();
-}
-
-static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
-  if (sysroot.empty())
-    return false;
-
-  while (!path.empty() && !llvm::sys::fs::equivalent(sysroot, path))
-    path = llvm::sys::path::parent_path(path);
-
-  return !path.empty();
-}
-
-/// \brief Handle GnuLD script for ELF.
-std::error_code ELFGNULdScript::parse(const LinkingContext &ctx,
-                                      raw_ostream &diagnostics) {
-  ELFFileNode::Attributes attributes;
-  if (std::error_code ec = GNULdScript::parse(ctx, diagnostics))
-    return ec;
-  StringRef sysRoot = _elfLinkingContext.getSysroot();
-  if (!sysRoot.empty() && isPathUnderSysroot(sysRoot, *getPath(ctx)))
-    attributes.setSysRooted(true);
-  for (const script::Command *c : _linkerScript->_commands) {
-    auto *group = dyn_cast<script::Group>(c);
-    if (!group)
-      continue;
-    size_t numfiles = 0;
-    for (const script::Path &path : group->getPaths()) {
-      // TODO : Propagate Set WholeArchive/dashlPrefix
-      attributes.setAsNeeded(path._asNeeded);
-      attributes.setDashlPrefix(path._isDashlPrefix);
-      auto inputNode = new ELFFileNode(
-          _elfLinkingContext, _elfLinkingContext.allocateString(path._path),
-          attributes);
-      std::unique_ptr<InputElement> inputFile(inputNode);
-      _expandElements.push_back(std::move(inputFile));
-      ++numfiles;
-    }
-    _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));
-  }
-  return std::error_code();
-}





More information about the llvm-commits mailing list