diff options
| author | Rafael Auler <rafaelauler@gmail.com> | 2015-02-03 16:08:57 +0000 |
|---|---|---|
| committer | Rafael Auler <rafaelauler@gmail.com> | 2015-02-03 16:08:57 +0000 |
| commit | ee95c3b5c57f7b3e4fe369f543b14d2b677789f1 (patch) | |
| tree | fdf645ab3567e69f856bda9277e2cdaa9979e2ef | |
| parent | 0285fc869ddcdce44ebd301580cd3dd6797e0dc2 (diff) | |
| download | bcm5719-llvm-ee95c3b5c57f7b3e4fe369f543b14d2b677789f1.tar.gz bcm5719-llvm-ee95c3b5c57f7b3e4fe369f543b14d2b677789f1.zip | |
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
llvm-svn: 227975
| -rw-r--r-- | lld/include/lld/ReaderWriter/ELFLinkingContext.h | 8 | ||||
| -rw-r--r-- | lld/include/lld/ReaderWriter/LinkerScript.h | 16 | ||||
| -rw-r--r-- | lld/lib/Driver/GnuLdDriver.cpp | 9 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/LinkerScript.cpp | 27 | ||||
| -rw-r--r-- | lld/utils/linker-script-test/linker-script-test.cpp | 8 |
5 files changed, 44 insertions, 24 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index 915492a5637..e544bcd7aa6 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -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 diff --git a/lld/include/lld/ReaderWriter/LinkerScript.h b/lld/include/lld/ReaderWriter/LinkerScript.h index 26f1ea44253..39f0df8e7e1 100644 --- a/lld/include/lld/ReaderWriter/LinkerScript.h +++ b/lld/include/lld/ReaderWriter/LinkerScript.h @@ -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; diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index e4f757e6d1a..5100918511f 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -274,9 +274,10 @@ GnuLdDriver::evalLinkerScript(ELFLinkingContext &ctx, 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(ELFLinkingContext &ctx, 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(); } diff --git a/lld/lib/ReaderWriter/LinkerScript.cpp b/lld/lib/ReaderWriter/LinkerScript.cpp index c8dbfdd32fb..24dfe1beee6 100644 --- a/lld/lib/ReaderWriter/LinkerScript.cpp +++ b/lld/lib/ReaderWriter/LinkerScript.cpp @@ -892,67 +892,67 @@ void Sections::dump(raw_ostream &os) const { } // 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() { diff --git a/lld/utils/linker-script-test/linker-script-test.cpp b/lld/utils/linker-script-test/linker-script-test.cpp index 974989833e8..027ecb36c38 100644 --- a/lld/utils/linker-script-test/linker-script-test.cpp +++ b/lld/utils/linker-script-test/linker-script-test.cpp @@ -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()); + } } } |

