[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
This commit is contained in:
Shankar Easwaran 2013-08-31 05:27:38 +00:00
parent 2c4f8b7ee8
commit d26c8e3463
27 changed files with 279 additions and 188 deletions

View File

@ -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.

View File

@ -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 =

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -289,6 +289,8 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
return true;
}
inputGraph->addInternalFile(ctx->createInternalFiles());
if (ctx->outputYAML())
inputGraph->dump(diagnostics);

View File

@ -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".

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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() {

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {