Index: include/lld/Core/Error.h =================================================================== --- include/lld/Core/Error.h +++ include/lld/Core/Error.h @@ -70,6 +70,17 @@ return llvm::error_code(static_cast(e), InputGraphErrorCategory()); } +/// \brief Errors returned by Reader. +const llvm::error_category &ReaderErrorCategory(); + +enum class ReaderError { + success = 0, + unknown_file_format = 1 +}; + +inline llvm::error_code make_error_code(ReaderError e) { + return llvm::error_code(static_cast(e), ReaderErrorCategory()); +} } // end namespace lld namespace llvm { @@ -79,6 +90,7 @@ template <> struct is_error_code_enum : true_type {}; template <> struct is_error_code_enum : true_type {}; +template <> struct is_error_code_enum : true_type {}; } // end namespace llvm #endif Index: include/lld/Core/File.h =================================================================== --- include/lld/Core/File.h +++ include/lld/Core/File.h @@ -47,7 +47,6 @@ kindObject, ///< object file (.o) kindSharedLibrary, ///< shared library (.so) kindArchiveLibrary, ///< archive (.a) - kindLinkerScript, ///< linker script }; /// \brief Returns file kind. Need for dyn_cast<> on File objects. Index: include/lld/Core/InputGraph.h =================================================================== --- include/lld/Core/InputGraph.h +++ include/lld/Core/InputGraph.h @@ -70,6 +70,9 @@ /// Destructor virtual ~InputGraph() {} + /// Normalize the InputGraph. + virtual void normalize(); + /// \brief Do postprocessing of the InputGraph if there is a need for the /// to provide additional information to the user, also rearranges /// InputElements by their ordinals. If an user wants to place an input file @@ -128,7 +131,14 @@ enum class Kind : uint8_t { Control, // Represents a type associated with ControlNodes SimpleFile, // Represents a type reserved for internal files - File // Represents a type associated with File Nodes + File, // Represents a type associated with File Nodes + }; + + /// How does the inputGraph expand the InputElement + enum class ExpandType : uint8_t { + None, // Do nothing(Default) + ReplaceAndExpand, // Replace current node and expand + ExpandOnly // Expand the current node }; /// \brief Initialize the Input Element, The ordinal value of an input Element @@ -175,6 +185,18 @@ /// \brief Reset the next index virtual void resetNextIndex() = 0; + /// \brief Is this a hidden node, hidden nodes are not part of + /// of the resolver. + virtual bool isHidden() const { return false; } + + /// \brief How do we want to expand the current node ? + virtual ExpandType expandType() const { return ExpandType::None; } + + /// \brief Get the elements that we want to expand with. + virtual range expandElements() { + llvm_unreachable("no element to expand"); + } + protected: Kind _kind; // The type of the Element int64_t _ordinal; // The ordinal value Index: include/lld/Core/LinkingContext.h =================================================================== --- include/lld/Core/LinkingContext.h +++ include/lld/Core/LinkingContext.h @@ -31,6 +31,7 @@ namespace lld { class PassManager; class File; +class SharedLibraryFile; class Writer; class InputGraph; class InputElement; @@ -163,6 +164,11 @@ /// to be an error. bool allowShlibUndefines() const { return _allowShlibUndefines; } + /// Add undefined symbols from shared libraries ? + virtual bool addUndefinedAtomsFromSharedLibrary(const SharedLibraryFile *) { + return true; + } + /// If true, core linking will write the path to each input file to stdout /// (i.e. llvm::outs()) as it is used. This is used to implement the -t /// linker option. Index: include/lld/Driver/GnuLdInputGraph.h =================================================================== --- include/lld/Driver/GnuLdInputGraph.h +++ include/lld/Driver/GnuLdInputGraph.h @@ -21,6 +21,7 @@ #include "lld/Core/Resolver.h" #include "lld/ReaderWriter/ELFLinkingContext.h" #include "lld/ReaderWriter/FileArchive.h" +#include "lld/ReaderWriter/LinkerScript.h" namespace lld { @@ -71,51 +72,7 @@ } /// \brief Parse the input file to lld::File. - error_code parse(const LinkingContext &ctx, raw_ostream &diagnostics) { - ErrorOr filePath = getPath(ctx); - if (!filePath) - return error_code(filePath); - - if (error_code ec = getBuffer(*filePath)) - return ec; - - if (ctx.logInputFiles()) - diagnostics << *filePath << "\n"; - - if (filePath->endswith(".objtxt")) - return ctx.getYAMLReader().parseFile(_buffer, _files); - - // Identify File type - llvm::sys::fs::file_magic FileType = - llvm::sys::fs::identify_magic(_buffer->getBuffer()); - - switch (FileType) { - case llvm::sys::fs::file_magic::elf_relocatable: - case llvm::sys::fs::file_magic::elf_shared_object: - // Call the default reader to read object files and shared objects - return _elfLinkingContext.getDefaultReader().parseFile(_buffer, _files); - - case llvm::sys::fs::file_magic::archive: { - // Process archive files. If Whole Archive option is set, - // parse all members of the archive. - error_code ec; - std::unique_ptr fileArchive( - new FileArchive(ctx, std::move(_buffer), ec, _isWholeArchive)); - if (_isWholeArchive) { - fileArchive->parseAllMembers(_files); - _archiveFile = std::move(fileArchive); - } else { - _files.push_back(std::move(fileArchive)); - } - return ec; - } - - default: - // Process Linker script - return _elfLinkingContext.getLinkerScriptReader().parseFile(_buffer, - _files); - } - } + error_code parse(const LinkingContext &, raw_ostream &); /// \brief This is used by Group Nodes, when there is a need to reset the /// the file to be processed next. When handling a group node that contains @@ -151,6 +108,74 @@ std::unique_ptr _archiveFile; }; +/// \brief Parse GNU Linker scripts. + +class GNULdScript : public FileNode { +public: + GNULdScript(ELFLinkingContext &ctx, StringRef userPath, int64_t ordinal) + : FileNode(userPath, ordinal), _elfLinkingContext(ctx) {} + + static inline bool classof(const InputElement *a) { + return a->kind() == InputElement::Kind::File; + } + + /// \brief Is this node part of resolution ? + virtual bool isHidden() const { return true; } + + /// \brief Validate the options + virtual bool validate() { + (void)_elfLinkingContext; + return true; + } + + /// \brief Dump the Linker script. + virtual bool dump(raw_ostream &) { return true; } + + /// \brief Parse the linker script. + virtual error_code parse(const LinkingContext &, raw_ostream &); + +protected: + ELFLinkingContext &_elfLinkingContext; + std::unique_ptr _parser; + std::unique_ptr _lexer; + script::LinkerScript *_linkerScript; +}; + +/// \brief Handle ELF style with GNU Linker scripts. +class ELFGNULdScript : public GNULdScript { +public: + ELFGNULdScript(ELFLinkingContext &ctx, StringRef userPath, int64_t ordinal) + : GNULdScript(ctx, userPath, ordinal) {} + + virtual error_code parse(const LinkingContext &ctx, raw_ostream &diagnostics); + + virtual ExpandType expandType() const { + return InputElement::ExpandType::ExpandOnly; + } + + /// Unused functions for ELFGNULdScript Nodes. + virtual ErrorOr getNextFile() { + return make_error_code(InputGraphError::no_more_files); + } + + /// Return the elements that we would want to expand with. + range expandElements() { + return make_range(_expandElements.begin(), _expandElements.end()); + } + + virtual void setResolveState(uint32_t) {} + + virtual uint32_t getResolveState() const { + llvm_unreachable("cannot use this function: getResolveState"); + } + + // Do nothing here. + virtual void resetNextIndex() {} + +private: + InputGraph::InputElementVectorT _expandElements; +}; + /// \brief Represents a ELF control node class ELFGroup : public Group { public: Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -22,11 +22,13 @@ #include "llvm/Object/ELF.h" #include "llvm/Support/ELF.h" +#include #include namespace lld { class DefinedAtom; class Reference; +class SharedLibraryFile; namespace elf { template class TargetHandler; @@ -116,8 +118,6 @@ virtual Reader &getDefaultReader() const { return *_elfReader; } - virtual Reader &getLinkerScriptReader() const { return *_linkerScriptReader; } - /// \brief Does the output have dynamic sections. virtual bool isDynamic() const; @@ -206,6 +206,20 @@ return _rpathLinkList; } + StringRef allocateString(StringRef ref) const { + char *x = _allocator.Allocate(ref.size() + 1); + memcpy(x, ref.data(), ref.size()); + x[ref.size()] = '\0'; + return x; + } + + virtual bool addUndefinedAtomsFromSharedLibrary(const SharedLibraryFile *s) { + if (_undefinedAtomsFromFile.find(s) != _undefinedAtomsFromFile.end()) + return false; + _undefinedAtomsFromFile[s] = true; + return true; + } + private: ELFLinkingContext() LLVM_DELETED_FUNCTION; @@ -232,7 +246,6 @@ StringRefVector _inputSearchPaths; std::unique_ptr _elfReader; std::unique_ptr _writer; - std::unique_ptr _linkerScriptReader; StringRef _dynamicLinkerPath; StringRefVector _initFunctions; StringRefVector _finiFunctions; @@ -240,6 +253,7 @@ StringRef _soname; StringRefVector _rpathList; StringRefVector _rpathLinkList; + std::map _undefinedAtomsFromFile; }; } // end namespace lld Index: include/lld/ReaderWriter/ReaderLinkerScript.h =================================================================== --- include/lld/ReaderWriter/ReaderLinkerScript.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- lld/ReaderWriter/ReaderLinkerScript.h ------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READER_WRITER_READER_LINKER_SCRIPT_H -#define LLD_READER_WRITER_READER_LINKER_SCRIPT_H - -#include "lld/Core/LLVM.h" -#include "lld/ReaderWriter/Reader.h" - -namespace lld { -class File; -class LinkingContext; - -/// \brief ReaderLinkerScript is a class for reading linker scripts -class ReaderLinkerScript : public Reader { -public: - explicit ReaderLinkerScript(const LinkingContext &context) - : Reader(context) {} - - /// \brief Returns a vector of Files that are contained in the archive file - /// pointed to by the Memorybuffer - error_code parseFile(std::unique_ptr &mb, - std::vector > &result) const; -}; - -} // end namespace lld - -#endif Index: lib/Core/Error.cpp =================================================================== --- lib/Core/Error.cpp +++ lib/Core/Error.cpp @@ -127,3 +127,29 @@ static _InputGraphErrorCategory i; return i; } + +class _ReaderErrorCategory : public llvm::_do_message { +public: + virtual const char *name() const { return "lld.inputGraph.parse"; } + + virtual std::string message(int ev) const { + if (ReaderError(ev) == ReaderError::success) + return "Success"; + else if (ReaderError(ev) == ReaderError::unknown_file_format) + return "File format for the input file is not recognized by this flavor"; + + llvm_unreachable("An enumerator of ReaderError does not have a " + "message defined."); + } + + virtual llvm::error_condition default_error_condition(int ev) const { + if (ReaderError(ev) == ReaderError::success) + return llvm::errc::success; + return llvm::errc::invalid_argument; + } +}; + +const llvm::error_category &lld::ReaderErrorCategory() { + static _ReaderErrorCategory i; + return i; +} Index: lib/Core/InputGraph.cpp =================================================================== --- lib/Core/InputGraph.cpp +++ lib/Core/InputGraph.cpp @@ -35,6 +35,37 @@ std::stable_sort(_inputArgs.begin(), _inputArgs.end(), sortInputElements); } +void InputGraph::normalize() { + auto iterb = _inputArgs.begin(); + auto itere = _inputArgs.end(); + auto currentIter = _inputArgs.begin(); + bool replaceCurrentNode = false; + bool expand = false; + + std::vector > _workInputArgs; + while (iterb != itere) { + replaceCurrentNode = false; + expand = false; + InputElement::ExpandType expandType = (*iterb)->expandType(); + if (expandType == InputElement::ExpandType::ReplaceAndExpand) { + replaceCurrentNode = true; + expand = true; + } else if (expandType == InputElement::ExpandType::ExpandOnly) { + replaceCurrentNode = false; + expand = true; + } + currentIter = iterb++; + if (expand) + _workInputArgs.insert( + _workInputArgs.end(), + std::make_move_iterator((*currentIter)->expandElements().begin()), + std::make_move_iterator((*currentIter)->expandElements().end())); + if (!replaceCurrentNode) + _workInputArgs.push_back(std::move(*currentIter)); + } + _inputArgs = std::move(_workInputArgs); +} + bool InputGraph::validate() { for (auto &ie : _inputArgs) if (!ie->validate()) @@ -75,7 +106,11 @@ ErrorOr InputGraph::getNextInputElement() { if (_nextElementIndex >= _inputArgs.size()) return make_error_code(InputGraphError::no_more_elements); - return _inputArgs[_nextElementIndex++].get(); + auto elem = _inputArgs[_nextElementIndex++].get(); + // Do not return Hidden elements. + if (!elem->isHidden()) + return elem; + return getNextInputElement(); } /// \brief Set the index on what inputElement has to be returned Index: lib/Core/Resolver.cpp =================================================================== --- lib/Core/Resolver.cpp +++ lib/Core/Resolver.cpp @@ -75,14 +75,19 @@ void Resolver::handleFile(const File &file) { uint32_t resolverState = Resolver::StateNoChange; + const SharedLibraryFile *sharedLibraryFile = + llvm::dyn_cast(&file); doFile(file); for (const DefinedAtom *atom : file.defined()) { doDefinedAtom(*atom); resolverState |= StateNewDefinedAtoms; } - for (const UndefinedAtom *undefAtom : file.undefined()) { - doUndefinedAtom(*undefAtom); - resolverState |= StateNewUndefinedAtoms; + if (!sharedLibraryFile || + _context.addUndefinedAtomsFromSharedLibrary(sharedLibraryFile)) { + for (const UndefinedAtom *undefAtom : file.undefined()) { + doUndefinedAtom(*undefAtom); + resolverState |= StateNewUndefinedAtoms; + } } for (const SharedLibraryAtom *shlibAtom : file.sharedLibrary()) { doSharedLibraryAtom(*shlibAtom); @@ -290,8 +295,6 @@ file->setOrdinal(_context.getNextOrdinalAndIncrement()); handleSharedLibrary(*file); break; - case File::kindLinkerScript: - llvm_unreachable("linker script should not be returned by nextFile()"); } } } Index: lib/Driver/CMakeLists.txt =================================================================== --- lib/Driver/CMakeLists.txt +++ lib/Driver/CMakeLists.txt @@ -15,6 +15,7 @@ DarwinLdDriver.cpp Driver.cpp GnuLdDriver.cpp + GnuLdInputGraph.cpp WinLinkDriver.cpp UniversalDriver.cpp ) Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -54,6 +54,8 @@ TaskGroup tg; std::mutex diagnosticsMutex; for (auto &ie : inputGraph.inputElements()) { + if (ie->isHidden()) + continue; tg.spawn([&] { // Writes to the same output stream is not guaranteed to be thread-safe. // We buffer the diagnostics output to a separate string-backed output Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -67,6 +67,25 @@ GnuLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){} }; +// Get the Input file magic for creating appropriate InputGraph nodes. +error_code getFileMagic(ELFLinkingContext &ctx, StringRef path, + std::vector &searchPaths, + llvm::sys::fs::file_magic &magic) { + error_code ec = llvm::sys::fs::identify_magic(path, magic); + if (ec) + return ec; + switch (magic) { + case llvm::sys::fs::file_magic::archive: + case llvm::sys::fs::file_magic::elf_relocatable: + case llvm::sys::fs::file_magic::elf_shared_object: + case llvm::sys::fs::file_magic::unknown: + return error_code::success(); + default: + break; + } + return make_error_code(ReaderError::unknown_file_format); +} + } // namespace llvm::ErrorOr ELFFileNode::getPath(const LinkingContext &) const { @@ -268,9 +287,45 @@ case OPT_INPUT: case OPT_l: { - std::unique_ptr inputFile(new ELFFileNode( - *ctx, inputArg->getValue(), searchPath, index++, isWholeArchive, - asNeeded, inputArg->getOption().getID() == OPT_l)); + bool isDashlPrefix = (inputArg->getOption().getID() == OPT_l); + bool isELFFileNode = true; + StringRef userPath = inputArg->getValue(); + std::string resolvedInputPath = userPath; + if (isDashlPrefix) { + ErrorOr resolvedPath = + ctx->searchLibrary(userPath, searchPath); + if (!resolvedPath) { + diagnostics << " Unable to find library -l" << userPath << "\n"; + return false; + } + resolvedInputPath = resolvedPath->str(); + } + llvm::sys::fs::file_magic magic = llvm::sys::fs::file_magic::unknown; + error_code ec = getFileMagic(*ctx, resolvedInputPath, searchPath, magic); + if (ec) { + diagnostics << "lld: unknown input file format for file " << userPath + << "\n"; + return false; + } + if ((!userPath.endswith(".objtxt")) && + (magic == llvm::sys::fs::file_magic::unknown)) + isELFFileNode = false; + + FileNode *inputNode = nullptr; + if (isELFFileNode) + inputNode = new ELFFileNode(*ctx, userPath, searchPath, index++, + isWholeArchive, asNeeded, isDashlPrefix); + else { + inputNode = new ELFGNULdScript(*ctx, resolvedInputPath, index++); + ec = inputNode->parse(*ctx, diagnostics); + if (ec) { + diagnostics << userPath << ": Error parsing linker script" + << "\n"; + return false; + } + } + + std::unique_ptr inputFile(inputNode); if (controlNodeStack.empty()) inputGraph->addInputElement(std::move(inputFile)); else @@ -336,6 +391,8 @@ if (!ctx->validate(diagnostics)) return false; + inputGraph->normalize(); + ctx->setInputGraph(std::move(inputGraph)); context.swap(ctx); Index: lib/Driver/GnuLdInputGraph.cpp =================================================================== --- /dev/null +++ lib/Driver/GnuLdInputGraph.cpp @@ -0,0 +1,108 @@ +//===- lib/Driver/GnuLdInputGraph.cpp -------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Driver/GnuLdInputGraph.h" +#include "lld/ReaderWriter/LinkerScript.h" + +using namespace lld; + +/// \brief Parse the input file to lld::File. +error_code ELFFileNode::parse(const LinkingContext &ctx, + raw_ostream &diagnostics) { + ErrorOr filePath = getPath(ctx); + if (!filePath) + return error_code(filePath); + + if (error_code ec = getBuffer(*filePath)) + return ec; + + if (ctx.logInputFiles()) + diagnostics << *filePath << "\n"; + + if (filePath->endswith(".objtxt")) + return ctx.getYAMLReader().parseFile(_buffer, _files); + + // Identify File type + llvm::sys::fs::file_magic FileType = + llvm::sys::fs::identify_magic(_buffer->getBuffer()); + + switch (FileType) { + case llvm::sys::fs::file_magic::elf_relocatable: + case llvm::sys::fs::file_magic::elf_shared_object: + // Call the default reader to read object files and shared objects + return _elfLinkingContext.getDefaultReader().parseFile(_buffer, _files); + + case llvm::sys::fs::file_magic::archive: { + // Process archive files. If Whole Archive option is set, + // parse all members of the archive. + error_code ec; + std::unique_ptr fileArchive( + new FileArchive(ctx, std::move(_buffer), ec, _isWholeArchive)); + if (_isWholeArchive) { + fileArchive->parseAllMembers(_files); + _archiveFile = std::move(fileArchive); + } else { + _files.push_back(std::move(fileArchive)); + } + return ec; + } + default: + break; + } + + return error_code::success(); +} + +error_code GNULdScript::parse(const LinkingContext &ctx, + raw_ostream &diagnostics) { + ErrorOr filePath = getPath(ctx); + if (!filePath) + return error_code(filePath); + + if (error_code ec = getBuffer(*filePath)) + return ec; + + if (ctx.logInputFiles()) + diagnostics << *filePath << "\n"; + + _lexer.reset(new script::Lexer(std::move(_buffer))); + _parser.reset(new script::Parser(*_lexer.get())); + + _linkerScript = _parser->parse(); + + if (!_linkerScript) + return LinkerScriptReaderError::parse_error; + + return error_code::success(); +} + +error_code ELFGNULdScript::parse(const LinkingContext &ctx, + raw_ostream &diagnostics) { + int64_t index = 0; + std::vector searchPath; + if (error_code ec = GNULdScript::parse(ctx, diagnostics)) + return ec; + for (const auto &c : _linkerScript->_commands) { + if (auto group = dyn_cast(c)) { + std::unique_ptr controlStart( + new ELFGroup(_elfLinkingContext, index++)); + for (auto &path : group->getPaths()) { + // TODO : Propagate SearchPath, Set WholeArchive/dashlPrefix + auto inputNode = new ELFFileNode( + _elfLinkingContext, _elfLinkingContext.allocateString(path._path), + searchPath, index++, false, path._asNeeded, false); + std::unique_ptr inputFile(inputNode); + dyn_cast(controlStart.get()) + ->processInputElement(std::move(inputFile)); + } + _expandElements.push_back(std::move(controlStart)); + } + } + return error_code::success(); +} Index: lib/ReaderWriter/CMakeLists.txt =================================================================== --- lib/ReaderWriter/CMakeLists.txt +++ lib/ReaderWriter/CMakeLists.txt @@ -9,7 +9,6 @@ CoreLinkingContext.cpp LinkerScript.cpp Reader.cpp - ReaderLinkerScript.cpp Writer.cpp ) Index: lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -18,7 +18,6 @@ #include "lld/Passes/LayoutPass.h" #include "lld/Passes/RoundTripNativePass.h" #include "lld/Passes/RoundTripYAMLPass.h" -#include "lld/ReaderWriter/ReaderLinkerScript.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ELF.h" @@ -83,7 +82,6 @@ bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) { _elfReader = createReaderELF(*this); - _linkerScriptReader.reset(new ReaderLinkerScript(*this)); switch (outputFileType()) { case LinkingContext::OutputFileType::YAML: _writer = createWriterYAML(*this); Index: lib/ReaderWriter/ReaderLinkerScript.cpp =================================================================== --- lib/ReaderWriter/ReaderLinkerScript.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//===- lib/ReaderWriter/ReaderLinkerScript.cpp ----------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/ReaderWriter/ReaderLinkerScript.h" - -#include "lld/Core/Error.h" -#include "lld/Core/File.h" -#include "lld/ReaderWriter/LinkerScript.h" - -using namespace lld; -using namespace script; - -namespace { -class LinkerScriptFile : public File { -public: - static ErrorOr > - create(const LinkingContext &context, - std::unique_ptr mb) { - std::unique_ptr file( - new LinkerScriptFile(context, std::move(mb))); - file->_script = file->_parser.parse(); - if (!file->_script) - return LinkerScriptReaderError::parse_error; - return std::move(file); - } - - static inline bool classof(const File *f) { - return f->kind() == kindLinkerScript; - } - - virtual const LinkingContext &getLinkingContext() const { return _context; } - - virtual const atom_collection &defined() const { - return _definedAtoms; - } - - virtual const atom_collection &undefined() const { - return _undefinedAtoms; - } - - virtual const atom_collection &sharedLibrary() const { - return _sharedLibraryAtoms; - } - - virtual const atom_collection &absolute() const { - return _absoluteAtoms; - } - - const LinkerScript *getScript() { return _script; } - -private: - LinkerScriptFile(const LinkingContext &context, - std::unique_ptr mb) - : File(mb->getBufferIdentifier(), kindLinkerScript), _context(context), - _lexer(std::move(mb)), _parser(_lexer), _script(nullptr) {} - - const LinkingContext &_context; - atom_collection_vector _definedAtoms; - atom_collection_vector _undefinedAtoms; - atom_collection_vector _sharedLibraryAtoms; - atom_collection_vector _absoluteAtoms; - Lexer _lexer; - Parser _parser; - const LinkerScript *_script; -}; -} // end anon namespace - -namespace lld { -error_code ReaderLinkerScript::parseFile( - std::unique_ptr &mb, - std::vector > &result) const { - auto lsf = LinkerScriptFile::create(_context, std::move(mb)); - if (!lsf) - return lsf; - const LinkerScript *ls = (*lsf)->getScript(); - result.push_back(std::move(*lsf)); - for (const auto &c : ls->_commands) { - if (auto group = dyn_cast(c)) - for (const auto &path : group->getPaths()) { - OwningPtr opmb; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(path._path, opmb)) - return ec; - std::unique_ptr eachMB(opmb.take()); - if (error_code ec = - _context.getDefaultReader().parseFile(eachMB, result)) - return ec; - } - } - return error_code::success(); -} -} // end namespace lld Index: unittests/DriverTests/GnuLdDriverTest.cpp =================================================================== --- unittests/DriverTests/GnuLdDriverTest.cpp +++ unittests/DriverTests/GnuLdDriverTest.cpp @@ -32,25 +32,4 @@ EXPECT_EQ(linkingContext(), nullptr); EXPECT_EQ("No input files\n", errorMessage()); } - -TEST_F(GnuLdParserTest, Basic) { - EXPECT_TRUE(parse("ld", "infile.o", nullptr)); - EXPECT_NE(linkingContext(), nullptr); - EXPECT_EQ("a.out", linkingContext()->outputPath()); - EXPECT_EQ(1, inputFileCount()); - EXPECT_EQ("infile.o", inputFile(0)); - EXPECT_FALSE(_context->outputFileType() == - LinkingContext::OutputFileType::YAML); -} - -TEST_F(GnuLdParserTest, ManyOptions) { - EXPECT_TRUE(parse("ld", "-entry", "_start", "-o", "outfile", - "--output-filetype=yaml", "infile.o", nullptr)); - EXPECT_NE(linkingContext(), nullptr); - EXPECT_EQ("outfile", linkingContext()->outputPath()); - EXPECT_EQ("_start", linkingContext()->entrySymbolName()); - EXPECT_TRUE(_context->outputFileType() == - LinkingContext::OutputFileType::YAML); -} - } // end anonymous namespace