diff options
author | Shankar Easwaran <shankare@codeaurora.org> | 2013-08-31 05:27:38 +0000 |
---|---|---|
committer | Shankar Easwaran <shankare@codeaurora.org> | 2013-08-31 05:27:38 +0000 |
commit | d26c8e346344eec7d178b0cf5fe2fa30813c076e (patch) | |
tree | a5ffbb94f8c35f0bb9eeb760d1b75a515307bdab /lld | |
parent | 2c4f8b7ee87fb6f77688bee1dd00e10ae2707f00 (diff) | |
download | bcm5719-llvm-d26c8e346344eec7d178b0cf5fe2fa30813c076e.tar.gz bcm5719-llvm-d26c8e346344eec7d178b0cf5fe2fa30813c076e.zip |
[lld][LinkingContext] Atoms created from command line options should be available in YAML
This adds an API to the LinkingContext for flavors to add Internal files
containing atoms that need to appear in the YAML output as well, when -emit-yaml
switch is used.
Flavors can add more internal files for other options that are needed.
llvm-svn: 189718
Diffstat (limited to 'lld')
27 files changed, 279 insertions, 188 deletions
diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h index adff5ce15f6..5dccb3b1d79 100644 --- a/lld/include/lld/Core/LinkingContext.h +++ b/lld/include/lld/Core/LinkingContext.h @@ -53,7 +53,7 @@ public: /// Name of symbol linker should use as "entry point" to program, /// usually "main" or "start". - StringRef entrySymbolName() const { return _entrySymbolName; } + virtual StringRef entrySymbolName() const { return _entrySymbolName; } /// Whether core linking should remove Atoms not reachable by following /// References from the entry point Atom or from all global scope Atoms @@ -184,9 +184,7 @@ public: // Set the entry symbol name. You may also need to call addDeadStripRoot() for // the symbol if your platform supports dead-stripping, so that the symbol // will not be removed from the output. - void setEntrySymbolName(StringRef name) { - // Entry function have to be resolved as an undefined symbol. - addInitialUndefinedSymbol(name); + virtual void setEntrySymbolName(StringRef name) { _entrySymbolName = name; } @@ -234,6 +232,12 @@ public: typedef StringRefVector::iterator StringRefVectorIter; typedef StringRefVector::const_iterator StringRefVectorConstIter; + /// Create linker internal files containing atoms for the linker to include + /// during link. Flavors can override this function in their LinkingContext + /// to add more internal files. These internal files are positioned before + /// the actual input files. + virtual std::vector<std::unique_ptr<lld::File> > createInternalFiles(); + /// Return the list of undefined symbols that are specified in the /// linker command line, using the -u option. range<const StringRef *> initialUndefinedSymbols() const { @@ -320,6 +324,12 @@ protected: /// Abstract method to lazily instantiate the Writer. virtual Writer &writer() const = 0; + /// Method to create a internal file for the entry symbol + virtual std::unique_ptr<File> createEntrySymbolFile(); + + /// Method to create a internal file for an undefined symbol + virtual std::unique_ptr<File> createUndefinedSymbolFile(); + StringRef _outputPath; StringRef _entrySymbolName; bool _deadStrip; @@ -338,6 +348,7 @@ protected: std::unique_ptr<Reader> _yamlReader; StringRefVector _initialUndefinedSymbols; std::unique_ptr<InputGraph> _inputGraph; + llvm::BumpPtrAllocator _allocator; private: /// Validate the subclass bits. Only called by validate. diff --git a/lld/include/lld/Driver/InputGraph.h b/lld/include/lld/Driver/InputGraph.h index 9cfd1fb8da8..195a8250e2b 100644 --- a/lld/include/lld/Driver/InputGraph.h +++ b/lld/include/lld/Driver/InputGraph.h @@ -34,19 +34,18 @@ class LinkingContext; /// nodes in the input graph contains Input elements. The InputElements are /// either Input Files or Control Options. The Input Files represent each Input /// File to the linker and the control option specify what the linker needs -/// to do when it processes the option. Each InputElement that is part of the -/// Graph has also an Ordinal value associated with it. The ordinal value is -/// needed for components to figure out the relative position of the arguments -/// that appeared in the Command Line. One such example is adding the list of -/// dynamic dynamic libraries to the DT_NEEDED list with the ELF Flavor. The -/// InputElements also have a weight function that can be used to determine the -/// weight of the file, for statistical purposes. The InputGraph also would -/// contain a set of General options that are processed by the linker, which -/// control the output +/// to do when it processes the option. +/// Each InputElement that is part of the Graph has an Ordinal value +/// associated with it. The ordinal value is needed for the Writer to figure out +/// the relative position of the arguments that appeared in the Command Line. +/// InputElements have a weight function that can be used to determine the +/// weight of the file, for statistical purposes. class InputGraph { public: typedef std::vector<std::unique_ptr<InputElement> > InputElementVectorT; typedef InputElementVectorT::iterator InputElementIterT; + typedef std::vector<std::unique_ptr<File> > FileVectorT; + typedef FileVectorT::iterator FileIterT; /// \brief Initialize the inputgraph InputGraph() : _ordinal(0), _numElements(0), _numFiles(0) {} @@ -66,16 +65,27 @@ public: /// Total number of InputElements virtual int64_t numElements() const { return _numElements; } + /// Total number of Internal files + virtual int64_t numInternalFiles() const { return _internalFiles.size(); } + /// \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 /// at the desired position, the user can do that virtual void doPostProcess(); - /// \brief Iterators - InputElementIterT begin() { return _inputArgs.begin(); } + virtual void addInternalFile(std::vector<std::unique_ptr<File> > inputFiles) { + for (auto &ai : inputFiles) + _internalFiles.push_back(std::move(ai)); + } - InputElementIterT end() { return _inputArgs.end(); } + range<FileIterT> internalFiles() { + return make_range(_internalFiles.begin(), _internalFiles.end()); + } + + range<InputElementIterT> inputElements() { + return make_range(_inputArgs.begin(), _inputArgs.end()); + } /// \brief Validate the input graph virtual bool validate(); @@ -90,6 +100,8 @@ public: private: // Input arguments InputElementVectorT _inputArgs; + // Extra Input files + FileVectorT _internalFiles; // Ordinals int64_t _ordinal; // Total number of InputElements @@ -103,9 +115,9 @@ private: class InputElement { public: /// Each input element in the graph can be a File or a control - enum class Kind : uint8_t { - Control, // Represents a type associated with ControlNodes - File, // Represents a type associated with File Nodes + enum class Kind : uint8_t{ + Control, // Represents a type associated with ControlNodes + File // Represents a type associated with File Nodes }; /// \brief Initialize the Input Element, The ordinal value of an input Element @@ -147,9 +159,9 @@ class ControlNode : public InputElement { public: /// A control node could be of several types supported by InputGraph /// Future kinds of Control node could be added - enum class ControlKind : uint8_t { - Simple, // Represents a simple control node - Group // Represents a type associated with ControlNodes + enum class ControlKind : uint8_t{ + Simple, // Represents a simple control node + Group // Represents a type associated with ControlNodes }; ControlNode(ControlNode::ControlKind controlKind = diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index a7cd19d0435..4c67c04d097 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -10,9 +10,11 @@ #ifndef LLD_READER_WRITER_ELF_LINKER_CONTEXT_H #define LLD_READER_WRITER_ELF_LINKER_CONTEXT_H +#include "lld/Core/LinkingContext.h" #include "lld/Core/PassManager.h" #include "lld/Core/Pass.h" -#include "lld/Core/LinkingContext.h" +#include "lld/Core/range.h" + #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Writer.h" @@ -38,11 +40,11 @@ public: class ELFLinkingContext : public LinkingContext { public: enum class OutputMagic : uint8_t { - DEFAULT, // The default mode, no specific magic set - NMAGIC, // Disallow shared libraries and dont align sections - // PageAlign Data, Mark Text Segment/Data segment RW - OMAGIC // Disallow shared libraries and dont align sections, - // Mark Text Segment/Data segment RW + DEFAULT, // The default mode, no specific magic set + NMAGIC, // Disallow shared libraries and dont align sections + // PageAlign Data, Mark Text Segment/Data segment RW + OMAGIC // Disallow shared libraries and dont align sections, + // Mark Text Segment/Data segment RW }; llvm::Triple getTriple() const { return _triple; } virtual bool is64Bits() const; @@ -154,6 +156,9 @@ public: StringRef searchLibrary(StringRef libName, const std::vector<StringRef> &searchPath) const; + /// Get the entry symbol name + virtual StringRef entrySymbolName() const; + private: ELFLinkingContext() LLVM_DELETED_FUNCTION; @@ -162,6 +167,9 @@ protected: virtual Writer &writer() const; + /// Method to create a internal file for an undefined symbol + virtual std::unique_ptr<File> createUndefinedSymbolFile(); + uint16_t _outputFileType; // e.g ET_EXEC llvm::Triple _triple; std::unique_ptr<TargetHandlerBase> _targetHandler; diff --git a/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h b/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h index ab27327ecca..9acf547f1fa 100644 --- a/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h @@ -122,6 +122,13 @@ public: return false; } +protected: + /// Method to create a internal file for the entry symbol + virtual std::unique_ptr<File> createEntrySymbolFile(); + + /// Method to create a internal file for an undefined symbol + virtual std::unique_ptr<File> createUndefinedSymbolFile(); + private: // The start address for the program. The default value for the executable is // 0x400000, but can be altered using -base command line option. diff --git a/lld/lib/Core/LinkingContext.cpp b/lld/lib/Core/LinkingContext.cpp index 5d628aa7a07..e341a886eac 100644 --- a/lld/lib/Core/LinkingContext.cpp +++ b/lld/lib/Core/LinkingContext.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "lld/Core/LinkingContext.h" +#include "lld/Core/InputFiles.h" #include "lld/ReaderWriter/Writer.h" +#include "lld/ReaderWriter/Simple.h" #include "llvm/ADT/Triple.h" @@ -50,6 +52,39 @@ void LinkingContext::addImplicitFiles(InputFiles &inputs) const { this->writer().addFiles(inputs); } +std::unique_ptr<File> LinkingContext::createEntrySymbolFile() { + if (entrySymbolName().empty()) + return nullptr; + std::unique_ptr<SimpleFile> entryFile( + new SimpleFile(*this, "command line option -entry")); + entryFile->addAtom( + *(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName()))); + return std::move(entryFile); +} + +std::unique_ptr<File> LinkingContext::createUndefinedSymbolFile() { + if (_initialUndefinedSymbols.empty()) + return nullptr; + std::unique_ptr<SimpleFile> undefinedSymFile( + new SimpleFile(*this, "command line option -u")); + for (auto undefSymStr : _initialUndefinedSymbols) + undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom( + *undefinedSymFile, undefSymStr))); + return std::move(undefinedSymFile); +} + +std::vector<std::unique_ptr<File> > LinkingContext::createInternalFiles() { + std::vector<std::unique_ptr<File> > result; + std::unique_ptr<File> internalFile; + internalFile = createEntrySymbolFile(); + if (internalFile) + result.push_back(std::move(internalFile)); + internalFile = createUndefinedSymbolFile(); + if (internalFile) + result.push_back(std::move(internalFile)); + return result; +} + void LinkingContext::addPasses(PassManager &pm) const {} } // end namespace lld diff --git a/lld/lib/Driver/Driver.cpp b/lld/lib/Driver/Driver.cpp index ae20f84c973..fd2d6524c74 100644 --- a/lld/lib/Driver/Driver.cpp +++ b/lld/lib/Driver/Driver.cpp @@ -52,7 +52,7 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) { std::atomic<bool> fail(false); TaskGroup tg; std::vector<std::unique_ptr<LinkerInput> > linkerInputs; - for (auto &ie : inputGraph) { + for (auto &ie : inputGraph.inputElements()) { if (ie->kind() == InputElement::Kind::File) { FileNode *fileNode = (llvm::dyn_cast<FileNode>)(ie.get()); linkerInputs.push_back(std::move(fileNode->createLinkerInput(context))); @@ -79,6 +79,10 @@ bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) { return true; InputFiles inputs; + + for (auto &f : inputGraph.internalFiles()) + inputs.appendFile(*f.get()); + for (auto &f : files) inputs.appendFiles(f); diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index 7060da11747..2019fa757b5 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -289,6 +289,8 @@ bool GnuLdDriver::parse(int argc, const char *argv[], return true; } + inputGraph->addInternalFile(ctx->createInternalFiles()); + if (ctx->outputYAML()) inputGraph->dump(diagnostics); diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 27457e7239a..11251879f5b 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -471,6 +471,11 @@ bool WinLinkDriver::parse(int argc, const char *argv[], return true; } + // A list of undefined symbols will be added to the input + // file list to force the core linker to try to resolve + // the undefined symbols. + inputGraph.addInternalFile(ctx.createInternalFiles()); + // If /out option was not specified, the default output file name is // constructed by replacing an extension of the first input file // with ".exe". diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp index e19a4be573b..7e013705647 100644 --- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -9,6 +9,7 @@ #include "lld/ReaderWriter/ELFLinkingContext.h" +#include "File.h" #include "TargetHandler.h" #include "Targets.h" @@ -22,6 +23,17 @@ #include "llvm/Support/Path.h" namespace lld { + +class CommandLineUndefinedAtom : public SimpleUndefinedAtom { +public: + CommandLineUndefinedAtom(const File &f, StringRef name) + : SimpleUndefinedAtom(f, name) {} + + virtual CanBeNull canBeNull() const { + return CanBeNull::canBeNullAtBuildtime; + } +}; + ELFLinkingContext::ELFLinkingContext( llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler) : _outputFileType(elf::ET_EXEC), _triple(triple), @@ -29,8 +41,7 @@ ELFLinkingContext::ELFLinkingContext( _isStaticExecutable(false), _outputYAML(false), _noInhibitExec(false), _mergeCommonStrings(false), _runLayoutPass(true), _useShlibUndefines(false), _dynamicLinkerArg(false), - _noAllowDynamicLibraries(false), - _outputMagic(OutputMagic::DEFAULT) {} + _noAllowDynamicLibraries(false), _outputMagic(OutputMagic::DEFAULT) {} bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); } @@ -59,11 +70,13 @@ uint16_t ELFLinkingContext::getOutputMachine() const { } } -bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) { - if (_outputFileType == elf::ET_EXEC && _entrySymbolName.empty()) { - _entrySymbolName = "_start"; - } +StringRef ELFLinkingContext::entrySymbolName() const { + if (_outputFileType == elf::ET_EXEC && _entrySymbolName.empty()) + return "_start"; + return _entrySymbolName; +} +bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) { _elfReader = createReaderELF(*this); _linkerScriptReader.reset(new ReaderLinkerScript(*this)); _writer = _outputYAML ? createWriterYAML(*this) : createWriterELF(*this); @@ -157,4 +170,15 @@ StringRef ELFLinkingContext::searchLibrary( return libName; } +std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() { + if (_initialUndefinedSymbols.empty()) + return nullptr; + std::unique_ptr<SimpleFile> undefinedSymFile( + new SimpleFile(*this, "command line option -u")); + for (auto undefSymStr : _initialUndefinedSymbols) + undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom( + *undefinedSymFile, undefSymStr))); + return std::move(undefinedSymFile); +} + } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h deleted file mode 100644 index 14d9ab9c97e..00000000000 --- a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h +++ /dev/null @@ -1,95 +0,0 @@ -//===- lib/ReaderWriter/ELF/ExecutableAtoms.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_ELF_EXECUTABLE_ATOM_H -#define LLD_READER_WRITER_ELF_EXECUTABLE_ATOM_H - -#include "Atoms.h" -#include "File.h" - -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/File.h" -#include "lld/Core/Reference.h" -#include "lld/Core/UndefinedAtom.h" -#include "lld/ReaderWriter/Writer.h" - -namespace lld { -namespace elf { -/// \brief All atoms are owned by a File. To add linker specific atoms -/// the atoms need to be inserted to a file called (CRuntimeFile) which -/// are basically additional symbols required by libc and other runtime -/// libraries part of executing a program. This class provides support -/// for adding absolute symbols and undefined symbols -template <class ELFT> class CRuntimeFile : public ELFFile<ELFT> { -public: - typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; - CRuntimeFile(const ELFLinkingContext &context, StringRef name = "C runtime") - : ELFFile<ELFT>(context, name) {} - - /// \brief add a global absolute atom - virtual void addAbsoluteAtom(StringRef symbolName) { - Elf_Sym *symbol = new (_allocator.Allocate<Elf_Sym>()) Elf_Sym; - symbol->st_name = 0; - symbol->st_value = 0; - symbol->st_shndx = llvm::ELF::SHN_ABS; - symbol->setBindingAndType(llvm::ELF::STB_GLOBAL, - llvm::ELF::STT_OBJECT); - symbol->st_other = llvm::ELF::STV_DEFAULT; - symbol->st_size = 0; - auto *newAtom = - new (_allocator) ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, -1); - _absoluteAtoms._atoms.push_back(newAtom); - } - - /// \brief add an undefined atom - virtual void addUndefinedAtom(StringRef symbolName) { - assert(!symbolName.empty() && "UndefinedAtoms must have a name"); - Elf_Sym *symbol = new (_allocator) Elf_Sym; - symbol->st_name = 0; - symbol->st_value = 0; - symbol->st_shndx = llvm::ELF::SHN_UNDEF; - symbol->st_other = llvm::ELF::STV_DEFAULT; - symbol->st_size = 0; - auto *newAtom = - new (_allocator) ELFUndefinedAtom<ELFT>(*this, symbolName, symbol); - _undefinedAtoms._atoms.push_back(newAtom); - } - - virtual const File::atom_collection<DefinedAtom> &defined() const { - return _definedAtoms; - } - - virtual const File::atom_collection<UndefinedAtom> &undefined() const { - return _undefinedAtoms; - } - - virtual const File::atom_collection<SharedLibraryAtom> &sharedLibrary() const { - return _sharedLibraryAtoms; - } - - virtual const File::atom_collection<AbsoluteAtom> &absolute() const { - return _absoluteAtoms; - } - - // cannot add atoms to C Runtime file - virtual void addAtom(const Atom &) { - llvm_unreachable("cannot add atoms to Runtime files"); - } - -protected: - llvm::BumpPtrAllocator _allocator; - File::atom_collection_vector<DefinedAtom> _definedAtoms; - File::atom_collection_vector<UndefinedAtom> _undefinedAtoms; - File::atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; - File::atom_collection_vector<AbsoluteAtom> _absoluteAtoms; -}; -} // end namespace elf -} // end namespace lld - -#endif diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h index 33d925067b2..7e0a07691b2 100644 --- a/lld/lib/ReaderWriter/ELF/File.h +++ b/lld/lib/ReaderWriter/ELF/File.h @@ -737,6 +737,79 @@ private: /// \brief the cached options relevant while reading the ELF File bool _doStringsMerge : 1; }; + +/// \brief All atoms are owned by a File. To add linker specific atoms +/// the atoms need to be inserted to a file called (CRuntimeFile) which +/// are basically additional symbols required by libc and other runtime +/// libraries part of executing a program. This class provides support +/// for adding absolute symbols and undefined symbols +template <class ELFT> class CRuntimeFile : public ELFFile<ELFT> { +public: + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + CRuntimeFile(const ELFLinkingContext &context, StringRef name = "C runtime") + : ELFFile<ELFT>(context, name) {} + + /// \brief add a global absolute atom + virtual Atom *addAbsoluteAtom(StringRef symbolName) { + assert(!symbolName.empty() && "AbsoluteAtoms must have a name"); + Elf_Sym *symbol = new (_allocator) Elf_Sym; + symbol->st_name = 0; + symbol->st_value = 0; + symbol->st_shndx = llvm::ELF::SHN_ABS; + symbol->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_OBJECT); + symbol->st_other = llvm::ELF::STV_DEFAULT; + symbol->st_size = 0; + auto *newAtom = + new (_allocator) ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, -1); + _absoluteAtoms._atoms.push_back(newAtom); + return newAtom; + } + + /// \brief add an undefined atom + virtual Atom *addUndefinedAtom(StringRef symbolName) { + assert(!symbolName.empty() && "UndefinedAtoms must have a name"); + Elf_Sym *symbol = new (_allocator) Elf_Sym; + symbol->st_name = 0; + symbol->st_value = 0; + symbol->st_shndx = llvm::ELF::SHN_UNDEF; + symbol->st_other = llvm::ELF::STV_DEFAULT; + symbol->st_size = 0; + auto *newAtom = + new (_allocator) ELFUndefinedAtom<ELFT>(*this, symbolName, symbol); + _undefinedAtoms._atoms.push_back(newAtom); + return newAtom; + } + + virtual const File::atom_collection<DefinedAtom> &defined() const { + return _definedAtoms; + } + + virtual const File::atom_collection<UndefinedAtom> &undefined() const { + return _undefinedAtoms; + } + + virtual const File::atom_collection<SharedLibraryAtom> & + sharedLibrary() const { + return _sharedLibraryAtoms; + } + + virtual const File::atom_collection<AbsoluteAtom> &absolute() const { + return _absoluteAtoms; + } + + // cannot add atoms to C Runtime file + virtual void addAtom(const Atom &) { + llvm_unreachable("cannot add atoms to Runtime files"); + } + +protected: + llvm::BumpPtrAllocator _allocator; + File::atom_collection_vector<DefinedAtom> _definedAtoms; + File::atom_collection_vector<UndefinedAtom> _undefinedAtoms; + File::atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; + File::atom_collection_vector<AbsoluteAtom> _absoluteAtoms; +}; + } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h index 30996cc249b..e74d2a10f03 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h @@ -10,7 +10,7 @@ #ifndef LLD_READER_WRITER_ELF_HEXAGON_EXECUTABLE_ATOM_H #define LLD_READER_WRITER_ELF_HEXAGON_EXECUTABLE_ATOM_H -#include "ExecutableAtoms.h" +#include "File.h" namespace lld { namespace elf { diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h index 09e39f4fa02..df9582b9c87 100644 --- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h @@ -17,25 +17,15 @@ #include "llvm/ADT/StringSet.h" #include "DefaultLayout.h" +#include "File.h" #include "TargetLayout.h" -#include "ExecutableAtoms.h" namespace lld { namespace elf { using namespace llvm; using namespace llvm::object; -template<class ELFT> -class OutputELFWriter; - -/// \brief This acts as a internal file that the linker uses to add -/// undefined symbols that are defined by using the linker options such -/// as -u, or --defsym option. -template <class ELFT> class LinkerInternalFile : public CRuntimeFile<ELFT> { -public: - LinkerInternalFile(const ELFLinkingContext &context) - : CRuntimeFile<ELFT>(context, "Linker Internal File") {}; -}; +template <class ELFT> class OutputELFWriter; //===----------------------------------------------------------------------===// // OutputELFWriter Class @@ -123,7 +113,6 @@ protected: LLD_UNIQUE_BUMP_PTR(HashSection<ELFT>) _hashTable; llvm::StringSet<> _soNeeded; /// @} - LinkerInternalFile<ELFT> _linkerInternalFile; }; //===----------------------------------------------------------------------===// @@ -131,8 +120,7 @@ protected: //===----------------------------------------------------------------------===// template <class ELFT> OutputELFWriter<ELFT>::OutputELFWriter(const ELFLinkingContext &context) - : _context(context), _targetHandler(context.getTargetHandler<ELFT>()), - _linkerInternalFile(context) { + : _context(context), _targetHandler(context.getTargetHandler<ELFT>()) { _layout = &_targetHandler.targetLayout(); } @@ -238,12 +226,6 @@ template <class ELFT> void OutputELFWriter<ELFT>::addFiles(InputFiles &inputFiles) { // Add all input Files that are defined by the target _targetHandler.addFiles(inputFiles); - // Add all symbols that are specified by the -u option - // as part of the command line argument to lld - for (auto ai : _context.initialUndefinedSymbols()) - _linkerInternalFile.addUndefinedAtom(ai); - // Make the linker internal file to be the first file - inputFiles.prependFile(_linkerInternalFile); } template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() { diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h index 6730351d2d9..fa2026b1f47 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h @@ -19,6 +19,7 @@ namespace lld { namespace elf { + /// \brief x86-64 internal references. enum { /// \brief The 32 bit index of the relocation in the got this reference refers diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h index a10a9302cda..f05d9f52c5a 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -11,6 +11,7 @@ #define LLD_READER_WRITER_ELF_X86_64_TARGET_HANDLER_H #include "DefaultTargetHandler.h" +#include "File.h" #include "X86_64RelocationHandler.h" #include "TargetLayout.h" diff --git a/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h index 54d86036fd2..0cf680f352f 100644 --- a/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h +++ b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h @@ -111,23 +111,5 @@ private: MemberFile _memberFile; }; -/// An instance of UndefinedSymbolFile has a list of undefined symbols -/// specified by "/include" command line option. This will be added to the -/// input file list to force the core linker to try to resolve the undefined -/// symbols. -class UndefinedSymbolFile : public SimpleFile { -public: - UndefinedSymbolFile(const LinkingContext &ctx) - : SimpleFile(ctx, "Linker Internal File") { - for (StringRef symbol : ctx.initialUndefinedSymbols()) { - UndefinedAtom *atom = new (_alloc) coff::COFFUndefinedAtom(*this, symbol); - addAtom(*atom); - } - } - -private: - llvm::BumpPtrAllocator _alloc; -}; - } // end namespace coff } // end namespace lld diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp index 88440daf7a3..a5f830b8a8b 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp @@ -53,11 +53,28 @@ bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) { return false; } -void PECOFFLinkingContext::addImplicitFiles(InputFiles &files) const { - // Add a pseudo file for "/include" linker option. - auto *undefFile = new (_alloc) coff::UndefinedSymbolFile(*this); - files.prependFile(*undefFile); +std::unique_ptr<File> PECOFFLinkingContext::createEntrySymbolFile() { + if (entrySymbolName().empty()) + return nullptr; + std::unique_ptr<SimpleFile> entryFile( + new SimpleFile(*this, "command line option /entry")); + entryFile->addAtom( + *(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName()))); + return std::move(entryFile); +} +std::unique_ptr<File> PECOFFLinkingContext::createUndefinedSymbolFile() { + if (_initialUndefinedSymbols.empty()) + return nullptr; + std::unique_ptr<SimpleFile> undefinedSymFile( + new SimpleFile(*this, "command line option /c (or) /include")); + for (auto undefSymStr : _initialUndefinedSymbols) + undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom( + *undefinedSymFile, undefSymStr))); + return std::move(undefinedSymFile); +} + +void PECOFFLinkingContext::addImplicitFiles(InputFiles &files) const { auto *linkerFile = new (_alloc) coff::LinkerGeneratedSymbolFile(*this); files.appendFile(*linkerFile); } diff --git a/lld/test/Driver/libsearch-inputGraph.test b/lld/test/Driver/libsearch-inputGraph.test index 45510ffc2eb..14eed1bcb8f 100644 --- a/lld/test/Driver/libsearch-inputGraph.test +++ b/lld/test/Driver/libsearch-inputGraph.test @@ -1,8 +1,8 @@ -RUN: lld -flavor gnu -L%p/../elf/Inputs -lfnarchive -emit-yaml 2> %t.err +RUN: lld -flavor gnu -L%p/../elf/Inputs -lfnarchive -emit-yaml --noinhibit-exec 2> %t.err RUN: FileCheck %s < %t.err -RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive -lfnarchive -emit-yaml 2> %t1.err +RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive -lfnarchive -emit-yaml --noinhibit-exec 2> %t1.err RUN: FileCheck %s -check-prefix="WHOLEARCHIVE" < %t1.err -RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive --as-needed -lfnarchive -emit-yaml 2> %t2.err +RUN: lld -flavor gnu -L%p/../elf/Inputs --whole-archive --as-needed -lfnarchive -emit-yaml --noinhibit-exec 2> %t2.err RUN: FileCheck %s -check-prefix="ASNEEDED" < %t2.err CHECK: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a diff --git a/lld/test/elf/Hexagon/hexagon-plt-setup.test b/lld/test/elf/Hexagon/hexagon-plt-setup.test index 91989c618cb..1315ecb3933 100644 --- a/lld/test/elf/Hexagon/hexagon-plt-setup.test +++ b/lld/test/elf/Hexagon/hexagon-plt-setup.test @@ -1,5 +1,5 @@ RUN: lld -flavor gnu -target hexagon %p/Inputs/use-shared.hexagon \ -RUN: -emit-yaml -o %t2 +RUN: -emit-yaml --noinhibit-exec -o %t2 RUN: FileCheck %s < %t2 CHECK: - name: fn3 diff --git a/lld/test/elf/X86_64/largebss.test b/lld/test/elf/X86_64/largebss.test index dacb018320c..78687a8ac3f 100644 --- a/lld/test/elf/X86_64/largebss.test +++ b/lld/test/elf/X86_64/largebss.test @@ -3,7 +3,7 @@ # Any typeZeroFill content wouldnot have space reserved in the file to store # its content -RUN: lld -flavor gnu -target x86_64 %p/Inputs/largebss.o -emit-yaml | FileCheck %s +RUN: lld -flavor gnu -target x86_64 %p/Inputs/largebss.o -emit-yaml --noinhibit-exec | FileCheck %s CHECK: - name: largecommon diff --git a/lld/test/elf/branch.objtxt b/lld/test/elf/branch.objtxt index bddf3966359..6a2962cfcbd 100644 --- a/lld/test/elf/branch.objtxt +++ b/lld/test/elf/branch.objtxt @@ -1,5 +1,7 @@ -RUN: lld -flavor gnu -target hexagon -static -emit-yaml %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon | FileCheck %s -check-prefix hexagon-yaml -RUN: lld -flavor gnu -target hexagon -e target -o %t1 %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon +RUN: lld -flavor gnu -target hexagon -static -emit-yaml \ +RUN: %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon --noinhibit-exec | FileCheck %s -check-prefix hexagon-yaml +RUN: lld -flavor gnu -target hexagon -e target -o %t1 \ +RUN: %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon --noinhibit-exec RUN: llvm-readobj -h %t1 | FileCheck -check-prefix=hexagon-readobj %s hexagon-yaml: - name: back diff --git a/lld/test/elf/mergeconstants.objtxt b/lld/test/elf/mergeconstants.objtxt index 94a4b5cb26c..abe132fc13b 100644 --- a/lld/test/elf/mergeconstants.objtxt +++ b/lld/test/elf/mergeconstants.objtxt @@ -1,5 +1,5 @@ # The test checks for mergeable strings that appear in the object file -RUN: lld -flavor gnu --merge-strings -emit-yaml %p/Inputs/constants-merge.x86-64 | FileCheck -check-prefix=mergeAtoms %s +RUN: lld -flavor gnu --merge-strings -emit-yaml %p/Inputs/constants-merge.x86-64 --noinhibit-exec | FileCheck -check-prefix=mergeAtoms %s mergeAtoms: - ref-name: [[CONSTANT:[-a-zA-Z0-9_]+]] mergeAtoms: type: constant diff --git a/lld/test/elf/mergeglobalatoms.test b/lld/test/elf/mergeglobalatoms.test index 7831b719cd5..ff3e18e8c18 100644 --- a/lld/test/elf/mergeglobalatoms.test +++ b/lld/test/elf/mergeglobalatoms.test @@ -1,7 +1,7 @@ # ELF files can have mergeable strings which are global!, treat them as global # defined atoms RUN: lld -flavor gnu -emit-yaml %p/Inputs/globalconst.o.x86-64 \ -RUN: | FileCheck -check-prefix=globalatoms %s +RUN: --noinhibit-exec | FileCheck -check-prefix=globalatoms %s globalatoms: - name: mystr globalatoms: scope: global diff --git a/lld/test/elf/quickdata.test b/lld/test/elf/quickdata.test index 5c670f5a089..3c90e77a364 100644 --- a/lld/test/elf/quickdata.test +++ b/lld/test/elf/quickdata.test @@ -1,5 +1,5 @@ RUN: lld -flavor gnu -target hexagon -emit-yaml %p/Inputs/quickdata-test.elf-hexagon \ -RUN: | FileCheck %s -check-prefix hexagon +RUN: --noinhibit-exec | FileCheck %s -check-prefix hexagon hexagon: - name: ac1 hexagon: scope: global diff --git a/lld/test/pecoff/include.test b/lld/test/pecoff/include.test index 39c319c62bc..b2e8be0d8bb 100644 --- a/lld/test/pecoff/include.test +++ b/lld/test/pecoff/include.test @@ -4,5 +4,5 @@ # RUN: /include:sym1 /include:sym2 -- %t.obj 2> %t1 # RUN: FileCheck %s < %t1 -CHECK: Undefined Symbol: Linker Internal File : sym1 -CHECK: Undefined Symbol: Linker Internal File : sym2 +CHECK: Undefined Symbol: command line option /c (or) /include : sym1 +CHECK: Undefined Symbol: command line option /c (or) /include : sym2 diff --git a/lld/test/undef-basic.objtxt b/lld/test/undef-basic.objtxt new file mode 100644 index 00000000000..e6a29421e70 --- /dev/null +++ b/lld/test/undef-basic.objtxt @@ -0,0 +1,22 @@ +# RUN: lld -flavor gnu -u undefinedsymbol -e entrysymbol %s -emit-yaml \ +# RUN: --noinhibit-exec | FileCheck %s + +# +# Test that we are able to add undefined atoms from the command line +# + +--- +absolute-atoms: + - name: putchar + value: 0xFFFF0040 + + - name: reset + value: 0xFFFF0080 + +... + + +# CHECK: undefined-atoms: +# CHECK: - name: entrysymbol +# CHECK: - name: undefinedsymbol +# CHECK: can-be-null: at-buildtime diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index cbe327c5448..6aa1e60e588 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -55,8 +55,6 @@ TEST_F(WinLinkParserTest, Basic) { EXPECT_TRUE(_context.isTerminalServerAware()); EXPECT_TRUE(_context.getDynamicBaseEnabled()); EXPECT_TRUE(_context.deadStrip()); - EXPECT_FALSE(_context.initialUndefinedSymbols().empty()); - EXPECT_EQ("_start", _context.initialUndefinedSymbols()[0]); } TEST_F(WinLinkParserTest, UnixStyleOption) { |