Add a unit test for LinkerScript.
authorRui Ueyama <ruiu@google.com>
Wed, 28 Jan 2015 18:38:50 +0000 (18:38 +0000)
committerRui Ueyama <ruiu@google.com>
Wed, 28 Jan 2015 18:38:50 +0000 (18:38 +0000)
llvm-svn: 227341

lld/include/lld/Driver/Driver.h
lld/lib/Driver/GnuLdDriver.cpp
lld/unittests/DriverTests/GnuLdDriverTest.cpp

index b42ea3a..1875ab2 100644 (file)
@@ -76,6 +76,12 @@ public:
                     std::unique_ptr<ELFLinkingContext> &context,
                     raw_ostream &diagnostics = llvm::errs());
 
+  /// Parses a given memory buffer as a linker script and evaluate that.
+  /// Public function for testing.
+  static std::error_code evalLinkerScript(ELFLinkingContext &ctx,
+                                          std::unique_ptr<MemoryBuffer> mb,
+                                          raw_ostream &diag);
+
 private:
   static llvm::Triple getDefaultTarget(const char *progName);
   static bool applyEmulation(llvm::Triple &triple,
index 6b68f9c..2444384 100644 (file)
@@ -249,9 +249,12 @@ evaluateLinkerScriptGroup(ELFLinkingContext &ctx, StringRef path,
   for (const script::Path &path : group->getPaths()) {
     ErrorOr<StringRef> pathOrErr = path._isDashlPrefix
       ? ctx.searchLibrary(path._path) : ctx.searchFile(path._path, sysroot);
-    if (std::error_code ec = pathOrErr.getError())
-      return make_dynamic_error_code(
-        Twine("Unable to find file ") + path._path + ": " + ec.message());
+    if (std::error_code ec = pathOrErr.getError()) {
+      auto file = llvm::make_unique<ErrorFile>(path._path, ec);
+      ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
+      ++numfiles;
+      continue;
+    }
 
     std::vector<std::unique_ptr<File>> files
       = loadFile(ctx, pathOrErr.get(), false);
@@ -266,20 +269,17 @@ evaluateLinkerScriptGroup(ELFLinkingContext &ctx, StringRef path,
   return std::error_code();
 }
 
-static std::error_code
-evaluateLinkerScript(ELFLinkingContext &ctx, StringRef path,
-                     raw_ostream &diag) {
+std::error_code
+GnuLdDriver::evalLinkerScript(ELFLinkingContext &ctx,
+                              std::unique_ptr<MemoryBuffer> mb,
+                              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;
-  auto lexer = llvm::make_unique<script::Lexer>(std::move(mb.get()));
+  StringRef path = mb->getBufferIdentifier();
+  auto lexer = llvm::make_unique<script::Lexer>(std::move(mb));
   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.
   for (const script::Command *c : script->_commands)
@@ -623,7 +623,15 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
       if (isScript) {
         if (ctx->logInputFiles())
           diagnostics << path << "\n";
-        std::error_code ec = evaluateLinkerScript(*ctx, realpath, diagnostics);
+        ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
+          MemoryBuffer::getFileOrSTDIN(path);
+        if (std::error_code ec = mb.getError()) {
+          diagnostics << "Cannot open " << path << ": "
+                      << ec.message() << "\n";
+          return false;
+        }
+        std::error_code ec = evalLinkerScript(*ctx, std::move(mb.get()),
+                                              diagnostics);
         if (ec) {
           diagnostics << path << ": Error parsing linker script: "
                       << ec.message() << "\n";
index a1445ab..b5a819c 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "DriverTest.h"
 #include "lld/ReaderWriter/ELFLinkingContext.h"
+#include "llvm/Support/MemoryBuffer.h"
 
 using namespace llvm;
 using namespace lld;
@@ -145,3 +146,21 @@ TEST_F(GnuLdParserTest, DefsymMisssingSymbol) {
 TEST_F(GnuLdParserTest, DefsymMisssingValue) {
   EXPECT_FALSE(parse("ld", "a.o", "--defsym=sym=", nullptr));
 }
+
+// Linker script
+
+TEST_F(GnuLdParserTest, LinkerScriptGroup) {
+  parse("ld", "a.o", nullptr);
+  std::unique_ptr<MemoryBuffer> mb = MemoryBuffer::getMemBuffer(
+    "GROUP(/x /y)", "foo.so");
+  std::string s;
+  raw_string_ostream out(s);
+  std::error_code ec = GnuLdDriver::evalLinkerScript(
+    *_context, std::move(mb), out);
+  EXPECT_FALSE(ec);
+  std::vector<std::unique_ptr<Node>> &nodes = _context->getNodes();
+  EXPECT_EQ((size_t)4, nodes.size());
+  EXPECT_EQ("/x", cast<FileNode>(nodes[1].get())->getFile()->path());
+  EXPECT_EQ("/y", cast<FileNode>(nodes[2].get())->getFile()->path());
+  EXPECT_EQ(2, cast<GroupEnd>(nodes[3].get())->getSize());
+}