[lld] r227975 - Make ELFLinkingContext own LinkerScript buffers

Rafael Auler rafaelauler at gmail.com
Tue Feb 3 08:08:57 PST 2015


Author: rafauler
Date: Tue Feb  3 10:08:57 2015
New Revision: 227975

URL: http://llvm.org/viewvc/llvm-project?rev=227975&view=rev
Log:
Make ELFLinkingContext own LinkerScript buffers

Currently, no one owns script::Parser buffers, but yet ELFLinkingContext gets
updated with StringRef pointers to data inside Parser buffers. Since this buffer
is locally owned inside GnuLdDriver::evalLinkerScript(), as soon as this
function finishes, all pointers in ELFLinkingContext that comes from linker
scripts get invalid. The problem is that we need someone to own linker scripts
data structures and, since ELFLinkingContext transports references to linker
scripts data, we can simply make it also own all linker scripts data.

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


Modified:
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/LinkerScript.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/ReaderWriter/LinkerScript.cpp
    lld/trunk/utils/linker-script-test/linker-script-test.cpp

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=227975&r1=227974&r2=227975&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Tue Feb  3 10:08:57 2015
@@ -17,6 +17,7 @@
 #include "lld/Core/range.h"
 #include "lld/Core/Reader.h"
 #include "lld/Core/Writer.h"
+#include "lld/ReaderWriter/LinkerScript.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Object/ELF.h"
@@ -296,6 +297,12 @@ public:
     addSearchPath("=/usr/lib");
   }
 
+  // We can parse several linker scripts via command line whose ASTs are stored
+  // in the current linking context via addLinkerScript().
+  void addLinkerScript(std::unique_ptr<script::Parser> script) {
+    _scripts.push_back(std::move(script));
+  }
+
 private:
   ELFLinkingContext() LLVM_DELETED_FUNCTION;
 
@@ -335,6 +342,7 @@ protected:
   StringRefVector _rpathLinkList;
   std::map<std::string, uint64_t> _absoluteSymbols;
   llvm::StringSet<> _dynamicallyExportedSymbols;
+  std::vector<std::unique_ptr<script::Parser>> _scripts;
 };
 } // end namespace lld
 

Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=227975&r1=227974&r2=227975&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Tue Feb  3 10:08:57 2015
@@ -15,6 +15,7 @@
 #ifndef LLD_READER_WRITER_LINKER_SCRIPT_H
 #define LLD_READER_WRITER_LINKER_SCRIPT_H
 
+#include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
 #include "lld/Core/range.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -739,9 +740,18 @@ public:
 /// https://sourceware.org/binutils/docs/ld/Scripts.html
 class Parser {
 public:
-  explicit Parser(Lexer &lex) : _lex(lex), _peekAvailable(false) {}
+  explicit Parser(std::unique_ptr<MemoryBuffer> mb)
+      : _lex(std::move(mb)), _peekAvailable(false) {}
 
-  LinkerScript *parse();
+  /// Let's not allow copying of Parser class because it would be expensive
+  /// to update all the AST pointers to a new buffer.
+  Parser(const Parser &instance) LLVM_DELETED_FUNCTION;
+
+  /// Lex and parse the current memory buffer to create a linker script AST.
+  std::error_code parse();
+
+  /// Returns a reference to the top level node of the linker script AST.
+  LinkerScript *get() { return &_script; }
 
 private:
   /// Advances to the next token, either asking the Lexer to lex the next token
@@ -981,7 +991,7 @@ private:
   // The top-level/entry-point linker script AST node
   LinkerScript _script;
 
-  Lexer &_lex;
+  Lexer _lex;
 
   // Current token being analyzed
   Token _tok;

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=227975&r1=227974&r2=227975&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Feb  3 10:08:57 2015
@@ -274,9 +274,10 @@ GnuLdDriver::evalLinkerScript(ELFLinking
                               raw_ostream &diag) {
   // Read the script file from disk and parse.
   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();
+  auto parser = llvm::make_unique<script::Parser>(std::move(mb));
+  if (std::error_code ec = parser->parse())
+    return ec;
+  script::LinkerScript *script = parser->get();
   if (!script)
     return LinkerScriptReaderError::parse_error;
   // Evaluate script commands.
@@ -292,6 +293,8 @@ GnuLdDriver::evalLinkerScript(ELFLinking
     if (auto *output = dyn_cast<script::Output>(c))
       ctx.setOutputPath(output->getOutputFileName());
   }
+  // Transfer ownership of the script to the linking context
+  ctx.addLinkerScript(std::move(parser));
   return std::error_code();
 }
 

Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=227975&r1=227974&r2=227975&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Tue Feb  3 10:08:57 2015
@@ -892,67 +892,67 @@ void Sections::dump(raw_ostream &os) con
 }
 
 // Parser functions
-LinkerScript *Parser::parse() {
+std::error_code Parser::parse() {
   // Get the first token.
   _lex.lex(_tok);
   // Parse top level commands.
   while (true) {
     switch (_tok._kind) {
     case Token::eof:
-      return &_script;
+      return std::error_code();
     case Token::semicolon:
       consumeToken();
       break;
     case Token::kw_output: {
       auto output = parseOutput();
       if (!output)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(output);
       break;
     }
     case Token::kw_output_format: {
       auto outputFormat = parseOutputFormat();
       if (!outputFormat)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(outputFormat);
       break;
     }
     case Token::kw_output_arch: {
       auto outputArch = parseOutputArch();
       if (!outputArch)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(outputArch);
       break;
     }
     case Token::kw_group: {
       auto group = parseGroup();
       if (!group)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(group);
       break;
     }
     case Token::kw_as_needed:
       // Not allowed at top level.
       error(_tok, "AS_NEEDED not allowed at top level.");
-      return nullptr;
+      return LinkerScriptReaderError::parse_error;
     case Token::kw_entry: {
       Entry *entry = parseEntry();
       if (!entry)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(entry);
       break;
     }
     case Token::kw_search_dir: {
       SearchDir *searchDir = parseSearchDir();
       if (!searchDir)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(searchDir);
       break;
     }
     case Token::kw_sections: {
       Sections *sections = parseSections();
       if (!sections)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(sections);
       break;
     }
@@ -962,18 +962,17 @@ LinkerScript *Parser::parse() {
     case Token::kw_provide_hidden: {
       const Command *cmd = parseSymbolAssignment();
       if (!cmd)
-        return nullptr;
+        return LinkerScriptReaderError::parse_error;
       _script._commands.push_back(cmd);
       break;
     }
     default:
       // Unexpected.
       error(_tok, "expected linker script command");
-      return nullptr;
+      return LinkerScriptReaderError::parse_error;
     }
   }
-
-  return nullptr;
+  return LinkerScriptReaderError::parse_error;
 }
 
 const Expression *Parser::parseFunctionCall() {

Modified: lld/trunk/utils/linker-script-test/linker-script-test.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/utils/linker-script-test/linker-script-test.cpp?rev=227975&r1=227974&r2=227975&view=diff
==============================================================================
--- lld/trunk/utils/linker-script-test/linker-script-test.cpp (original)
+++ lld/trunk/utils/linker-script-test/linker-script-test.cpp Tue Feb  3 10:08:57 2015
@@ -48,10 +48,10 @@ int main(int argc, const char **argv) {
       llvm::errs() << ec.message() << "\n";
       return 1;
     }
-    Lexer l(std::move(mb.get()));
-    Parser p(l);
-    LinkerScript *ls = p.parse();
-    if (ls)
+    Parser p(std::move(mb.get()));
+    if (!p.parse()) {
+      LinkerScript *ls = p.get();
       ls->dump(llvm::outs());
+    }
   }
 }





More information about the llvm-commits mailing list