diff options
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) { |