Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -10,6 +10,7 @@ #ifndef LLD_READER_WRITER_ELF_LINKER_CONTEXT_H #define LLD_READER_WRITER_ELF_LINKER_CONTEXT_H +#include "LinkerScript.h" #include "lld/Core/LinkingContext.h" #include "lld/Core/Pass.h" #include "lld/Core/PassManager.h" @@ -291,6 +292,23 @@ bool alignSegments() const { return _alignSegments; } void setAlignSegments(bool align) { _alignSegments = align; } + // We can parse several "implicit" linker scripts, which are all input files + // that are not recognized as objects or archives. These are stored in the + // ELFLinkingContext with addLinkerScriptInstance(). However, only one + // "master" linker script can override the default linker script, specified + // with -T in the command line and, here, by calling + // addMasterLinkerScript(). + script::ScriptInstance & + addLinkerScriptInstance(std::unique_ptr script) { + _scripts.push_back(std::move(script)); + return *_scripts.back().get(); + } + script::ScriptInstance & + addMasterLinkerScript(std::unique_ptr script) { + _scripts.push_back(std::move(script)); + _masterLinkerScript = _scripts.back().get(); + return *_masterLinkerScript; + } private: ELFLinkingContext() LLVM_DELETED_FUNCTION; @@ -330,6 +348,8 @@ StringRefVector _rpathLinkList; std::map _absoluteSymbols; llvm::StringSet<> _dynamicallyExportedSymbols; + std::vector> _scripts; + script::ScriptInstance *_masterLinkerScript; }; } // end namespace lld Index: include/lld/ReaderWriter/LinkerScript.h =================================================================== --- include/lld/ReaderWriter/LinkerScript.h +++ include/lld/ReaderWriter/LinkerScript.h @@ -722,6 +722,10 @@ public: explicit Parser(Lexer &lex) : _lex(lex), _peekAvailable(false) {} + /// 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; + LinkerScript *parse(); private: @@ -964,6 +968,24 @@ bool _peekAvailable; Token _bufferedToken; }; + +/// Encapsulates a linker script reading session, including lexer, parser and +/// semantic analysis. +class ScriptInstance { +public: + ScriptInstance(std::unique_ptr mb) + : _lex(llvm::make_unique(std::move(mb))), + _parser(llvm::make_unique(*_lex)) { + _topLevelNode = _parser->parse(); + } + + LinkerScript *getTopLevelNode(); + +private: + std::unique_ptr _lex; + std::unique_ptr _parser; + LinkerScript *_topLevelNode; +}; } // end namespace script } // end namespace lld Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -274,9 +274,9 @@ raw_ostream &diag) { // Read the script file from disk and parse. StringRef path = mb->getBufferIdentifier(); - auto lexer = llvm::make_unique(std::move(mb)); - auto parser = llvm::make_unique(*lexer); - script::LinkerScript *script = parser->parse(); + script::LinkerScript *script = + ctx.addLinkerScriptInstance(llvm::make_unique( + std::move(mb))).getTopLevelNode(); if (!script) return LinkerScriptReaderError::parse_error; // Evaluate script commands. Index: lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -62,7 +62,7 @@ _dynamicLinkerArg(false), _noAllowDynamicLibraries(false), _mergeRODataToTextSegment(true), _demangle(true), _alignSegments(true), _outputMagic(OutputMagic::DEFAULT), _initFunction("_init"), - _finiFunction("_fini"), _sysrootPath("") {} + _finiFunction("_fini"), _sysrootPath(""), _masterLinkerScript(nullptr) {} void ELFLinkingContext::addPasses(PassManager &pm) { pm.add(std::unique_ptr(new elf::OrderPass())); Index: lib/ReaderWriter/LinkerScript.cpp =================================================================== --- lib/ReaderWriter/LinkerScript.cpp +++ lib/ReaderWriter/LinkerScript.cpp @@ -1917,5 +1917,10 @@ return new (_alloc) Sections(sectionsCommands); } +// ScriptInstance functions +LinkerScript *ScriptInstance::getTopLevelNode() { + return _topLevelNode; +} + } // end namespace script } // end namespace lld