summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Core/LinkingContext.h19
-rw-r--r--lld/include/lld/Driver/InputGraph.h48
-rw-r--r--lld/include/lld/ReaderWriter/ELFLinkingContext.h20
-rw-r--r--lld/include/lld/ReaderWriter/PECOFFLinkingContext.h7
-rw-r--r--lld/lib/Core/LinkingContext.cpp35
-rw-r--r--lld/lib/Driver/Driver.cpp6
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp2
-rw-r--r--lld/lib/Driver/WinLinkDriver.cpp5
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp36
-rw-r--r--lld/lib/ReaderWriter/ELF/ExecutableAtoms.h95
-rw-r--r--lld/lib/ReaderWriter/ELF/File.h73
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.h24
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h1
-rw-r--r--lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h18
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp25
-rw-r--r--lld/test/Driver/libsearch-inputGraph.test6
-rw-r--r--lld/test/elf/Hexagon/hexagon-plt-setup.test2
-rw-r--r--lld/test/elf/X86_64/largebss.test2
-rw-r--r--lld/test/elf/branch.objtxt6
-rw-r--r--lld/test/elf/mergeconstants.objtxt2
-rw-r--r--lld/test/elf/mergeglobalatoms.test2
-rw-r--r--lld/test/elf/quickdata.test2
-rw-r--r--lld/test/pecoff/include.test4
-rw-r--r--lld/test/undef-basic.objtxt22
-rw-r--r--lld/unittests/DriverTests/WinLinkDriverTest.cpp2
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) {
OpenPOWER on IntegriCloud