mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 21:53:12 +08:00
Rename TargetInfo -> LinkingContext.
Also change some local variable names: "ti" -> "context" and "_targetInfo" -> "_context". Differential Revision: http://llvm-reviews.chandlerc.com/D1301 llvm-svn: 187823
This commit is contained in:
@@ -49,7 +49,7 @@ Adding an Option to an existing Flavor
|
||||
|
||||
#. Add the option to the desired :file:`lib/Driver/{flavor}Options.td`.
|
||||
|
||||
#. Add to :cpp:class:`lld::FlavorTargetInfo` a getter and setter method
|
||||
#. Add to :cpp:class:`lld::FlavorLinkingContext` a getter and setter method
|
||||
for the option.
|
||||
|
||||
#. Modify :cpp:func:`lld::FlavorDriver::parse` in :file:
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
||||
///
|
||||
/// The ArchiveLibraryFile subclass of File is used to represent unix
|
||||
/// static library archives. These libraries provide no atoms to the
|
||||
@@ -34,15 +33,14 @@ public:
|
||||
/// specified name and return the File object for that member, or nullptr.
|
||||
virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
protected:
|
||||
/// only subclasses of ArchiveLibraryFile can be instantiated
|
||||
ArchiveLibraryFile(const TargetInfo &ti, StringRef path)
|
||||
: File(path, kindArchiveLibrary), _targetInfo(ti) {
|
||||
}
|
||||
ArchiveLibraryFile(const LinkingContext &context, StringRef path)
|
||||
: File(path, kindArchiveLibrary), _context(context) {}
|
||||
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/range.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
/// all AbsoluteAtoms in this File.
|
||||
virtual const atom_collection<AbsoluteAtom> &absolute() const = 0;
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const = 0;
|
||||
virtual const LinkingContext &getLinkingContext() const = 0;
|
||||
|
||||
protected:
|
||||
/// \brief only subclasses of File can be instantiated
|
||||
@@ -233,15 +233,15 @@ public:
|
||||
typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
|
||||
virtual DefinedAtomRange definedAtoms() = 0;
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
protected:
|
||||
/// \brief only subclasses of MutableFile can be instantiated
|
||||
MutableFile(const TargetInfo &ti, StringRef p)
|
||||
: File(p, kindObject), _targetInfo(ti) {}
|
||||
MutableFile(const LinkingContext &ti, StringRef p)
|
||||
: File(p, kindObject), _context(ti) {}
|
||||
|
||||
private:
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
} // end namespace lld
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lld/Core/TargetInfo.h - Linker Target Info Interface ---------------===//
|
||||
//===- lld/Core/LinkingContext.h - Linker Target Info Interface -----------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
class Triple;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
@@ -34,33 +34,29 @@ class File;
|
||||
class Writer;
|
||||
class InputFiles;
|
||||
|
||||
/// \brief The TargetInfo class encapsulates "what and how" to link.
|
||||
/// \brief The LinkingContext class encapsulates "what and how" to link.
|
||||
///
|
||||
/// The base class TargetInfo contains the options needed by core linking.
|
||||
/// Subclasses of TargetInfo have additional options needed by specific Readers
|
||||
/// and Writers. For example, ELFTargetInfo has methods that supplies options
|
||||
/// The base class LinkingContext contains the options needed by core linking.
|
||||
/// Subclasses of LinkingContext have additional options needed by specific
|
||||
/// Readers
|
||||
/// and Writers. For example, ELFLinkingContext has methods that supplies
|
||||
/// options
|
||||
/// to the ELF Reader and Writer.
|
||||
///
|
||||
/// \todo Consider renaming to something like "LinkingOptions".
|
||||
class TargetInfo : public Reader {
|
||||
class LinkingContext : public Reader {
|
||||
public:
|
||||
virtual ~TargetInfo();
|
||||
virtual ~LinkingContext();
|
||||
|
||||
/// \name Methods needed by core linking
|
||||
/// @{
|
||||
|
||||
/// Name of symbol linker should use as "entry point" to program,
|
||||
/// usually "main" or "start".
|
||||
StringRef entrySymbolName() const {
|
||||
return _entrySymbolName;
|
||||
}
|
||||
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
|
||||
/// if globalsAreDeadStripRoots() is true.
|
||||
bool deadStrip() const {
|
||||
return _deadStrip;
|
||||
}
|
||||
bool deadStrip() const { return _deadStrip; }
|
||||
|
||||
/// Only used if deadStrip() returns true. Means all global scope Atoms
|
||||
/// should be marked live (along with all Atoms they reference). Usually
|
||||
@@ -84,9 +80,7 @@ public:
|
||||
/// object file contains a DefinedAtom which will replace an existing
|
||||
/// UndefinedAtom. If this method returns true, core linking will actively
|
||||
/// load every member object file from every archive.
|
||||
bool forceLoadAllArchives() const {
|
||||
return _forceLoadAllArchives;
|
||||
}
|
||||
bool forceLoadAllArchives() const { return _forceLoadAllArchives; }
|
||||
|
||||
/// Archive files (aka static libraries) are normally lazily loaded. That is,
|
||||
/// object files within an archive are only loaded and linked in, if the
|
||||
@@ -117,16 +111,12 @@ public:
|
||||
/// \todo This should be a method core linking calls with a list of the
|
||||
/// UndefinedAtoms so that different drivers can format the error message
|
||||
/// as needed.
|
||||
bool printRemainingUndefines() const {
|
||||
return _printRemainingUndefines;
|
||||
}
|
||||
bool printRemainingUndefines() const { return _printRemainingUndefines; }
|
||||
|
||||
/// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
|
||||
/// SharedLibraryAtom for the link to be successful. This method controls
|
||||
/// whether core linking considers remaining undefines to be an error.
|
||||
bool allowRemainingUndefines() const {
|
||||
return _allowRemainingUndefines;
|
||||
}
|
||||
bool allowRemainingUndefines() const { return _allowRemainingUndefines; }
|
||||
|
||||
/// In the lld model, a SharedLibraryAtom is a proxy atom for something
|
||||
/// that will be found in a dynamic shared library when the program runs.
|
||||
@@ -161,9 +151,7 @@ public:
|
||||
/// SharedLibraryAtom for the link to be successful. This method controls
|
||||
/// whether core linking considers remaining undefines from the shared library
|
||||
/// to be an error.
|
||||
bool allowShlibUndefines() const {
|
||||
return _allowShlibUndefines;
|
||||
}
|
||||
bool allowShlibUndefines() const { return _allowShlibUndefines; }
|
||||
|
||||
/// If true, core linking will write the path to each input file to stdout
|
||||
/// (i.e. llvm::outs()) as it is used. This is used to implement the -t
|
||||
@@ -171,31 +159,21 @@ public:
|
||||
///
|
||||
/// \todo This should be a method core linking calls so that drivers can
|
||||
/// format the line as needed.
|
||||
bool logInputFiles() const {
|
||||
return _logInputFiles;
|
||||
}
|
||||
bool logInputFiles() const { return _logInputFiles; }
|
||||
|
||||
/// Parts of LLVM use global variables which are bound to command line
|
||||
/// options (see llvm::cl::Options). This method returns "command line"
|
||||
/// options which are used to configure LLVM's command line settings.
|
||||
/// For instance the -debug-only XXX option can be used to dynamically
|
||||
/// trace different parts of LLVM and lld.
|
||||
const std::vector<const char*> &llvmOptions() const {
|
||||
return _llvmOptions;
|
||||
}
|
||||
const std::vector<const char *> &llvmOptions() const { return _llvmOptions; }
|
||||
|
||||
/// This method returns the sequence of input files for core linking to
|
||||
/// process.
|
||||
///
|
||||
/// \todo Consider moving this out of TargetInfo so that the same TargetInfo
|
||||
/// object can be reused for different links.
|
||||
const std::vector<LinkerInput> &inputFiles() const {
|
||||
return _inputFiles;
|
||||
}
|
||||
const std::vector<LinkerInput> &inputFiles() const { return _inputFiles; }
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Methods used by Drivers to configure TargetInfo
|
||||
/// \name Methods used by Drivers to configure LinkingContext
|
||||
/// @{
|
||||
void setOutputPath(StringRef str) { _outputPath = str; }
|
||||
void setEntrySymbolName(StringRef name) { _entrySymbolName = name; }
|
||||
@@ -213,30 +191,22 @@ public:
|
||||
void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) {
|
||||
_warnIfCoalesableAtomsHaveDifferentLoadName = warn;
|
||||
}
|
||||
void setForceLoadAllArchives(bool force) {
|
||||
_forceLoadAllArchives = force;
|
||||
}
|
||||
void setForceLoadAllArchives(bool force) { _forceLoadAllArchives = force; }
|
||||
void setPrintRemainingUndefines(bool print) {
|
||||
_printRemainingUndefines = print;
|
||||
}
|
||||
void setAllowRemainingUndefines(bool allow) {
|
||||
_allowRemainingUndefines = allow;
|
||||
}
|
||||
void setAllowShlibUndefines(bool allow) {
|
||||
_allowShlibUndefines = allow;
|
||||
}
|
||||
void setLogInputFiles(bool log) {
|
||||
_logInputFiles = log;
|
||||
}
|
||||
void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; }
|
||||
void setLogInputFiles(bool log) { _logInputFiles = log; }
|
||||
void appendInputFile(StringRef path) {
|
||||
_inputFiles.emplace_back(LinkerInput(path));
|
||||
}
|
||||
void appendInputFile(std::unique_ptr<llvm::MemoryBuffer> buffer) {
|
||||
_inputFiles.emplace_back(LinkerInput(std::move(buffer)));
|
||||
}
|
||||
void appendLLVMOption(const char *opt) {
|
||||
_llvmOptions.push_back(opt);
|
||||
}
|
||||
void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); }
|
||||
|
||||
/// This method adds undefined symbols specified by the -u option to the
|
||||
/// to the list of undefined symbols known to the linker. This option
|
||||
@@ -264,7 +234,6 @@ public:
|
||||
/// \returns true if there is an error with the current settings.
|
||||
bool validate(raw_ostream &diagnostics);
|
||||
|
||||
|
||||
/// @}
|
||||
/// \name Methods used by Driver::link()
|
||||
/// @{
|
||||
@@ -273,12 +242,10 @@ public:
|
||||
///
|
||||
/// \todo To support in-memory linking, we need an abstraction that allows
|
||||
/// the linker to write to an in-memory buffer.
|
||||
StringRef outputPath() const {
|
||||
return _outputPath;
|
||||
}
|
||||
StringRef outputPath() const { return _outputPath; }
|
||||
|
||||
/// Abstract method to parse a supplied input file buffer into one or
|
||||
/// more lld::File objects. Subclasses of TargetInfo must implement this
|
||||
/// more lld::File objects. Subclasses of LinkingContext must implement this
|
||||
/// method.
|
||||
///
|
||||
/// \param inputBuff This is an in-memory read-only copy of the input file.
|
||||
@@ -290,8 +257,9 @@ public:
|
||||
/// \param [out] result The instantiated lld::File object is returned here.
|
||||
/// The \p result is a vector because some input files parse into more than
|
||||
/// one lld::File (e.g. YAML).
|
||||
virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &inputBuff,
|
||||
std::vector<std::unique_ptr<File>> &result) const = 0;
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &inputBuff,
|
||||
std::vector<std::unique_ptr<File> > &result) const = 0;
|
||||
|
||||
/// This is a wrapper around parseFile() where the input file is specified
|
||||
/// by file system path. The default implementation reads the input file
|
||||
@@ -299,13 +267,13 @@ public:
|
||||
///
|
||||
/// \param path This is the file system path to the input file.
|
||||
/// \param [out] result The instantiated lld::File object is returned here.
|
||||
virtual error_code readFile(StringRef path,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
virtual error_code
|
||||
readFile(StringRef path, std::vector<std::unique_ptr<File> > &result) const;
|
||||
|
||||
/// This method is called by core linking to give the Writer a chance
|
||||
/// to add file format specific "files" to set of files to be linked. This is
|
||||
/// how file format specific atoms can be added to the link.
|
||||
virtual void addImplicitFiles(InputFiles&) const;
|
||||
virtual void addImplicitFiles(InputFiles &) const;
|
||||
|
||||
/// This method is called by core linking to build the list of Passes to be
|
||||
/// run on the merged/linked graph of all input files.
|
||||
@@ -318,7 +286,6 @@ public:
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Methods needed by YAML I/O and error messages to convert Kind values
|
||||
/// to and from strings.
|
||||
/// @{
|
||||
@@ -333,35 +300,32 @@ public:
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
TargetInfo(); // Must be subclassed
|
||||
LinkingContext(); // Must be subclassed
|
||||
|
||||
/// Abstract method to lazily instantiate the Writer.
|
||||
virtual Writer &writer() const = 0;
|
||||
|
||||
|
||||
StringRef _outputPath;
|
||||
StringRef _entrySymbolName;
|
||||
bool _deadStrip;
|
||||
bool _globalsAreDeadStripRoots;
|
||||
bool _searchArchivesToOverrideTentativeDefinitions;
|
||||
bool _searchSharedLibrariesToOverrideTentativeDefinitions;
|
||||
bool _warnIfCoalesableAtomsHaveDifferentCanBeNull;
|
||||
bool _warnIfCoalesableAtomsHaveDifferentLoadName;
|
||||
bool _forceLoadAllArchives;
|
||||
bool _printRemainingUndefines;
|
||||
bool _allowRemainingUndefines;
|
||||
bool _logInputFiles;
|
||||
bool _allowShlibUndefines;
|
||||
std::vector<StringRef> _deadStripRoots;
|
||||
StringRef _outputPath;
|
||||
StringRef _entrySymbolName;
|
||||
bool _deadStrip;
|
||||
bool _globalsAreDeadStripRoots;
|
||||
bool _searchArchivesToOverrideTentativeDefinitions;
|
||||
bool _searchSharedLibrariesToOverrideTentativeDefinitions;
|
||||
bool _warnIfCoalesableAtomsHaveDifferentCanBeNull;
|
||||
bool _warnIfCoalesableAtomsHaveDifferentLoadName;
|
||||
bool _forceLoadAllArchives;
|
||||
bool _printRemainingUndefines;
|
||||
bool _allowRemainingUndefines;
|
||||
bool _logInputFiles;
|
||||
bool _allowShlibUndefines;
|
||||
std::vector<StringRef> _deadStripRoots;
|
||||
std::vector<LinkerInput> _inputFiles;
|
||||
std::vector<const char*> _llvmOptions;
|
||||
std::unique_ptr<Reader> _yamlReader;
|
||||
StringRefVector _initialUndefinedSymbols;
|
||||
std::vector<const char *> _llvmOptions;
|
||||
std::unique_ptr<Reader> _yamlReader;
|
||||
StringRefVector _initialUndefinedSymbols;
|
||||
|
||||
private:
|
||||
private:
|
||||
/// Validate the subclass bits. Only called by validate.
|
||||
virtual bool validateImpl(raw_ostream &diagnostics) = 0;
|
||||
};
|
||||
@@ -23,17 +23,16 @@
|
||||
namespace lld {
|
||||
|
||||
class Atom;
|
||||
class TargetInfo;
|
||||
class LinkingContext;
|
||||
|
||||
/// \brief The Resolver is responsible for merging all input object files
|
||||
/// and producing a merged graph.
|
||||
class Resolver : public InputFiles::Handler {
|
||||
public:
|
||||
Resolver(const TargetInfo &ti, const InputFiles &inputs)
|
||||
: _targetInfo(ti), _inputFiles(inputs), _symbolTable(ti), _result(ti),
|
||||
_haveLLVMObjs(false), _addToFinalSection(false),
|
||||
_completedInitialObjectFiles(false) {
|
||||
}
|
||||
Resolver(const LinkingContext &context, const InputFiles &inputs)
|
||||
: _context(context), _inputFiles(inputs), _symbolTable(context),
|
||||
_result(context), _haveLLVMObjs(false), _addToFinalSection(false),
|
||||
_completedInitialObjectFiles(false) {}
|
||||
|
||||
// InputFiles::Handler methods
|
||||
virtual void doDefinedAtom(const DefinedAtom&);
|
||||
@@ -66,7 +65,8 @@ private:
|
||||
|
||||
class MergedFile : public MutableFile {
|
||||
public:
|
||||
MergedFile(const TargetInfo &ti) : MutableFile(ti, "<linker-internal>") {}
|
||||
MergedFile(const LinkingContext &context)
|
||||
: MutableFile(context, "<linker-internal>") {}
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
return _definedAtoms;
|
||||
@@ -93,10 +93,9 @@ private:
|
||||
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
|
||||
};
|
||||
|
||||
|
||||
const TargetInfo &_targetInfo;
|
||||
const InputFiles &_inputFiles;
|
||||
SymbolTable _symbolTable;
|
||||
const LinkingContext &_context;
|
||||
const InputFiles &_inputFiles;
|
||||
SymbolTable _symbolTable;
|
||||
std::vector<const Atom *> _atoms;
|
||||
std::set<const Atom *> _deadStripRoots;
|
||||
std::vector<const Atom *> _atomsWithUnresolvedReferences;
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace lld {
|
||||
class AbsoluteAtom;
|
||||
class Atom;
|
||||
class DefinedAtom;
|
||||
class LinkingContext;
|
||||
class ResolverOptions;
|
||||
class SharedLibraryAtom;
|
||||
class TargetInfo;
|
||||
class UndefinedAtom;
|
||||
|
||||
/// \brief The SymbolTable class is responsible for coalescing atoms.
|
||||
@@ -37,7 +37,7 @@ class UndefinedAtom;
|
||||
/// if an atom has been coalesced away.
|
||||
class SymbolTable {
|
||||
public:
|
||||
explicit SymbolTable(const TargetInfo &);
|
||||
explicit SymbolTable(const LinkingContext &);
|
||||
|
||||
/// @brief add atom to symbol table
|
||||
void add(const DefinedAtom &);
|
||||
@@ -96,10 +96,10 @@ private:
|
||||
void addByName(const Atom &);
|
||||
void addByContent(const DefinedAtom &);
|
||||
|
||||
const TargetInfo &_targetInfo;
|
||||
AtomToAtom _replacedAtoms;
|
||||
NameToAtom _nameTable;
|
||||
AtomContentSet _contentTable;
|
||||
const LinkingContext &_context;
|
||||
AtomToAtom _replacedAtoms;
|
||||
NameToAtom _nameTable;
|
||||
AtomContentSet _contentTable;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// \file
|
||||
///
|
||||
/// Interface for Drivers which convert command line arguments into
|
||||
/// TargetInfo objects, then perform the link.
|
||||
/// LinkingContext objects, then perform the link.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -26,19 +26,20 @@
|
||||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
class TargetInfo;
|
||||
class CoreTargetInfo;
|
||||
class MachOTargetInfo;
|
||||
class PECOFFTargetInfo;
|
||||
class ELFTargetInfo;
|
||||
class LinkingContext;
|
||||
class CoreLinkingContext;
|
||||
class MachOLinkingContext;
|
||||
class PECOFFLinkingContext;
|
||||
class ELFLinkingContext;
|
||||
|
||||
/// Base class for all Drivers.
|
||||
class Driver {
|
||||
protected:
|
||||
|
||||
/// Performs link using specified options.
|
||||
static bool link(const TargetInfo &targetInfo,
|
||||
static bool link(const LinkingContext &context,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
Driver() LLVM_DELETED_FUNCTION;
|
||||
};
|
||||
@@ -68,7 +69,7 @@ public:
|
||||
/// Uses gnu/binutils style ld command line options to fill in options struct.
|
||||
/// Returns true iff there was an error.
|
||||
static bool parse(int argc, const char *argv[],
|
||||
std::unique_ptr<ELFTargetInfo> &targetInfo,
|
||||
std::unique_ptr<ELFLinkingContext> &context,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
@@ -86,10 +87,11 @@ public:
|
||||
static bool linkMachO(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
/// Uses darwin style ld command line options to update targetInfo object.
|
||||
/// Uses darwin style ld command line options to update LinkingContext object.
|
||||
/// Returns true iff there was an error.
|
||||
static bool parse(int argc, const char *argv[], MachOTargetInfo &info,
|
||||
static bool parse(int argc, const char *argv[], MachOLinkingContext &info,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
DarwinLdDriver() LLVM_DELETED_FUNCTION;
|
||||
};
|
||||
@@ -105,7 +107,7 @@ public:
|
||||
|
||||
/// Uses Windows style link command line options to fill in options struct.
|
||||
/// Returns true iff there was an error.
|
||||
static bool parse(int argc, const char *argv[], PECOFFTargetInfo &info,
|
||||
static bool parse(int argc, const char *argv[], PECOFFLinkingContext &info,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
@@ -124,7 +126,7 @@ public:
|
||||
|
||||
/// Uses lld-core command line options to fill in options struct.
|
||||
/// Returns true iff there was an error.
|
||||
static bool parse(int argc, const char *argv[], CoreTargetInfo &info,
|
||||
static bool parse(int argc, const char *argv[], CoreLinkingContext &info,
|
||||
raw_ostream &diagnostics = llvm::errs());
|
||||
|
||||
private:
|
||||
|
||||
47
lld/include/lld/ReaderWriter/CoreLinkingContext.h
Normal file
47
lld/include/lld/ReaderWriter/CoreLinkingContext.h
Normal file
@@ -0,0 +1,47 @@
|
||||
//===- lld/ReaderWriter/CoreLinkingContext.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_CORE_LINKER_CONTEXT_H
|
||||
#define LLD_READER_WRITER_CORE_LINKER_CONTEXT_H
|
||||
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
class CoreLinkingContext : public LinkingContext {
|
||||
public:
|
||||
CoreLinkingContext();
|
||||
|
||||
virtual bool validateImpl(raw_ostream &diagnostics);
|
||||
virtual void addPasses(PassManager &pm) const;
|
||||
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
|
||||
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
|
||||
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const;
|
||||
|
||||
void addPassNamed(StringRef name) { _passNames.push_back(name); }
|
||||
|
||||
protected:
|
||||
virtual Writer &writer() const;
|
||||
|
||||
private:
|
||||
mutable std::unique_ptr<Reader> _reader;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
std::vector<StringRef> _passNames;
|
||||
};
|
||||
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
//===- lld/ReaderWriter/CoreTargetInfo.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_CORE_TARGET_INFO_H
|
||||
#define LLD_READER_WRITER_CORE_TARGET_INFO_H
|
||||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
class CoreTargetInfo : public TargetInfo {
|
||||
public:
|
||||
CoreTargetInfo();
|
||||
|
||||
virtual bool validateImpl(raw_ostream &diagnostics);
|
||||
virtual void addPasses(PassManager &pm) const;
|
||||
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
|
||||
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
|
||||
|
||||
|
||||
virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
|
||||
void addPassNamed(StringRef name) {
|
||||
_passNames.push_back(name);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Writer &writer() const;
|
||||
|
||||
private:
|
||||
mutable std::unique_ptr<Reader> _reader;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
std::vector<StringRef> _passNames;
|
||||
};
|
||||
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lld/ReaderWriter/ELFTargetInfo.h -----------------------------------===//
|
||||
//===- lld/ReaderWriter/ELFLinkingContext.h -------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,12 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_TARGET_INFO_H
|
||||
#define LLD_READER_WRITER_ELF_TARGET_INFO_H
|
||||
#ifndef LLD_READER_WRITER_ELF_LINKER_CONTEXT_H
|
||||
#define LLD_READER_WRITER_ELF_LINKER_CONTEXT_H
|
||||
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
@@ -26,21 +26,23 @@ namespace lld {
|
||||
class DefinedAtom;
|
||||
class Reference;
|
||||
|
||||
namespace elf { template <typename ELFT> class TargetHandler; }
|
||||
namespace elf {
|
||||
template <typename ELFT> class TargetHandler;
|
||||
}
|
||||
|
||||
class TargetHandlerBase {
|
||||
public:
|
||||
virtual ~TargetHandlerBase() {}
|
||||
};
|
||||
|
||||
class ELFTargetInfo : public TargetInfo {
|
||||
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;
|
||||
@@ -77,16 +79,16 @@ public:
|
||||
/// having NMAGIC/OMAGIC
|
||||
virtual bool allowLinkWithDynamicLibraries() const {
|
||||
if (_outputMagic == OutputMagic::NMAGIC ||
|
||||
_outputMagic == OutputMagic::OMAGIC ||
|
||||
_noAllowDynamicLibraries)
|
||||
_outputMagic == OutputMagic::OMAGIC || _noAllowDynamicLibraries)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const;
|
||||
|
||||
static std::unique_ptr<ELFTargetInfo> create(llvm::Triple);
|
||||
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
|
||||
|
||||
/// \brief Does this relocation belong in the dynamic plt relocation table?
|
||||
///
|
||||
@@ -155,31 +157,32 @@ public:
|
||||
bool appendLibrary(StringRef libName);
|
||||
|
||||
private:
|
||||
ELFTargetInfo() LLVM_DELETED_FUNCTION;
|
||||
ELFLinkingContext() LLVM_DELETED_FUNCTION;
|
||||
|
||||
protected:
|
||||
ELFTargetInfo(llvm::Triple, std::unique_ptr<TargetHandlerBase>);
|
||||
ELFLinkingContext(llvm::Triple, std::unique_ptr<TargetHandlerBase>);
|
||||
|
||||
virtual Writer &writer() const;
|
||||
|
||||
uint16_t _outputFileType; // e.g ET_EXEC
|
||||
llvm::Triple _triple;
|
||||
uint16_t _outputFileType; // e.g ET_EXEC
|
||||
llvm::Triple _triple;
|
||||
std::unique_ptr<TargetHandlerBase> _targetHandler;
|
||||
uint64_t _baseAddress;
|
||||
bool _isStaticExecutable;
|
||||
bool _outputYAML;
|
||||
bool _noInhibitExec;
|
||||
bool _mergeCommonStrings;
|
||||
bool _runLayoutPass;
|
||||
bool _useShlibUndefines;
|
||||
bool _dynamicLinkerArg;
|
||||
bool _noAllowDynamicLibraries;
|
||||
OutputMagic _outputMagic;
|
||||
StringRefVector _inputSearchPaths;
|
||||
llvm::BumpPtrAllocator _extraStrings;
|
||||
std::unique_ptr<Reader> _elfReader;
|
||||
std::unique_ptr<Writer> _writer;
|
||||
std::unique_ptr<Reader> _linkerScriptReader;
|
||||
StringRef _dynamicLinkerPath;
|
||||
uint64_t _baseAddress;
|
||||
bool _isStaticExecutable;
|
||||
bool _outputYAML;
|
||||
bool _noInhibitExec;
|
||||
bool _mergeCommonStrings;
|
||||
bool _runLayoutPass;
|
||||
bool _useShlibUndefines;
|
||||
bool _dynamicLinkerArg;
|
||||
bool _noAllowDynamicLibraries;
|
||||
OutputMagic _outputMagic;
|
||||
StringRefVector _inputSearchPaths;
|
||||
llvm::BumpPtrAllocator _extraStrings;
|
||||
std::unique_ptr<Reader> _elfReader;
|
||||
std::unique_ptr<Writer> _writer;
|
||||
std::unique_ptr<Reader> _linkerScriptReader;
|
||||
StringRef _dynamicLinkerPath;
|
||||
};
|
||||
} // end namespace lld
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lld/ReaderWriter/MachOTargetInfo.h ---------------------------------===//
|
||||
//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,10 +7,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_MACHO_TARGET_INFO_H
|
||||
#define LLD_READER_WRITER_MACHO_TARGET_INFO_H
|
||||
#ifndef LLD_READER_WRITER_MACHO_LINKER_CONTEXT_H
|
||||
#define LLD_READER_WRITER_MACHO_LINKER_CONTEXT_H
|
||||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
@@ -19,21 +19,22 @@
|
||||
namespace lld {
|
||||
|
||||
namespace mach_o {
|
||||
class KindHandler; // defined in lib. this header is in include.
|
||||
class KindHandler; // defined in lib. this header is in include.
|
||||
}
|
||||
|
||||
class MachOTargetInfo : public TargetInfo {
|
||||
class MachOLinkingContext : public LinkingContext {
|
||||
public:
|
||||
MachOTargetInfo();
|
||||
~MachOTargetInfo();
|
||||
MachOLinkingContext();
|
||||
~MachOLinkingContext();
|
||||
|
||||
virtual void addPasses(PassManager &pm) const;
|
||||
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
|
||||
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
|
||||
virtual bool validateImpl(raw_ostream &diagnostics);
|
||||
|
||||
virtual error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const;
|
||||
|
||||
uint32_t getCPUType() const;
|
||||
uint32_t getCPUSubType() const;
|
||||
@@ -42,14 +43,12 @@ public:
|
||||
bool addUnixThreadLoadCommand() const;
|
||||
bool outputTypeHasEntry() const;
|
||||
|
||||
virtual uint64_t pageZeroSize() const {
|
||||
return _pageZeroSize;
|
||||
}
|
||||
|
||||
virtual uint64_t pageZeroSize() const { return _pageZeroSize; }
|
||||
|
||||
mach_o::KindHandler &kindHandler() const;
|
||||
|
||||
|
||||
uint32_t outputFileType() const { return _outputFileType; }
|
||||
|
||||
|
||||
enum Arch {
|
||||
arch_unknown,
|
||||
arch_x86,
|
||||
@@ -58,11 +57,9 @@ public:
|
||||
arch_armv7,
|
||||
arch_armv7s,
|
||||
};
|
||||
|
||||
|
||||
enum class OS {
|
||||
macOSX,
|
||||
iOS,
|
||||
iOS_simulator
|
||||
macOSX, iOS, iOS_simulator
|
||||
};
|
||||
|
||||
Arch arch() const { return _arch; }
|
||||
@@ -74,38 +71,39 @@ public:
|
||||
bool minOS(StringRef mac, StringRef iOS) const;
|
||||
void setDoNothing(bool value) { _doNothing = value; }
|
||||
bool doNothing() const { return _doNothing; }
|
||||
|
||||
|
||||
static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
|
||||
static Arch archFromName(StringRef archName);
|
||||
static uint32_t cpuTypeFromArch(Arch arch);
|
||||
static uint32_t cpuSubtypeFromArch(Arch arch);
|
||||
|
||||
|
||||
private:
|
||||
virtual Writer &writer() const;
|
||||
|
||||
/// 32-bit packed encoding of "X.Y.Z" where nibbles are xxxx.yy.zz.
|
||||
/// 32-bit packed encoding of "X.Y.Z" where nibbles are xxxx.yy.zz.
|
||||
struct PackedVersion {
|
||||
PackedVersion(StringRef);
|
||||
static bool parse(StringRef, PackedVersion&);
|
||||
bool operator<(const PackedVersion&) const;
|
||||
bool operator>=(const PackedVersion&) const;
|
||||
bool operator==(const PackedVersion&) const;
|
||||
private:
|
||||
PackedVersion(uint32_t v) : _value(v) { }
|
||||
static bool parse(StringRef, PackedVersion &);
|
||||
bool operator<(const PackedVersion &) const;
|
||||
bool operator>=(const PackedVersion &) const;
|
||||
bool operator==(const PackedVersion &) const;
|
||||
|
||||
uint32_t _value;
|
||||
private:
|
||||
PackedVersion(uint32_t v) : _value(v) {}
|
||||
|
||||
uint32_t _value;
|
||||
};
|
||||
|
||||
uint32_t _outputFileType; // e.g MH_EXECUTE
|
||||
bool _outputFileTypeStatic; // Disambiguate static vs dynamic prog
|
||||
bool _doNothing; // for -help and -v which just print info
|
||||
Arch _arch;
|
||||
OS _os;
|
||||
PackedVersion _osMinVersion;
|
||||
uint64_t _pageZeroSize;
|
||||
mutable std::unique_ptr<mach_o::KindHandler> _kindHandler;
|
||||
mutable std::unique_ptr<Reader> _machoReader;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
uint32_t _outputFileType; // e.g MH_EXECUTE
|
||||
bool _outputFileTypeStatic; // Disambiguate static vs dynamic prog
|
||||
bool _doNothing; // for -help and -v which just print info
|
||||
Arch _arch;
|
||||
OS _os;
|
||||
PackedVersion _osMinVersion;
|
||||
uint64_t _pageZeroSize;
|
||||
mutable std::unique_ptr<mach_o::KindHandler> _kindHandler;
|
||||
mutable std::unique_ptr<Reader> _machoReader;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
};
|
||||
|
||||
} // end namespace lld
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lld/ReaderWriter/PECOFFTargetInfo.h ---------------------------------===//
|
||||
//===- lld/ReaderWriter/PECOFFLinkingContext.h ----------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,12 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_PECOFF_TARGET_INFO_H
|
||||
#define LLD_READER_WRITER_PECOFF_TARGET_INFO_H
|
||||
#ifndef LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
|
||||
#define LLD_READER_WRITER_PECOFF_LINKER_CONTEXT_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
|
||||
namespace lld {
|
||||
|
||||
class PECOFFTargetInfo : public TargetInfo {
|
||||
class PECOFFLinkingContext : public LinkingContext {
|
||||
public:
|
||||
PECOFFTargetInfo()
|
||||
PECOFFLinkingContext()
|
||||
: _baseAddress(0x400000), _stackReserve(1024 * 1024), _stackCommit(4096),
|
||||
_heapReserve(1024 * 1024), _heapCommit(4096),
|
||||
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), _minOSVersion(6, 0),
|
||||
_nxCompat(true), _largeAddressAware(false), _baseRelocationEnabled(true),
|
||||
_terminalServerAware(true) {}
|
||||
_nxCompat(true), _largeAddressAware(false),
|
||||
_baseRelocationEnabled(true), _terminalServerAware(true) {}
|
||||
|
||||
struct OSVersion {
|
||||
OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
|
||||
@@ -37,9 +37,9 @@ public:
|
||||
int minorVersion;
|
||||
};
|
||||
|
||||
virtual error_code parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const;
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const;
|
||||
|
||||
virtual Writer &writer() const;
|
||||
virtual bool validateImpl(raw_ostream &diagnostics);
|
||||
@@ -17,10 +17,10 @@
|
||||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
class ELFTargetInfo;
|
||||
class ELFLinkingContext;
|
||||
class File;
|
||||
class LinkerInput;
|
||||
class TargetInfo;
|
||||
class LinkingContext;
|
||||
|
||||
/// \brief An abstract class for reading object files, library files, and
|
||||
/// executable files.
|
||||
@@ -44,19 +44,18 @@ public:
|
||||
|
||||
protected:
|
||||
// only concrete subclasses can be instantiated
|
||||
Reader(const TargetInfo &ti)
|
||||
: _targetInfo(ti) {}
|
||||
Reader(const LinkingContext &context) : _context(context) {}
|
||||
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
typedef ErrorOr<Reader &> ReaderFunc(const LinkerInput &);
|
||||
|
||||
std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &);
|
||||
std::unique_ptr<Reader> createReaderMachO(const TargetInfo &);
|
||||
std::unique_ptr<Reader> createReaderNative(const TargetInfo &);
|
||||
std::unique_ptr<Reader> createReaderPECOFF(const TargetInfo &);
|
||||
std::unique_ptr<Reader> createReaderYAML(const TargetInfo &);
|
||||
std::unique_ptr<Reader> createReaderELF(const ELFLinkingContext &);
|
||||
std::unique_ptr<Reader> createReaderMachO(const LinkingContext &);
|
||||
std::unique_ptr<Reader> createReaderNative(const LinkingContext &);
|
||||
std::unique_ptr<Reader> createReaderPECOFF(const LinkingContext &);
|
||||
std::unique_ptr<Reader> createReaderYAML(const LinkingContext &);
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,15 +23,14 @@
|
||||
|
||||
namespace lld {
|
||||
class File;
|
||||
class LinkingContext;
|
||||
class LinkerInput;
|
||||
class TargetInfo;
|
||||
|
||||
/// \brief ReaderArchive is a class for reading archive libraries
|
||||
class ReaderArchive : public Reader {
|
||||
public:
|
||||
ReaderArchive(const TargetInfo &ti, const Reader &memberReader)
|
||||
: Reader(ti) {
|
||||
}
|
||||
ReaderArchive(const LinkingContext &context, const Reader &memberReader)
|
||||
: Reader(context) {}
|
||||
|
||||
/// \brief Returns a vector of Files that are contained in the archive file
|
||||
/// pointed to by the Memorybuffer
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
namespace lld {
|
||||
class File;
|
||||
class LinkerInput;
|
||||
class TargetInfo;
|
||||
class LinkingContext;
|
||||
|
||||
/// \brief ReaderLinkerScript is a class for reading linker scripts
|
||||
class ReaderLinkerScript : public Reader {
|
||||
public:
|
||||
explicit ReaderLinkerScript(const TargetInfo &ti)
|
||||
: Reader(ti) {}
|
||||
explicit ReaderLinkerScript(const LinkingContext &context)
|
||||
: Reader(context) {}
|
||||
|
||||
/// \brief Returns a vector of Files that are contained in the archive file
|
||||
/// pointed to by the Memorybuffer
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
namespace lld {
|
||||
class SimpleFile : public MutableFile {
|
||||
public:
|
||||
SimpleFile(const TargetInfo &ti, StringRef path) : MutableFile(ti, path) {
|
||||
SimpleFile(const LinkingContext &context, StringRef path)
|
||||
: MutableFile(context, path) {
|
||||
static uint32_t lastOrdinal = 0;
|
||||
_ordinal = lastOrdinal++;
|
||||
}
|
||||
@@ -169,9 +170,7 @@ private:
|
||||
|
||||
class SimpleUndefinedAtom : public UndefinedAtom {
|
||||
public:
|
||||
SimpleUndefinedAtom(const File &f, StringRef name)
|
||||
: _file(f)
|
||||
, _name(name) {
|
||||
SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) {
|
||||
assert(!name.empty() && "UndefinedAtoms must have a name");
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
#include <memory>
|
||||
|
||||
namespace lld {
|
||||
class ELFTargetInfo;
|
||||
class ELFLinkingContext;
|
||||
class File;
|
||||
class InputFiles;
|
||||
class MachOTargetInfo;
|
||||
class PECOFFTargetInfo;
|
||||
class TargetInfo;
|
||||
class MachOLinkingContext;
|
||||
class PECOFFLinkingContext;
|
||||
class LinkingContext;
|
||||
|
||||
/// \brief The Writer is an abstract class for writing object files, shared
|
||||
/// library files, and executable files. Each file format (e.g. ELF, mach-o,
|
||||
@@ -42,11 +42,11 @@ protected:
|
||||
Writer();
|
||||
};
|
||||
|
||||
std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &);
|
||||
std::unique_ptr<Writer> createWriterMachO(const MachOTargetInfo &);
|
||||
std::unique_ptr<Writer> createWriterNative(const TargetInfo &);
|
||||
std::unique_ptr<Writer> createWriterPECOFF(const PECOFFTargetInfo &);
|
||||
std::unique_ptr<Writer> createWriterYAML(const TargetInfo &);
|
||||
std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &);
|
||||
std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &);
|
||||
std::unique_ptr<Writer> createWriterNative(const LinkingContext &);
|
||||
std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &);
|
||||
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &);
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,8 @@ add_lld_library(lldCore
|
||||
Error.cpp
|
||||
File.cpp
|
||||
InputFiles.cpp
|
||||
LinkingContext.cpp
|
||||
PassManager.cpp
|
||||
Resolver.cpp
|
||||
SymbolTable.cpp
|
||||
TargetInfo.cpp
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/Core/TargetInfo.cpp - Linker Target Info Interface -------------===//
|
||||
//===- lib/Core/LinkingContext.cpp - Linker Context Object Interface ------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,14 +7,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
TargetInfo::TargetInfo()
|
||||
LinkingContext::LinkingContext()
|
||||
: Reader(*this), _deadStrip(false), _globalsAreDeadStripRoots(false),
|
||||
_searchArchivesToOverrideTentativeDefinitions(false),
|
||||
_searchSharedLibrariesToOverrideTentativeDefinitions(false),
|
||||
@@ -24,15 +24,16 @@ TargetInfo::TargetInfo()
|
||||
_allowRemainingUndefines(false), _logInputFiles(false),
|
||||
_allowShlibUndefines(false) {}
|
||||
|
||||
TargetInfo::~TargetInfo() {}
|
||||
LinkingContext::~LinkingContext() {}
|
||||
|
||||
bool TargetInfo::validate(raw_ostream &diagnostics) {
|
||||
bool LinkingContext::validate(raw_ostream &diagnostics) {
|
||||
_yamlReader = createReaderYAML(*this);
|
||||
return validateImpl(diagnostics);
|
||||
}
|
||||
|
||||
error_code TargetInfo::readFile(StringRef path,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
error_code
|
||||
LinkingContext::readFile(StringRef path,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
OwningPtr<llvm::MemoryBuffer> opmb;
|
||||
if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb))
|
||||
return ec;
|
||||
@@ -41,16 +42,14 @@ error_code TargetInfo::readFile(StringRef path,
|
||||
return this->parseFile(mb, result);
|
||||
}
|
||||
|
||||
error_code TargetInfo::writeFile(const File &linkedFile) const {
|
||||
return this->writer().writeFile(linkedFile, _outputPath);
|
||||
error_code LinkingContext::writeFile(const File &linkedFile) const {
|
||||
return this->writer().writeFile(linkedFile, _outputPath);
|
||||
}
|
||||
|
||||
void TargetInfo::addImplicitFiles(InputFiles& inputs) const {
|
||||
this->writer().addFiles(inputs);
|
||||
}
|
||||
|
||||
void TargetInfo::addPasses(PassManager &pm) const {
|
||||
void LinkingContext::addImplicitFiles(InputFiles &inputs) const {
|
||||
this->writer().addFiles(inputs);
|
||||
}
|
||||
|
||||
void LinkingContext::addPasses(PassManager &pm) const {}
|
||||
|
||||
} // end namespace lld
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/Core/SymbolTable.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
|
||||
#include "llvm/Support/Debug.h"
|
||||
@@ -134,7 +134,7 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
|
||||
// tell symbol table
|
||||
_symbolTable.add(atom);
|
||||
|
||||
if (_targetInfo.deadStrip()) {
|
||||
if (_context.deadStrip()) {
|
||||
// add to set of dead-strip-roots, all symbols that
|
||||
// the compiler marks as don't strip
|
||||
if (atom.deadStrip() == DefinedAtom::deadStripNever)
|
||||
@@ -188,9 +188,9 @@ void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
|
||||
void Resolver::resolveUndefines() {
|
||||
ScopedTask task(getDefaultDomain(), "resolveUndefines");
|
||||
const bool searchArchives =
|
||||
_targetInfo.searchArchivesToOverrideTentativeDefinitions();
|
||||
_context.searchArchivesToOverrideTentativeDefinitions();
|
||||
const bool searchSharedLibs =
|
||||
_targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();
|
||||
_context.searchSharedLibrariesToOverrideTentativeDefinitions();
|
||||
|
||||
// keep looping until no more undefines were added in last loop
|
||||
unsigned int undefineGenCount = 0xFFFFFFFF;
|
||||
@@ -273,15 +273,15 @@ void Resolver::markLive(const Atom &atom) {
|
||||
void Resolver::deadStripOptimize() {
|
||||
ScopedTask task(getDefaultDomain(), "deadStripOptimize");
|
||||
// only do this optimization with -dead_strip
|
||||
if (!_targetInfo.deadStrip())
|
||||
if (!_context.deadStrip())
|
||||
return;
|
||||
|
||||
// clear liveness on all atoms
|
||||
_liveAtoms.clear();
|
||||
|
||||
// By default, shared libraries are built with all globals as dead strip roots
|
||||
if (_targetInfo.globalsAreDeadStripRoots()) {
|
||||
for ( const Atom *atom : _atoms ) {
|
||||
if (_context.globalsAreDeadStripRoots()) {
|
||||
for (const Atom *atom : _atoms) {
|
||||
const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
|
||||
if (defAtom == nullptr)
|
||||
continue;
|
||||
@@ -291,7 +291,7 @@ void Resolver::deadStripOptimize() {
|
||||
}
|
||||
|
||||
// Or, use list of names that are dead stip roots.
|
||||
for (const StringRef &name : _targetInfo.deadStripRoots()) {
|
||||
for (const StringRef &name : _context.deadStripRoots()) {
|
||||
const Atom *symAtom = _symbolTable.findByName(name);
|
||||
assert(symAtom->definition() != Atom::definitionUndefined);
|
||||
_deadStripRoots.insert(symAtom);
|
||||
@@ -317,7 +317,7 @@ bool Resolver::checkUndefines(bool final) {
|
||||
// build vector of remaining undefined symbols
|
||||
std::vector<const UndefinedAtom *> undefinedAtoms;
|
||||
_symbolTable.undefines(undefinedAtoms);
|
||||
if (_targetInfo.deadStrip()) {
|
||||
if (_context.deadStrip()) {
|
||||
// When dead code stripping, we don't care if dead atoms are undefined.
|
||||
undefinedAtoms.erase(std::remove_if(
|
||||
undefinedAtoms.begin(), undefinedAtoms.end(),
|
||||
@@ -337,18 +337,18 @@ bool Resolver::checkUndefines(bool final) {
|
||||
|
||||
// If this is a library and undefined symbols are allowed on the
|
||||
// target platform, skip over it.
|
||||
if (isa<SharedLibraryFile>(f) && _targetInfo.allowShlibUndefines())
|
||||
if (isa<SharedLibraryFile>(f) && _context.allowShlibUndefines())
|
||||
continue;
|
||||
|
||||
// Seems like this symbol is undefined. Warn that.
|
||||
foundUndefines = true;
|
||||
if (_targetInfo.printRemainingUndefines()) {
|
||||
if (_context.printRemainingUndefines()) {
|
||||
llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
|
||||
<< " : " << undefAtom->name() << "\n";
|
||||
}
|
||||
}
|
||||
if (foundUndefines) {
|
||||
if (_targetInfo.printRemainingUndefines())
|
||||
if (_context.printRemainingUndefines())
|
||||
llvm::errs() << "symbol(s) not found\n";
|
||||
return true;
|
||||
}
|
||||
@@ -393,7 +393,7 @@ bool Resolver::resolve() {
|
||||
this->updateReferences();
|
||||
this->deadStripOptimize();
|
||||
if (this->checkUndefines(false)) {
|
||||
if (!_targetInfo.allowRemainingUndefines())
|
||||
if (!_context.allowRemainingUndefines())
|
||||
return true;
|
||||
}
|
||||
this->removeCoalescedAwayAtoms();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
SymbolTable::SymbolTable(const TargetInfo &ti) : _targetInfo(ti) {}
|
||||
SymbolTable::SymbolTable(const LinkingContext &context) : _context(context) {}
|
||||
|
||||
void SymbolTable::add(const UndefinedAtom &atom) {
|
||||
this->addByName(atom);
|
||||
@@ -183,7 +183,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
||||
useNew = false;
|
||||
}
|
||||
else {
|
||||
if (_targetInfo.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
// FIXME: need diagonstics interface for writing warning messages
|
||||
llvm::errs() << "lld warning: undefined symbol "
|
||||
<< existingUndef->name()
|
||||
@@ -208,7 +208,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
||||
bool sameName = curShLib->loadName().equals(newShLib->loadName());
|
||||
if ( !sameName ) {
|
||||
useNew = false;
|
||||
if (_targetInfo.warnIfCoalesableAtomsHaveDifferentLoadName()) {
|
||||
if (_context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
|
||||
// FIXME: need diagonstics interface for writing warning messages
|
||||
llvm::errs() << "lld warning: shared library symbol "
|
||||
<< curShLib->name()
|
||||
@@ -220,7 +220,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
||||
}
|
||||
else if ( ! sameNullness ) {
|
||||
useNew = false;
|
||||
if (_targetInfo.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
// FIXME: need diagonstics interface for writing warning messages
|
||||
llvm::errs() << "lld warning: shared library symbol "
|
||||
<< curShLib->name()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/CoreTargetInfo.h"
|
||||
#include "lld/ReaderWriter/CoreLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -69,16 +69,15 @@ public:
|
||||
namespace lld {
|
||||
|
||||
bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
|
||||
CoreTargetInfo info;
|
||||
CoreLinkingContext info;
|
||||
if (parse(argc, argv, info))
|
||||
return true;
|
||||
|
||||
return Driver::link(info);
|
||||
}
|
||||
|
||||
|
||||
bool CoreDriver::parse(int argc, const char *argv[],
|
||||
CoreTargetInfo &info, raw_ostream &diagnostics) {
|
||||
bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &info,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse command line options using CoreOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
CoreOptTable table;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/MachOTargetInfo.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "../ReaderWriter/MachO/MachOFormat.hpp"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -73,7 +73,7 @@ namespace lld {
|
||||
|
||||
bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics) {
|
||||
MachOTargetInfo info;
|
||||
MachOLinkingContext info;
|
||||
if (parse(argc, argv, info, diagnostics))
|
||||
return true;
|
||||
if ( info.doNothing() )
|
||||
@@ -82,10 +82,9 @@ bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
|
||||
return link(info, diagnostics);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
MachOTargetInfo &info, raw_ostream &diagnostics) {
|
||||
bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
MachOLinkingContext &info,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse command line options using DarwinOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
DarwinLdOptTable table;
|
||||
@@ -149,10 +148,9 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
|
||||
// Handle -arch xxx
|
||||
if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) {
|
||||
info.setArch(MachOTargetInfo::archFromName(archStr->getValue()));
|
||||
if (info.arch() == MachOTargetInfo::arch_unknown) {
|
||||
diagnostics << "error: unknown arch named '"
|
||||
<< archStr->getValue()
|
||||
info.setArch(MachOLinkingContext::archFromName(archStr->getValue()));
|
||||
if (info.arch() == MachOLinkingContext::arch_unknown) {
|
||||
diagnostics << "error: unknown arch named '" << archStr->getValue()
|
||||
<< "'\n";
|
||||
return true;
|
||||
}
|
||||
@@ -165,19 +163,20 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
OPT_ios_simulator_version_min)) {
|
||||
switch (minOS->getOption().getID()) {
|
||||
case OPT_macosx_version_min:
|
||||
if (info.setOS(MachOTargetInfo::OS::macOSX, minOS->getValue())) {
|
||||
if (info.setOS(MachOLinkingContext::OS::macOSX, minOS->getValue())) {
|
||||
diagnostics << "error: malformed macosx_version_min value\n";
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OPT_ios_version_min:
|
||||
if (info.setOS(MachOTargetInfo::OS::iOS, minOS->getValue())) {
|
||||
if (info.setOS(MachOLinkingContext::OS::iOS, minOS->getValue())) {
|
||||
diagnostics << "error: malformed ios_version_min value\n";
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case OPT_ios_simulator_version_min:
|
||||
if (info.setOS(MachOTargetInfo::OS::iOS_simulator, minOS->getValue())) {
|
||||
if (info.setOS(MachOLinkingContext::OS::iOS_simulator,
|
||||
minOS->getValue())) {
|
||||
diagnostics << "error: malformed ios_simulator_version_min value\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,33 +29,33 @@
|
||||
namespace lld {
|
||||
|
||||
/// This is where the link is actually performed.
|
||||
bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
|
||||
bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
|
||||
// Honor -mllvm
|
||||
if (!targetInfo.llvmOptions().empty()) {
|
||||
unsigned numArgs = targetInfo.llvmOptions().size();
|
||||
const char **args = new const char*[numArgs + 2];
|
||||
if (!context.llvmOptions().empty()) {
|
||||
unsigned numArgs = context.llvmOptions().size();
|
||||
const char **args = new const char *[numArgs + 2];
|
||||
args[0] = "lld (LLVM option parsing)";
|
||||
for (unsigned i = 0; i != numArgs; ++i)
|
||||
args[i + 1] = targetInfo.llvmOptions()[i];
|
||||
args[i + 1] = context.llvmOptions()[i];
|
||||
args[numArgs + 1] = 0;
|
||||
llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
|
||||
}
|
||||
|
||||
// Read inputs
|
||||
ScopedTask readTask(getDefaultDomain(), "Read Args");
|
||||
std::vector<std::vector<std::unique_ptr<File>>> files(
|
||||
targetInfo.inputFiles().size());
|
||||
std::vector<std::vector<std::unique_ptr<File>> > files(
|
||||
context.inputFiles().size());
|
||||
size_t index = 0;
|
||||
std::atomic<bool> fail(false);
|
||||
TaskGroup tg;
|
||||
for (const auto &input : targetInfo.inputFiles()) {
|
||||
if (targetInfo.logInputFiles())
|
||||
for (const auto &input : context.inputFiles()) {
|
||||
if (context.logInputFiles())
|
||||
llvm::outs() << input.getPath() << "\n";
|
||||
|
||||
tg.spawn([&, index] {
|
||||
if (error_code ec = targetInfo.readFile(input.getPath(), files[index])) {
|
||||
diagnostics << "Failed to read file: " << input.getPath()
|
||||
<< ": " << ec.message() << "\n";
|
||||
tg.spawn([ &, index]{
|
||||
if (error_code ec = context.readFile(input.getPath(), files[index])) {
|
||||
diagnostics << "Failed to read file: " << input.getPath() << ": "
|
||||
<< ec.message() << "\n";
|
||||
fail = true;
|
||||
return;
|
||||
}
|
||||
@@ -73,16 +73,16 @@ bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
|
||||
inputs.appendFiles(f);
|
||||
|
||||
// Give target a chance to add files.
|
||||
targetInfo.addImplicitFiles(inputs);
|
||||
context.addImplicitFiles(inputs);
|
||||
|
||||
// assign an ordinal to each file so sort() can preserve command line order
|
||||
inputs.assignFileOrdinals();
|
||||
|
||||
// Do core linking.
|
||||
ScopedTask resolveTask(getDefaultDomain(), "Resolve");
|
||||
Resolver resolver(targetInfo, inputs);
|
||||
Resolver resolver(context, inputs);
|
||||
if (resolver.resolve()) {
|
||||
if (!targetInfo.allowRemainingUndefines())
|
||||
if (!context.allowRemainingUndefines())
|
||||
return true;
|
||||
}
|
||||
MutableFile &merged = resolver.resultFile();
|
||||
@@ -91,14 +91,14 @@ bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
|
||||
// Run passes on linked atoms.
|
||||
ScopedTask passTask(getDefaultDomain(), "Passes");
|
||||
PassManager pm;
|
||||
targetInfo.addPasses(pm);
|
||||
context.addPasses(pm);
|
||||
pm.runOnFile(merged);
|
||||
passTask.end();
|
||||
|
||||
// Give linked atoms to Writer to generate output file.
|
||||
ScopedTask writeTask(getDefaultDomain(), "Write");
|
||||
if (error_code ec = targetInfo.writeFile(merged)) {
|
||||
diagnostics << "Failed to write file '" << targetInfo.outputPath()
|
||||
if (error_code ec = context.writeFile(merged)) {
|
||||
diagnostics << "Failed to write file '" << context.outputPath()
|
||||
<< "': " << ec.message() << "\n";
|
||||
return true;
|
||||
}
|
||||
@@ -106,6 +106,4 @@ bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
bool GnuLdDriver::linkELF(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics) {
|
||||
std::unique_ptr<ELFTargetInfo> options;
|
||||
std::unique_ptr<ELFLinkingContext> options;
|
||||
bool error = parse(argc, argv, options, diagnostics);
|
||||
if (error)
|
||||
return true;
|
||||
@@ -86,7 +86,7 @@ bool GnuLdDriver::linkELF(int argc, const char *argv[],
|
||||
}
|
||||
|
||||
bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
std::unique_ptr<ELFTargetInfo> &targetInfo,
|
||||
std::unique_ptr<ELFLinkingContext> &context,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse command line options using LDOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
@@ -115,13 +115,13 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use -target or use default target triple to instantiate TargetInfo
|
||||
// Use -target or use default target triple to instantiate LinkingContext
|
||||
llvm::Triple triple;
|
||||
if (llvm::opt::Arg *trip = parsedArgs->getLastArg(OPT_target))
|
||||
triple = llvm::Triple(trip->getValue());
|
||||
else
|
||||
triple = getDefaultTarget(argv[0]);
|
||||
std::unique_ptr<ELFTargetInfo> options(ELFTargetInfo::create(triple));
|
||||
std::unique_ptr<ELFLinkingContext> options(ELFLinkingContext::create(triple));
|
||||
|
||||
if (!options) {
|
||||
diagnostics << "unknown target triple\n";
|
||||
@@ -205,15 +205,15 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
|
||||
// Handle NMAGIC
|
||||
if (parsedArgs->getLastArg(OPT_nmagic))
|
||||
options->setOutputMagic(ELFTargetInfo::OutputMagic::NMAGIC);
|
||||
options->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
|
||||
|
||||
// Handle OMAGIC
|
||||
if (parsedArgs->getLastArg(OPT_omagic))
|
||||
options->setOutputMagic(ELFTargetInfo::OutputMagic::OMAGIC);
|
||||
options->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
|
||||
|
||||
// Handle --no-omagic
|
||||
if (parsedArgs->getLastArg(OPT_no_omagic)) {
|
||||
options->setOutputMagic(ELFTargetInfo::OutputMagic::DEFAULT);
|
||||
options->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
|
||||
options->setNoAllowDynamicLibraries();
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
if (options->validate(diagnostics))
|
||||
return true;
|
||||
|
||||
targetInfo.swap(options);
|
||||
context.swap(options);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "lld/ReaderWriter/PECOFFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
@@ -93,8 +93,8 @@ bool parseMemoryOption(const StringRef &arg, raw_ostream &diagnostics,
|
||||
|
||||
// Parse /base command line option. The argument for the parameter is in the
|
||||
// form of "<address>[:<size>]".
|
||||
bool parseBaseOption(PECOFFTargetInfo &info, const StringRef &arg,
|
||||
raw_ostream &diagnostics) {
|
||||
bool parseBaseOption(PECOFFLinkingContext &context, const StringRef &arg,
|
||||
raw_ostream &diagnostics) {
|
||||
// Size should be set to SizeOfImage field in the COFF header, and if it's
|
||||
// smaller than the actual size, the linker should warn about that. Currently
|
||||
// we just ignore the value of size parameter.
|
||||
@@ -107,31 +107,31 @@ bool parseBaseOption(PECOFFTargetInfo &info, const StringRef &arg,
|
||||
<< addr << "\n";
|
||||
return false;
|
||||
}
|
||||
info.setBaseAddress(addr);
|
||||
context.setBaseAddress(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse /stack command line option
|
||||
bool parseStackOption(PECOFFTargetInfo &info, const StringRef &arg,
|
||||
bool parseStackOption(PECOFFLinkingContext &context, const StringRef &arg,
|
||||
raw_ostream &diagnostics) {
|
||||
uint64_t reserve;
|
||||
uint64_t commit = info.getStackCommit();
|
||||
uint64_t commit = context.getStackCommit();
|
||||
if (!parseMemoryOption(arg, diagnostics, reserve, commit))
|
||||
return false;
|
||||
info.setStackReserve(reserve);
|
||||
info.setStackCommit(commit);
|
||||
context.setStackReserve(reserve);
|
||||
context.setStackCommit(commit);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse /heap command line option.
|
||||
bool parseHeapOption(PECOFFTargetInfo &info, const StringRef &arg,
|
||||
bool parseHeapOption(PECOFFLinkingContext &context, const StringRef &arg,
|
||||
raw_ostream &diagnostics) {
|
||||
uint64_t reserve;
|
||||
uint64_t commit = info.getHeapCommit();
|
||||
uint64_t commit = context.getHeapCommit();
|
||||
if (!parseMemoryOption(arg, diagnostics, reserve, commit))
|
||||
return false;
|
||||
info.setHeapReserve(reserve);
|
||||
info.setHeapCommit(commit);
|
||||
context.setHeapReserve(reserve);
|
||||
context.setHeapCommit(commit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
|
||||
.Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
|
||||
}
|
||||
|
||||
bool parseMinOSVersion(PECOFFTargetInfo &info, const StringRef &osVersion,
|
||||
raw_ostream &diagnostics) {
|
||||
bool parseMinOSVersion(PECOFFLinkingContext &context,
|
||||
const StringRef &osVersion, raw_ostream &diagnostics) {
|
||||
StringRef majorVersion, minorVersion;
|
||||
llvm::tie(majorVersion, minorVersion) = osVersion.split('.');
|
||||
if (minorVersion.empty())
|
||||
@@ -154,22 +154,22 @@ bool parseMinOSVersion(PECOFFTargetInfo &info, const StringRef &osVersion,
|
||||
return false;
|
||||
if (!checkNumber(minorVersion, "invalid OS minor version: ", diagnostics))
|
||||
return false;
|
||||
PECOFFTargetInfo::OSVersion minOSVersion(atoi(majorVersion.str().c_str()),
|
||||
atoi(minorVersion.str().c_str()));
|
||||
info.setMinOSVersion(minOSVersion);
|
||||
PECOFFLinkingContext::OSVersion minOSVersion(
|
||||
atoi(majorVersion.str().c_str()), atoi(minorVersion.str().c_str()));
|
||||
context.setMinOSVersion(minOSVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse /subsystem command line option. The form of /subsystem is
|
||||
// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
|
||||
bool parseSubsystemOption(PECOFFTargetInfo &info, std::string arg,
|
||||
bool parseSubsystemOption(PECOFFLinkingContext &context, std::string arg,
|
||||
raw_ostream &diagnostics) {
|
||||
StringRef subsystemStr, osVersionStr;
|
||||
llvm::tie(subsystemStr, osVersionStr) = StringRef(arg).split(',');
|
||||
|
||||
// Parse optional OS version if exists.
|
||||
if (!osVersionStr.empty())
|
||||
if (!parseMinOSVersion(info, osVersionStr, diagnostics))
|
||||
if (!parseMinOSVersion(context, osVersionStr, diagnostics))
|
||||
return false;
|
||||
|
||||
// Parse subsystem name.
|
||||
@@ -178,16 +178,17 @@ bool parseSubsystemOption(PECOFFTargetInfo &info, std::string arg,
|
||||
diagnostics << "error: unknown subsystem name: " << subsystemStr << "\n";
|
||||
return false;
|
||||
}
|
||||
info.setSubsystem(subsystem);
|
||||
context.setSubsystem(subsystem);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Replace a file extension with ".exe". If the given file has no
|
||||
// extension, just add ".exe".
|
||||
StringRef getDefaultOutputFileName(PECOFFTargetInfo &info, StringRef path) {
|
||||
StringRef getDefaultOutputFileName(PECOFFLinkingContext &context,
|
||||
StringRef path) {
|
||||
SmallString<128> smallStr = path;
|
||||
llvm::sys::path::replace_extension(smallStr, ".exe");
|
||||
return info.allocateString(smallStr.str());
|
||||
return context.allocateString(smallStr.str());
|
||||
}
|
||||
|
||||
// Split the given string with spaces.
|
||||
@@ -231,16 +232,17 @@ bool handleFailIfMismatchOption(StringRef option,
|
||||
|
||||
// Add ".lib" extension if the path does not already have the extension to mimic
|
||||
// link.exe behavior.
|
||||
StringRef canonicalizeImportLibraryPath(PECOFFTargetInfo &info, StringRef path) {
|
||||
StringRef canonicalizeImportLibraryPath(PECOFFLinkingContext &context,
|
||||
StringRef path) {
|
||||
std::string s(path.lower());
|
||||
if (StringRef(s).endswith(".lib"))
|
||||
return path;
|
||||
return info.allocateString(std::string(path).append(".lib"));
|
||||
return context.allocateString(std::string(path).append(".lib"));
|
||||
}
|
||||
|
||||
// Process "LINK" environment variable. If defined, the value of the variable
|
||||
// should be processed as command line arguments.
|
||||
std::vector<const char *> processLinkEnv(PECOFFTargetInfo &info,
|
||||
std::vector<const char *> processLinkEnv(PECOFFLinkingContext &context,
|
||||
int argc, const char **argv) {
|
||||
std::vector<const char *> ret;
|
||||
// The first argument is the name of the command. This should stay at the head
|
||||
@@ -251,7 +253,7 @@ std::vector<const char *> processLinkEnv(PECOFFTargetInfo &info,
|
||||
// Add arguments specified by the LINK environment variable.
|
||||
if (char *envp = ::getenv("LINK"))
|
||||
for (std::string &arg : splitArgList(envp))
|
||||
ret.push_back(info.allocateString(arg).data());
|
||||
ret.push_back(context.allocateString(arg).data());
|
||||
|
||||
// Add the rest of arguments passed via the command line.
|
||||
for (int i = 1; i < argc; ++i)
|
||||
@@ -262,10 +264,10 @@ std::vector<const char *> processLinkEnv(PECOFFTargetInfo &info,
|
||||
|
||||
// Process "LIB" environment variable. The variable contains a list of search
|
||||
// paths separated by semicolons.
|
||||
void processLibEnv(PECOFFTargetInfo &info) {
|
||||
void processLibEnv(PECOFFLinkingContext &context) {
|
||||
if (char *envp = ::getenv("LIB"))
|
||||
for (StringRef path : splitPathList(envp))
|
||||
info.appendInputSearchPath(info.allocateString(path));
|
||||
context.appendInputSearchPath(context.allocateString(path));
|
||||
}
|
||||
|
||||
// Parses the given command line options and returns the result. Returns NULL if
|
||||
@@ -300,16 +302,17 @@ std::unique_ptr<llvm::opt::InputArgList> parseArgs(int argc, const char *argv[],
|
||||
|
||||
bool WinLinkDriver::linkPECOFF(int argc, const char *argv[],
|
||||
raw_ostream &diagnostics) {
|
||||
PECOFFTargetInfo info;
|
||||
std::vector<const char *> newargv = processLinkEnv(info, argc, argv);
|
||||
processLibEnv(info);
|
||||
if (parse(newargv.size() - 1, &newargv[0], info, diagnostics))
|
||||
PECOFFLinkingContext context;
|
||||
std::vector<const char *> newargv = processLinkEnv(context, argc, argv);
|
||||
processLibEnv(context);
|
||||
if (parse(newargv.size() - 1, &newargv[0], context, diagnostics))
|
||||
return true;
|
||||
return link(info, diagnostics);
|
||||
return link(context, diagnostics);
|
||||
}
|
||||
|
||||
bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
PECOFFTargetInfo &info, raw_ostream &diagnostics) {
|
||||
PECOFFLinkingContext &context,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse the options.
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs = parseArgs(
|
||||
argc, argv, diagnostics);
|
||||
@@ -327,70 +330,70 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
|
||||
ie = parsedArgs->filtered_end();
|
||||
it != ie; ++it) {
|
||||
info.appendLLVMOption((*it)->getValue());
|
||||
context.appendLLVMOption((*it)->getValue());
|
||||
}
|
||||
|
||||
// handle /base
|
||||
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_base))
|
||||
if (!parseBaseOption(info, arg->getValue(), diagnostics))
|
||||
if (!parseBaseOption(context, arg->getValue(), diagnostics))
|
||||
return true;
|
||||
|
||||
// handle /stack
|
||||
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_stack))
|
||||
if (!parseStackOption(info, arg->getValue(), diagnostics))
|
||||
if (!parseStackOption(context, arg->getValue(), diagnostics))
|
||||
return true;
|
||||
|
||||
// handle /heap
|
||||
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_heap))
|
||||
if (!parseHeapOption(info, arg->getValue(), diagnostics))
|
||||
if (!parseHeapOption(context, arg->getValue(), diagnostics))
|
||||
return true;
|
||||
|
||||
// handle /subsystem
|
||||
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem))
|
||||
if (!parseSubsystemOption(info, arg->getValue(), diagnostics))
|
||||
if (!parseSubsystemOption(context, arg->getValue(), diagnostics))
|
||||
return true;
|
||||
|
||||
// handle /entry
|
||||
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_entry))
|
||||
info.setEntrySymbolName(arg->getValue());
|
||||
context.setEntrySymbolName(arg->getValue());
|
||||
|
||||
// handle /libpath
|
||||
for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_libpath),
|
||||
ie = parsedArgs->filtered_end();
|
||||
it != ie; ++it) {
|
||||
info.appendInputSearchPath((*it)->getValue());
|
||||
context.appendInputSearchPath((*it)->getValue());
|
||||
}
|
||||
|
||||
// handle /force
|
||||
if (parsedArgs->getLastArg(OPT_force))
|
||||
info.setAllowRemainingUndefines(true);
|
||||
context.setAllowRemainingUndefines(true);
|
||||
|
||||
// handle /nxcompat:no
|
||||
if (parsedArgs->getLastArg(OPT_no_nxcompat))
|
||||
info.setNxCompat(false);
|
||||
context.setNxCompat(false);
|
||||
|
||||
// handle /largeaddressaware
|
||||
if (parsedArgs->getLastArg(OPT_largeaddressaware))
|
||||
info.setLargeAddressAware(true);
|
||||
context.setLargeAddressAware(true);
|
||||
|
||||
// handle /fixed
|
||||
if (parsedArgs->getLastArg(OPT_fixed))
|
||||
info.setBaseRelocationEnabled(false);
|
||||
context.setBaseRelocationEnabled(false);
|
||||
|
||||
// handle /tsaware:no
|
||||
if (parsedArgs->getLastArg(OPT_no_tsaware))
|
||||
info.setTerminalServerAware(false);
|
||||
context.setTerminalServerAware(false);
|
||||
|
||||
// handle /include
|
||||
for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_incl),
|
||||
ie = parsedArgs->filtered_end();
|
||||
it != ie; ++it) {
|
||||
info.addInitialUndefinedSymbol((*it)->getValue());
|
||||
context.addInitialUndefinedSymbol((*it)->getValue());
|
||||
}
|
||||
|
||||
// handle /out
|
||||
if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_out))
|
||||
info.setOutputPath(outpath->getValue());
|
||||
context.setOutputPath(outpath->getValue());
|
||||
|
||||
// handle /defaultlib
|
||||
std::vector<StringRef> defaultLibs;
|
||||
@@ -427,22 +430,22 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
|
||||
// Add input files specified via the command line.
|
||||
for (const StringRef path : inputPaths)
|
||||
info.appendInputFileOrLibrary(path);
|
||||
context.appendInputFileOrLibrary(path);
|
||||
|
||||
// Add the library files specified by /defaultlib option. The files
|
||||
// specified by the option should have lower precedence than the other files
|
||||
// added above, which is important for link.exe compatibility.
|
||||
for (const StringRef path : defaultLibs)
|
||||
info.appendLibraryFile(canonicalizeImportLibraryPath(info, path));
|
||||
context.appendLibraryFile(canonicalizeImportLibraryPath(context, path));
|
||||
|
||||
// If /out option was not specified, the default output file name is
|
||||
// constructed by replacing an extension of the first input file
|
||||
// with ".exe".
|
||||
if (info.outputPath().empty() && !inputPaths.empty())
|
||||
info.setOutputPath(getDefaultOutputFileName(info, inputPaths[0]));
|
||||
if (context.outputPath().empty() && !inputPaths.empty())
|
||||
context.setOutputPath(getDefaultOutputFileName(context, inputPaths[0]));
|
||||
|
||||
// Validate the combination of options used.
|
||||
return info.validate(diagnostics);
|
||||
return context.validate(diagnostics);
|
||||
}
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -6,7 +6,7 @@ add_subdirectory(Native)
|
||||
add_subdirectory(PECOFF)
|
||||
add_subdirectory(YAML)
|
||||
add_lld_library(lldReaderWriter
|
||||
CoreTargetInfo.cpp
|
||||
CoreLinkingContext.cpp
|
||||
LinkerScript.cpp
|
||||
Reader.cpp
|
||||
ReaderArchive.cpp
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/CoreTargetInfo.cpp --------------------------------===//
|
||||
//===- lib/ReaderWriter/CoreLinkingContext.cpp ----------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/ReaderWriter/CoreTargetInfo.h"
|
||||
#include "lld/ReaderWriter/CoreLinkingContext.h"
|
||||
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
|
||||
using namespace lld;
|
||||
|
||||
namespace {
|
||||
@@ -23,74 +22,48 @@ namespace {
|
||||
/// \brief Simple atom created by the stubs pass.
|
||||
class TestingStubAtom : public DefinedAtom {
|
||||
public:
|
||||
TestingStubAtom(const File &F, const Atom&) : _file(F) {
|
||||
TestingStubAtom(const File &F, const Atom &) : _file(F) {
|
||||
static uint32_t lastOrdinal = 0;
|
||||
_ordinal = lastOrdinal++;
|
||||
}
|
||||
|
||||
virtual const File &file() const {
|
||||
return _file;
|
||||
}
|
||||
virtual const File &file() const { return _file; }
|
||||
|
||||
virtual StringRef name() const {
|
||||
return StringRef();
|
||||
}
|
||||
virtual StringRef name() const { return StringRef(); }
|
||||
|
||||
virtual uint64_t ordinal() const {
|
||||
return _ordinal;
|
||||
}
|
||||
virtual uint64_t ordinal() const { return _ordinal; }
|
||||
|
||||
virtual uint64_t size() const {
|
||||
return 0;
|
||||
}
|
||||
virtual uint64_t size() const { return 0; }
|
||||
|
||||
virtual Scope scope() const {
|
||||
return DefinedAtom::scopeLinkageUnit;
|
||||
}
|
||||
virtual Scope scope() const { return DefinedAtom::scopeLinkageUnit; }
|
||||
|
||||
virtual Interposable interposable() const {
|
||||
return DefinedAtom::interposeNo;
|
||||
}
|
||||
virtual Interposable interposable() const { return DefinedAtom::interposeNo; }
|
||||
|
||||
virtual Merge merge() const {
|
||||
return DefinedAtom::mergeNo;
|
||||
}
|
||||
virtual Merge merge() const { return DefinedAtom::mergeNo; }
|
||||
|
||||
virtual ContentType contentType() const {
|
||||
return DefinedAtom::typeStub;
|
||||
}
|
||||
virtual ContentType contentType() const { return DefinedAtom::typeStub; }
|
||||
|
||||
virtual Alignment alignment() const {
|
||||
return Alignment(0, 0);
|
||||
}
|
||||
virtual Alignment alignment() const { return Alignment(0, 0); }
|
||||
|
||||
virtual SectionChoice sectionChoice() const {
|
||||
return DefinedAtom::sectionBasedOnContent;
|
||||
}
|
||||
|
||||
virtual StringRef customSectionName() const {
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
virtual SectionPosition sectionPosition() const {
|
||||
return sectionPositionAny;
|
||||
}
|
||||
|
||||
virtual StringRef customSectionName() const { return StringRef(); }
|
||||
|
||||
virtual SectionPosition sectionPosition() const { return sectionPositionAny; }
|
||||
|
||||
virtual DeadStripKind deadStrip() const {
|
||||
return DefinedAtom::deadStripNormal;
|
||||
}
|
||||
|
||||
virtual ContentPermissions permissions() const {
|
||||
virtual ContentPermissions permissions() const {
|
||||
return DefinedAtom::permR_X;
|
||||
}
|
||||
|
||||
virtual bool isAlias() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool isAlias() const { return false; }
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>();
|
||||
}
|
||||
virtual ArrayRef<uint8_t> rawContent() const { return ArrayRef<uint8_t>(); }
|
||||
|
||||
virtual reference_iterator begin() const {
|
||||
return reference_iterator(*this, nullptr);
|
||||
@@ -104,8 +77,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void incrementIterator(const void *&iter) const {
|
||||
}
|
||||
virtual void incrementIterator(const void *&iter) const {}
|
||||
|
||||
private:
|
||||
const File &_file;
|
||||
@@ -115,74 +87,48 @@ private:
|
||||
/// \brief Simple atom created by the GOT pass.
|
||||
class TestingGOTAtom : public DefinedAtom {
|
||||
public:
|
||||
TestingGOTAtom(const File &F, const Atom&) : _file(F) {
|
||||
TestingGOTAtom(const File &F, const Atom &) : _file(F) {
|
||||
static uint32_t lastOrdinal = 0;
|
||||
_ordinal = lastOrdinal++;
|
||||
}
|
||||
|
||||
virtual const File &file() const {
|
||||
return _file;
|
||||
}
|
||||
virtual const File &file() const { return _file; }
|
||||
|
||||
virtual StringRef name() const {
|
||||
return StringRef();
|
||||
}
|
||||
virtual StringRef name() const { return StringRef(); }
|
||||
|
||||
virtual uint64_t ordinal() const {
|
||||
return _ordinal;
|
||||
}
|
||||
virtual uint64_t ordinal() const { return _ordinal; }
|
||||
|
||||
virtual uint64_t size() const {
|
||||
return 0;
|
||||
}
|
||||
virtual uint64_t size() const { return 0; }
|
||||
|
||||
virtual Scope scope() const {
|
||||
return DefinedAtom::scopeLinkageUnit;
|
||||
}
|
||||
virtual Scope scope() const { return DefinedAtom::scopeLinkageUnit; }
|
||||
|
||||
virtual Interposable interposable() const {
|
||||
return DefinedAtom::interposeNo;
|
||||
}
|
||||
virtual Interposable interposable() const { return DefinedAtom::interposeNo; }
|
||||
|
||||
virtual Merge merge() const {
|
||||
return DefinedAtom::mergeNo;
|
||||
}
|
||||
virtual Merge merge() const { return DefinedAtom::mergeNo; }
|
||||
|
||||
virtual ContentType contentType() const {
|
||||
return DefinedAtom::typeGOT;
|
||||
}
|
||||
virtual ContentType contentType() const { return DefinedAtom::typeGOT; }
|
||||
|
||||
virtual Alignment alignment() const {
|
||||
return Alignment(3, 0);
|
||||
}
|
||||
virtual Alignment alignment() const { return Alignment(3, 0); }
|
||||
|
||||
virtual SectionChoice sectionChoice() const {
|
||||
return DefinedAtom::sectionBasedOnContent;
|
||||
}
|
||||
|
||||
virtual StringRef customSectionName() const {
|
||||
return StringRef();
|
||||
}
|
||||
virtual StringRef customSectionName() const { return StringRef(); }
|
||||
|
||||
virtual SectionPosition sectionPosition() const {
|
||||
return sectionPositionAny;
|
||||
}
|
||||
virtual SectionPosition sectionPosition() const { return sectionPositionAny; }
|
||||
|
||||
virtual DeadStripKind deadStrip() const {
|
||||
return DefinedAtom::deadStripNormal;
|
||||
}
|
||||
|
||||
virtual ContentPermissions permissions() const {
|
||||
virtual ContentPermissions permissions() const {
|
||||
return DefinedAtom::permRW_;
|
||||
}
|
||||
|
||||
virtual bool isAlias() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool isAlias() const { return false; }
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>();
|
||||
}
|
||||
virtual ArrayRef<uint8_t> rawContent() const { return ArrayRef<uint8_t>(); }
|
||||
|
||||
virtual reference_iterator begin() const {
|
||||
return reference_iterator(*this, nullptr);
|
||||
@@ -196,8 +142,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void incrementIterator(const void *&iter) const {
|
||||
}
|
||||
virtual void incrementIterator(const void *&iter) const {}
|
||||
|
||||
private:
|
||||
const File &_file;
|
||||
@@ -206,7 +151,7 @@ private:
|
||||
|
||||
class TestingPassFile : public MutableFile {
|
||||
public:
|
||||
TestingPassFile(const TargetInfo &ti) : MutableFile(ti, "Testing pass") {}
|
||||
TestingPassFile(const LinkingContext &ti) : MutableFile(ti, "Testing pass") {}
|
||||
|
||||
virtual void addAtom(const Atom &atom) {
|
||||
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&atom))
|
||||
@@ -216,10 +161,10 @@ public:
|
||||
}
|
||||
|
||||
virtual DefinedAtomRange definedAtoms() {
|
||||
return range<std::vector<const DefinedAtom*>::iterator>(
|
||||
_definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
|
||||
return range<std::vector<const DefinedAtom *>::iterator>(
|
||||
_definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
|
||||
}
|
||||
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
return _definedAtoms;
|
||||
}
|
||||
@@ -234,43 +179,37 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
|
||||
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
|
||||
};
|
||||
|
||||
struct TestingKindMapping {
|
||||
const char *string;
|
||||
int32_t value;
|
||||
bool isBranch;
|
||||
bool isGotLoad;
|
||||
bool isGotUse;
|
||||
const char *string;
|
||||
int32_t value;
|
||||
bool isBranch;
|
||||
bool isGotLoad;
|
||||
bool isGotUse;
|
||||
};
|
||||
|
||||
//
|
||||
// Table of fixup kinds in YAML documents used for testing
|
||||
//
|
||||
const TestingKindMapping sKinds[] = {
|
||||
{"in-group", -3, false, false, false},
|
||||
{"layout-after", -2, false, false, false},
|
||||
{"layout-before", -1, false, false, false},
|
||||
{"call32", 2, true, false, false},
|
||||
{"pcrel32", 3, false, false, false},
|
||||
{"gotLoad32", 7, false, true, true},
|
||||
{"gotUse32", 9, false, false, true},
|
||||
{"lea32wasGot", 8, false, false, false},
|
||||
{nullptr, 0, false, false, false}
|
||||
};
|
||||
{ "in-group", -3, false, false, false },
|
||||
{ "layout-after", -2, false, false, false },
|
||||
{ "layout-before", -1, false, false, false },
|
||||
{ "call32", 2, true, false, false }, { "pcrel32", 3, false, false, false },
|
||||
{ "gotLoad32", 7, false, true, true }, { "gotUse32", 9, false, false, true },
|
||||
{ "lea32wasGot", 8, false, false, false }, { nullptr, 0, false, false, false }
|
||||
};
|
||||
|
||||
class TestingStubsPass : public StubsPass {
|
||||
public:
|
||||
TestingStubsPass(const TargetInfo &ti) : _file(TestingPassFile(ti))
|
||||
{}
|
||||
TestingStubsPass(const LinkingContext &ti) : _file(TestingPassFile(ti)) {}
|
||||
|
||||
virtual bool noTextRelocs() {
|
||||
return true;
|
||||
}
|
||||
virtual bool noTextRelocs() { return true; }
|
||||
|
||||
virtual bool isCallSite(int32_t kind) {
|
||||
for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
|
||||
@@ -287,7 +226,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void addStubAtoms(MutableFile &mergedFile) {
|
||||
for (const DefinedAtom *stub : _file.defined() ) {
|
||||
for (const DefinedAtom *stub : _file.defined()) {
|
||||
mergedFile.addAtom(*stub);
|
||||
}
|
||||
}
|
||||
@@ -298,12 +237,9 @@ private:
|
||||
|
||||
class TestingGOTPass : public GOTPass {
|
||||
public:
|
||||
TestingGOTPass(const TargetInfo &ti) : _file(TestingPassFile(ti))
|
||||
{}
|
||||
TestingGOTPass(const LinkingContext &ti) : _file(TestingPassFile(ti)) {}
|
||||
|
||||
virtual bool noTextRelocs() {
|
||||
return true;
|
||||
}
|
||||
virtual bool noTextRelocs() { return true; }
|
||||
|
||||
virtual bool isGOTAccess(int32_t kind, bool &canBypassGOT) {
|
||||
for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
|
||||
@@ -317,9 +253,9 @@ public:
|
||||
|
||||
virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
|
||||
if (targetIsNowGOT)
|
||||
const_cast<Reference*>(ref)->setKind(3); // pcrel32
|
||||
const_cast<Reference *>(ref)->setKind(3); // pcrel32
|
||||
else
|
||||
const_cast<Reference*>(ref)->setKind(8); // lea32wasGot
|
||||
const_cast<Reference *>(ref)->setKind(8); // lea32wasGot
|
||||
}
|
||||
|
||||
virtual const DefinedAtom *makeGOTEntry(const Atom &target) {
|
||||
@@ -332,43 +268,41 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
CoreLinkingContext::CoreLinkingContext() {}
|
||||
|
||||
CoreTargetInfo::CoreTargetInfo() {
|
||||
}
|
||||
|
||||
bool CoreTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
bool CoreLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CoreTargetInfo::addPasses(PassManager &pm) const {
|
||||
void CoreLinkingContext::addPasses(PassManager &pm) const {
|
||||
for (StringRef name : _passNames) {
|
||||
if ( name.equals("layout") )
|
||||
if (name.equals("layout"))
|
||||
pm.add(std::unique_ptr<Pass>((new LayoutPass())));
|
||||
else if ( name.equals("GOT") )
|
||||
else if (name.equals("GOT"))
|
||||
pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
|
||||
else if ( name.equals("stubs") )
|
||||
else if (name.equals("stubs"))
|
||||
pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
|
||||
else
|
||||
llvm_unreachable("bad pass name");
|
||||
}
|
||||
}
|
||||
|
||||
error_code CoreTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
error_code CoreLinkingContext::parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
if (!_reader)
|
||||
_reader = createReaderYAML(*this);
|
||||
return _reader->parseFile(mb,result);
|
||||
return _reader->parseFile(mb, result);
|
||||
}
|
||||
|
||||
Writer &CoreTargetInfo::writer() const {
|
||||
Writer &CoreLinkingContext::writer() const {
|
||||
if (!_writer)
|
||||
_writer = createWriterYAML(*this);
|
||||
return *_writer;
|
||||
}
|
||||
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
CoreTargetInfo::relocKindFromString(StringRef str) const {
|
||||
ErrorOr<Reference::Kind>
|
||||
CoreLinkingContext::relocKindFromString(StringRef str) const {
|
||||
for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
|
||||
if (str.equals(p->string))
|
||||
return p->value;
|
||||
@@ -376,14 +310,11 @@ CoreTargetInfo::relocKindFromString(StringRef str) const {
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
|
||||
ErrorOr<std::string>
|
||||
CoreTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
ErrorOr<std::string>
|
||||
CoreLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
|
||||
if (kind == p->value)
|
||||
return std::string(p->string);
|
||||
}
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ public:
|
||||
if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC &&
|
||||
_symbol->st_shndx < llvm::ELF::SHN_HIPROC)) {
|
||||
if (!_targetAtomHandler) {
|
||||
const ELFTargetInfo &eti = (_owningFile.getTargetInfo());
|
||||
const ELFLinkingContext &eti = (_owningFile.getLinkingContext());
|
||||
TargetHandler<ELFT> &TargetHandler = eti.getTargetHandler<ELFT>();
|
||||
_targetAtomHandler = &TargetHandler.targetAtomHandler();
|
||||
}
|
||||
@@ -250,7 +250,7 @@ public:
|
||||
if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC &&
|
||||
_symbol->st_shndx < llvm::ELF::SHN_HIPROC)) {
|
||||
if (!_targetAtomHandler) {
|
||||
const ELFTargetInfo &eti = (_owningFile.getTargetInfo());
|
||||
const ELFLinkingContext &eti = (_owningFile.getLinkingContext());
|
||||
TargetHandler<ELFT> &TargetHandler = eti.getTargetHandler<ELFT>();
|
||||
_targetAtomHandler = &TargetHandler.targetAtomHandler();
|
||||
}
|
||||
@@ -277,7 +277,7 @@ public:
|
||||
((_symbol->st_shndx > llvm::ELF::SHN_LOPROC &&
|
||||
_symbol->st_shndx < llvm::ELF::SHN_HIPROC))) {
|
||||
if (!_targetAtomHandler) {
|
||||
const ELFTargetInfo &eti = (_owningFile.getTargetInfo());
|
||||
const ELFLinkingContext &eti = (_owningFile.getLinkingContext());
|
||||
TargetHandler<ELFT> &TargetHandler = eti.getTargetHandler<ELFT>();
|
||||
_targetAtomHandler = &TargetHandler.targetAtomHandler();
|
||||
}
|
||||
@@ -341,7 +341,7 @@ public:
|
||||
if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC &&
|
||||
_symbol->st_shndx < llvm::ELF::SHN_HIPROC)) {
|
||||
if (!_targetAtomHandler) {
|
||||
const ELFTargetInfo &eti = (_owningFile.getTargetInfo());
|
||||
const ELFLinkingContext &eti = (_owningFile.getLinkingContext());
|
||||
TargetHandler<ELFT> &TargetHandler = eti.getTargetHandler<ELFT>();
|
||||
_targetAtomHandler = &TargetHandler.targetAtomHandler();
|
||||
}
|
||||
@@ -391,7 +391,7 @@ public:
|
||||
if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC &&
|
||||
_symbol->st_shndx < llvm::ELF::SHN_HIPROC)) {
|
||||
if (!_targetAtomHandler) {
|
||||
const ELFTargetInfo &eti = (_owningFile.getTargetInfo());
|
||||
const ELFLinkingContext &eti = (_owningFile.getLinkingContext());
|
||||
TargetHandler<ELFT> &TargetHandler = eti.getTargetHandler<ELFT>();
|
||||
_targetAtomHandler = &TargetHandler.targetAtomHandler();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_lld_library(lldELF
|
||||
ELFTargetInfo.cpp
|
||||
ELFLinkingContext.cpp
|
||||
Reader.cpp
|
||||
Writer.cpp
|
||||
)
|
||||
@@ -7,10 +7,10 @@ add_lld_library(lldELF
|
||||
target_link_libraries(lldELF
|
||||
lldHexagonELFTarget
|
||||
lldPPCELFTarget
|
||||
lldReaderWriter
|
||||
lldX86_64ELFTarget
|
||||
lldX86ELFTarget
|
||||
lldPasses
|
||||
lldReaderWriter
|
||||
lldX86ELFTarget
|
||||
lldX86_64ELFTarget
|
||||
)
|
||||
|
||||
include_directories(.)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
|
||||
namespace lld {
|
||||
class ELFTargetInfo;
|
||||
class ELFLinkingContext;
|
||||
|
||||
namespace elf {
|
||||
class ELFWriter;
|
||||
@@ -51,9 +51,9 @@ public:
|
||||
CT_Tls,
|
||||
};
|
||||
|
||||
Chunk(StringRef name, Kind kind, const ELFTargetInfo &ti)
|
||||
Chunk(StringRef name, Kind kind, const ELFLinkingContext &context)
|
||||
: _name(name), _kind(kind), _fsize(0), _msize(0), _align2(0), _order(0),
|
||||
_ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) {}
|
||||
_ordinal(1), _start(0), _fileoffset(0), _context(context) {}
|
||||
virtual ~Chunk() {}
|
||||
// Does the chunk occupy disk space
|
||||
virtual bool occupiesNoDiskSpace() const { return false; }
|
||||
@@ -98,7 +98,7 @@ protected:
|
||||
uint64_t _ordinal;
|
||||
uint64_t _start;
|
||||
uint64_t _fileoffset;
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
const ELFLinkingContext &_context;
|
||||
};
|
||||
|
||||
} // end namespace elf
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
|
||||
typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
|
||||
|
||||
DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {}
|
||||
DefaultLayout(const ELFLinkingContext &context) : _context(context) {}
|
||||
|
||||
/// \brief Return the section order for a input section
|
||||
virtual SectionOrder getSectionOrder(StringRef name, int32_t contentType,
|
||||
@@ -261,7 +261,7 @@ public:
|
||||
RelocationTable<ELFT> *getDynamicRelocationTable() {
|
||||
if (!_dynamicRelocationTable) {
|
||||
_dynamicRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
|
||||
_targetInfo, ".rela.dyn", ORDER_DYNAMIC_RELOCS));
|
||||
_context, ".rela.dyn", ORDER_DYNAMIC_RELOCS));
|
||||
addSection(_dynamicRelocationTable.get());
|
||||
}
|
||||
return _dynamicRelocationTable.get();
|
||||
@@ -271,7 +271,7 @@ public:
|
||||
RelocationTable<ELFT> *getPLTRelocationTable() {
|
||||
if (!_pltRelocationTable) {
|
||||
_pltRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
|
||||
_targetInfo, ".rela.plt", ORDER_DYNAMIC_PLT_RELOCS));
|
||||
_context, ".rela.plt", ORDER_DYNAMIC_PLT_RELOCS));
|
||||
addSection(_pltRelocationTable.get());
|
||||
}
|
||||
return _pltRelocationTable.get();
|
||||
@@ -305,7 +305,7 @@ private:
|
||||
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _dynamicRelocationTable;
|
||||
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _pltRelocationTable;
|
||||
std::vector<lld::AtomLayout *> _absoluteAtoms;
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
const ELFLinkingContext &_context;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
@@ -473,8 +473,8 @@ template <class ELFT>
|
||||
AtomSection<ELFT> *DefaultLayout<ELFT>::createSection(
|
||||
StringRef sectionName, int32_t contentType,
|
||||
DefinedAtom::ContentPermissions permissions, SectionOrder sectionOrder) {
|
||||
return new (_allocator) AtomSection<ELFT>(
|
||||
_targetInfo, sectionName, contentType, permissions, sectionOrder);
|
||||
return new (_allocator) AtomSection<ELFT>(_context, sectionName, contentType,
|
||||
permissions, sectionOrder);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@@ -513,9 +513,9 @@ ErrorOr<const lld::AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom)
|
||||
getSection(sectionName, contentType, permissions);
|
||||
// Add runtime relocations to the .rela section.
|
||||
for (const auto &reloc : *definedAtom)
|
||||
if (_targetInfo.isDynamicRelocation(*definedAtom, *reloc))
|
||||
if (_context.isDynamicRelocation(*definedAtom, *reloc))
|
||||
getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
|
||||
else if (_targetInfo.isPLTRelocation(*definedAtom, *reloc))
|
||||
else if (_context.isPLTRelocation(*definedAtom, *reloc))
|
||||
getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
|
||||
return section->appendAtom(atom);
|
||||
} else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
|
||||
@@ -555,7 +555,7 @@ DefaultLayout<ELFT>::mergeSimiliarSections() {
|
||||
|
||||
template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
|
||||
ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
|
||||
ELFTargetInfo::OutputMagic outputMagic = _targetInfo.getOutputMagic();
|
||||
ELFLinkingContext::OutputMagic outputMagic = _context.getOutputMagic();
|
||||
// TODO: Do we want to give a chance for the targetHandlers
|
||||
// to sort segments in an arbitrary order ?
|
||||
// sort the sections by their order as defined by the layout
|
||||
@@ -609,8 +609,8 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
|
||||
if (!additionalSegmentInsert.second) {
|
||||
segment = additionalSegmentInsert.first->second;
|
||||
} else {
|
||||
segment = new (_allocator)
|
||||
Segment<ELFT>(_targetInfo, segmentName, segmentType);
|
||||
segment = new (_allocator) Segment<ELFT>(_context, segmentName,
|
||||
segmentType);
|
||||
additionalSegmentInsert.first->second = segment;
|
||||
_segments.push_back(segment);
|
||||
}
|
||||
@@ -620,8 +620,8 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
|
||||
// If the output magic is set to OutputMagic::NMAGIC or
|
||||
// OutputMagic::OMAGIC, Place the data alongside text in one single
|
||||
// segment
|
||||
if (outputMagic == ELFTargetInfo::OutputMagic::NMAGIC ||
|
||||
outputMagic == ELFTargetInfo::OutputMagic::OMAGIC)
|
||||
if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
|
||||
outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
|
||||
lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
|
||||
llvm::ELF::SHF_WRITE;
|
||||
|
||||
@@ -634,8 +634,8 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
|
||||
if (!segmentInsert.second) {
|
||||
segment = segmentInsert.first->second;
|
||||
} else {
|
||||
segment = new (_allocator)
|
||||
Segment<ELFT>(_targetInfo, "PT_LOAD", llvm::ELF::PT_LOAD);
|
||||
segment = new (_allocator) Segment<ELFT>(_context, "PT_LOAD",
|
||||
llvm::ELF::PT_LOAD);
|
||||
segmentInsert.first->second = segment;
|
||||
_segments.push_back(segment);
|
||||
}
|
||||
@@ -643,9 +643,9 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_targetInfo.isDynamic()) {
|
||||
if (_context.isDynamic()) {
|
||||
Segment<ELFT> *segment =
|
||||
new (_allocator) ProgramHeaderSegment<ELFT>(_targetInfo);
|
||||
new (_allocator) ProgramHeaderSegment<ELFT>(_context);
|
||||
_segments.push_back(segment);
|
||||
segment->append(_header);
|
||||
segment->append(_programHeader);
|
||||
@@ -676,8 +676,8 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
|
||||
if (_segments.empty())
|
||||
return;
|
||||
|
||||
uint64_t virtualAddress = _targetInfo.getBaseAddress();
|
||||
ELFTargetInfo::OutputMagic outputMagic = _targetInfo.getOutputMagic();
|
||||
uint64_t virtualAddress = _context.getBaseAddress();
|
||||
ELFLinkingContext::OutputMagic outputMagic = _context.getOutputMagic();
|
||||
|
||||
// HACK: This is a super dirty hack. The elf header and program header are
|
||||
// not part of a section, but we need them to be loaded at the base address
|
||||
@@ -710,10 +710,10 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
|
||||
continue;
|
||||
// Align the segment to a page boundary only if the output mode is
|
||||
// not OutputMagic::NMAGIC/OutputMagic::OMAGIC
|
||||
if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
|
||||
if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
|
||||
fileoffset =
|
||||
llvm::RoundUpToAlignment(fileoffset, _targetInfo.getPageSize());
|
||||
llvm::RoundUpToAlignment(fileoffset, _context.getPageSize());
|
||||
si->assignOffsets(fileoffset);
|
||||
fileoffset = si->fileOffset() + si->fileSize();
|
||||
}
|
||||
@@ -728,10 +728,10 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
|
||||
// first segment to the pagesize
|
||||
(*si)->assignVirtualAddress(address);
|
||||
(*si)->setMemSize(address - virtualAddress);
|
||||
if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
|
||||
if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
|
||||
virtualAddress =
|
||||
llvm::RoundUpToAlignment(address, _targetInfo.getPageSize());
|
||||
llvm::RoundUpToAlignment(address, _context.getPageSize());
|
||||
}
|
||||
_programHeader->resetProgramHeaders();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "DefaultLayout.h"
|
||||
#include "TargetHandler.h"
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
@@ -23,9 +23,8 @@ namespace elf {
|
||||
template <class ELFT>
|
||||
class DefaultTargetHandler : public TargetHandler<ELFT> {
|
||||
public:
|
||||
DefaultTargetHandler(ELFTargetInfo &targetInfo)
|
||||
: TargetHandler<ELFT>(targetInfo) {
|
||||
}
|
||||
DefaultTargetHandler(ELFLinkingContext &context)
|
||||
: TargetHandler<ELFT>(context) {}
|
||||
|
||||
bool doesOverrideHeader() { return false; }
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "Atoms.h"
|
||||
|
||||
#include "lld/Core/SharedLibraryFile.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
@@ -24,8 +24,8 @@ namespace lld {
|
||||
namespace elf {
|
||||
template <class ELFT> class DynamicFile LLVM_FINAL : public SharedLibraryFile {
|
||||
public:
|
||||
static ErrorOr<std::unique_ptr<DynamicFile> > create(
|
||||
const ELFTargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
static ErrorOr<std::unique_ptr<DynamicFile> >
|
||||
create(const ELFLinkingContext &ti, std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
std::unique_ptr<DynamicFile> file(
|
||||
new DynamicFile(ti, mb->getBufferIdentifier()));
|
||||
llvm::OwningPtr<llvm::object::Binary> binaryFile;
|
||||
@@ -110,15 +110,17 @@ public:
|
||||
*this, name, _soname, sym->second._symbol);
|
||||
}
|
||||
|
||||
virtual const ELFTargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const ELFLinkingContext &getLinkingContext() const {
|
||||
return _context;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicFile(const ELFTargetInfo &ti, StringRef name)
|
||||
: SharedLibraryFile(name), _targetInfo(ti) {}
|
||||
DynamicFile(const ELFLinkingContext &context, StringRef name)
|
||||
: SharedLibraryFile(name), _context(context) {}
|
||||
|
||||
mutable llvm::BumpPtrAllocator _alloc;
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
std::unique_ptr<llvm::object::ELFObjectFile<ELFT>> _objFile;
|
||||
const ELFLinkingContext &_context;
|
||||
std::unique_ptr<llvm::object::ELFObjectFile<ELFT> > _objFile;
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
|
||||
@@ -25,8 +25,8 @@ class DynamicLibraryWriter;
|
||||
template<class ELFT>
|
||||
class DynamicLibraryWriter : public OutputELFWriter<ELFT> {
|
||||
public:
|
||||
DynamicLibraryWriter(const ELFTargetInfo &ti):OutputELFWriter<ELFT>(ti)
|
||||
{}
|
||||
DynamicLibraryWriter(const ELFLinkingContext &context)
|
||||
: OutputELFWriter<ELFT>(context) {}
|
||||
|
||||
private:
|
||||
void buildDynamicSymbolTable(const File &file);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/ELFTargetInfo.cpp -----------------------------===//
|
||||
//===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "TargetHandler.h"
|
||||
#include "Targets.h"
|
||||
@@ -22,34 +22,28 @@
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
namespace lld {
|
||||
ELFTargetInfo::ELFTargetInfo(llvm::Triple triple,
|
||||
std::unique_ptr<TargetHandlerBase> targetHandler)
|
||||
: _outputFileType(elf::ET_EXEC),
|
||||
_triple(triple),
|
||||
_targetHandler(std::move(targetHandler)),
|
||||
_baseAddress(0),
|
||||
_isStaticExecutable(false),
|
||||
_outputYAML(false),
|
||||
_noInhibitExec(false),
|
||||
_mergeCommonStrings(false),
|
||||
_runLayoutPass(true),
|
||||
_useShlibUndefines(false),
|
||||
_dynamicLinkerArg(false),
|
||||
ELFLinkingContext::ELFLinkingContext(
|
||||
llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
|
||||
: _outputFileType(elf::ET_EXEC), _triple(triple),
|
||||
_targetHandler(std::move(targetHandler)), _baseAddress(0),
|
||||
_isStaticExecutable(false), _outputYAML(false), _noInhibitExec(false),
|
||||
_mergeCommonStrings(false), _runLayoutPass(true),
|
||||
_useShlibUndefines(false), _dynamicLinkerArg(false),
|
||||
_outputMagic(OutputMagic::DEFAULT) {}
|
||||
|
||||
bool ELFTargetInfo::is64Bits() const { return getTriple().isArch64Bit(); }
|
||||
bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); }
|
||||
|
||||
bool ELFTargetInfo::isLittleEndian() const {
|
||||
bool ELFLinkingContext::isLittleEndian() const {
|
||||
// TODO: Do this properly. It is not defined purely by arch.
|
||||
return true;
|
||||
}
|
||||
|
||||
void ELFTargetInfo::addPasses(PassManager &pm) const {
|
||||
void ELFLinkingContext::addPasses(PassManager &pm) const {
|
||||
if (_runLayoutPass)
|
||||
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
|
||||
}
|
||||
|
||||
uint16_t ELFTargetInfo::getOutputMachine() const {
|
||||
uint16_t ELFLinkingContext::getOutputMachine() const {
|
||||
switch (getTriple().getArch()) {
|
||||
case llvm::Triple::x86:
|
||||
return llvm::ELF::EM_386;
|
||||
@@ -64,9 +58,8 @@ uint16_t ELFTargetInfo::getOutputMachine() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool ELFTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
if (_outputFileType == elf::ET_EXEC &&
|
||||
_entrySymbolName.empty()) {
|
||||
bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
||||
if (_outputFileType == elf::ET_EXEC && _entrySymbolName.empty()) {
|
||||
_entrySymbolName = "_start";
|
||||
}
|
||||
|
||||
@@ -81,7 +74,7 @@ bool ELFTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ELFTargetInfo::isDynamic() const {
|
||||
bool ELFLinkingContext::isDynamic() const {
|
||||
switch (_outputFileType) {
|
||||
case llvm::ELF::ET_EXEC:
|
||||
return !_isStaticExecutable;
|
||||
@@ -91,11 +84,13 @@ bool ELFTargetInfo::isDynamic() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ELFTargetInfo::isRelativeReloc(const Reference &) const { return false; }
|
||||
bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code
|
||||
ELFTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const {
|
||||
error_code ELFLinkingContext::parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
ScopedTask task(getDefaultDomain(), "parseFile");
|
||||
error_code ec = _elfReader->parseFile(mb, result);
|
||||
if (!ec)
|
||||
@@ -113,29 +108,29 @@ ELFTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
return _linkerScriptReader->parseFile(mb, result);
|
||||
}
|
||||
|
||||
Writer &ELFTargetInfo::writer() const {
|
||||
return *_writer;
|
||||
}
|
||||
Writer &ELFLinkingContext::writer() const { return *_writer; }
|
||||
|
||||
|
||||
std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(llvm::Triple triple) {
|
||||
std::unique_ptr<ELFLinkingContext>
|
||||
ELFLinkingContext::create(llvm::Triple triple) {
|
||||
switch (triple.getArch()) {
|
||||
case llvm::Triple::x86:
|
||||
return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(triple));
|
||||
return std::unique_ptr<ELFLinkingContext>(
|
||||
new lld::elf::X86LinkingContext(triple));
|
||||
case llvm::Triple::x86_64:
|
||||
return std::unique_ptr<
|
||||
ELFTargetInfo>(new lld::elf::X86_64TargetInfo(triple));
|
||||
return std::unique_ptr<ELFLinkingContext>(
|
||||
new lld::elf::X86_64LinkingContext(triple));
|
||||
case llvm::Triple::hexagon:
|
||||
return std::unique_ptr<
|
||||
ELFTargetInfo>(new lld::elf::HexagonTargetInfo(triple));
|
||||
return std::unique_ptr<ELFLinkingContext>(
|
||||
new lld::elf::HexagonLinkingContext(triple));
|
||||
case llvm::Triple::ppc:
|
||||
return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(triple));
|
||||
return std::unique_ptr<ELFLinkingContext>(
|
||||
new lld::elf::PPCLinkingContext(triple));
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ELFTargetInfo::appendLibrary(StringRef libName) {
|
||||
bool ELFLinkingContext::appendLibrary(StringRef libName) {
|
||||
bool foundFile = false;
|
||||
StringRef pathref;
|
||||
for (StringRef dir : _inputSearchPaths) {
|
||||
@@ -29,8 +29,8 @@ namespace elf {
|
||||
template <class ELFT> class CRuntimeFile : public ELFFile<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
|
||||
CRuntimeFile(const ELFTargetInfo &ti, StringRef name = "C runtime")
|
||||
: ELFFile<ELFT>(ti, name) {}
|
||||
CRuntimeFile(const ELFLinkingContext &context, StringRef name = "C runtime")
|
||||
: ELFFile<ELFT>(context, name) {}
|
||||
|
||||
/// \brief add a global absolute atom
|
||||
virtual void addAbsoluteAtom(StringRef symbolName) {
|
||||
|
||||
@@ -25,9 +25,8 @@ class ExecutableWriter;
|
||||
template<class ELFT>
|
||||
class ExecutableWriter : public OutputELFWriter<ELFT> {
|
||||
public:
|
||||
ExecutableWriter(const ELFTargetInfo &ti)
|
||||
: OutputELFWriter<ELFT>(ti), _runtimeFile(ti)
|
||||
{}
|
||||
ExecutableWriter(const ELFLinkingContext &context)
|
||||
: OutputELFWriter<ELFT>(context), _runtimeFile(context) {}
|
||||
|
||||
private:
|
||||
virtual void addDefaultAtoms();
|
||||
@@ -46,7 +45,7 @@ private:
|
||||
/// absolute symbols
|
||||
template<class ELFT>
|
||||
void ExecutableWriter<ELFT>::addDefaultAtoms() {
|
||||
_runtimeFile.addUndefinedAtom(this->_targetInfo.entrySymbolName());
|
||||
_runtimeFile.addUndefinedAtom(this->_context.entrySymbolName());
|
||||
_runtimeFile.addAbsoluteAtom("__bss_start");
|
||||
_runtimeFile.addAbsoluteAtom("__bss_end");
|
||||
_runtimeFile.addAbsoluteAtom("_end");
|
||||
@@ -75,10 +74,10 @@ void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
|
||||
|
||||
template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
|
||||
OutputELFWriter<ELFT>::createDefaultSections();
|
||||
if (this->_targetInfo.isDynamic()) {
|
||||
if (this->_context.isDynamic()) {
|
||||
_interpSection.reset(new (this->_alloc) InterpSection<ELFT>(
|
||||
this->_targetInfo, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
|
||||
this->_targetInfo.getInterpreter()));
|
||||
this->_context, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
|
||||
this->_context.getInterpreter()));
|
||||
this->_layout->addSection(_interpSection.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/ReaderArchive.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -117,13 +117,13 @@ template <class ELFT> class ELFFile : public File {
|
||||
typedef typename MergedSectionMapT::iterator MergedSectionMapIterT;
|
||||
|
||||
public:
|
||||
ELFFile(const ELFTargetInfo &ti, StringRef name)
|
||||
: File(name, kindObject), _elfTargetInfo(ti) {}
|
||||
ELFFile(const ELFLinkingContext &context, StringRef name)
|
||||
: File(name, kindObject), _elfLinkingContext(context) {}
|
||||
|
||||
ELFFile(const ELFTargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> MB,
|
||||
llvm::error_code &EC)
|
||||
: File(MB->getBufferIdentifier(), kindObject), _elfTargetInfo(ti),
|
||||
_ordinal(0), _doStringsMerge(false) {
|
||||
ELFFile(const ELFLinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
|
||||
: File(MB->getBufferIdentifier(), kindObject),
|
||||
_elfLinkingContext(context), _ordinal(0), _doStringsMerge(false) {
|
||||
llvm::OwningPtr<llvm::object::Binary> binaryFile;
|
||||
EC = createBinary(MB.release(), binaryFile);
|
||||
if (EC)
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
|
||||
binaryFile.take();
|
||||
|
||||
_doStringsMerge = _elfTargetInfo.mergeCommonStrings();
|
||||
_doStringsMerge = _elfLinkingContext.mergeCommonStrings();
|
||||
|
||||
// Read input sections from the input file that need to be converted to
|
||||
// atoms
|
||||
@@ -487,7 +487,9 @@ public:
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
|
||||
virtual const ELFTargetInfo &getTargetInfo() const { return _elfTargetInfo; }
|
||||
virtual const ELFLinkingContext &getLinkingContext() const {
|
||||
return _elfLinkingContext;
|
||||
}
|
||||
|
||||
Atom *findAtom(const Elf_Sym *symbol) {
|
||||
return _symbolToAtomMapping.lookup(symbol);
|
||||
@@ -552,7 +554,8 @@ private:
|
||||
void updateReferences() {
|
||||
/// cached value of target relocation handler
|
||||
const TargetRelocationHandler<ELFT> &_targetRelocationHandler =
|
||||
_elfTargetInfo.template getTargetHandler<ELFT>().getRelocationHandler();
|
||||
_elfLinkingContext.template getTargetHandler<ELFT>()
|
||||
.getRelocationHandler();
|
||||
|
||||
for (auto &ri : _references) {
|
||||
if (ri->kind() >= lld::Reference::kindTargetLow) {
|
||||
@@ -667,7 +670,7 @@ private:
|
||||
// not. Let the TargetHandler to make a decision if that's the case.
|
||||
if (isTargetSpecificAtom(section, symbol)) {
|
||||
TargetHandler<ELFT> &targetHandler =
|
||||
_elfTargetInfo.template getTargetHandler<ELFT>();
|
||||
_elfLinkingContext.template getTargetHandler<ELFT>();
|
||||
TargetAtomHandler<ELFT> &targetAtomHandler =
|
||||
targetHandler.targetAtomHandler();
|
||||
return targetAtomHandler.getType(symbol) == llvm::ELF::STT_COMMON;
|
||||
@@ -716,7 +719,7 @@ private:
|
||||
_relocationReferences;
|
||||
std::vector<ELFReference<ELFT> *> _references;
|
||||
llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
|
||||
const ELFTargetInfo &_elfTargetInfo;
|
||||
const ELFLinkingContext &_elfLinkingContext;
|
||||
|
||||
/// \brief Atoms that are created for a section that has the merge property
|
||||
/// set
|
||||
|
||||
@@ -29,7 +29,7 @@ class Header : public Chunk<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
|
||||
|
||||
Header(const ELFTargetInfo &);
|
||||
Header(const ELFLinkingContext &);
|
||||
|
||||
void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
|
||||
void e_type(uint16_t type) { _eh.e_type = type; }
|
||||
@@ -66,8 +66,8 @@ private:
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
Header<ELFT>::Header(const ELFTargetInfo &ti)
|
||||
: Chunk<ELFT>("elfhdr", Chunk<ELFT>::K_Header, ti) {
|
||||
Header<ELFT>::Header(const ELFLinkingContext &context)
|
||||
: Chunk<ELFT>("elfhdr", Chunk<ELFT>::K_Header, context) {
|
||||
this->_align2 = ELFT::Is64Bits ? 8 : 4;
|
||||
this->_fsize = sizeof(Elf_Ehdr);
|
||||
this->_msize = sizeof(Elf_Ehdr);
|
||||
@@ -117,8 +117,8 @@ public:
|
||||
uint64_t _flagsClear;
|
||||
};
|
||||
|
||||
ProgramHeader(const ELFTargetInfo &ti)
|
||||
: Chunk<ELFT>("elfphdr", Chunk<ELFT>::K_ProgramHeader, ti) {
|
||||
ProgramHeader(const ELFLinkingContext &context)
|
||||
: Chunk<ELFT>("elfphdr", Chunk<ELFT>::K_ProgramHeader, context) {
|
||||
this->_align2 = ELFT::Is64Bits ? 8 : 4;
|
||||
resetProgramHeaders();
|
||||
}
|
||||
@@ -193,7 +193,7 @@ private:
|
||||
template <class ELFT>
|
||||
bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
|
||||
bool allocatedNew = false;
|
||||
ELFTargetInfo::OutputMagic outputMagic = this->_targetInfo.getOutputMagic();
|
||||
ELFLinkingContext::OutputMagic outputMagic = this->_context.getOutputMagic();
|
||||
// For segments that are not a loadable segment, we
|
||||
// just pick the values directly from the segment as there
|
||||
// wouldnt be any slices within that
|
||||
@@ -222,8 +222,8 @@ bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
|
||||
phdr->p_filesz = slice->fileSize();
|
||||
phdr->p_memsz = slice->memSize();
|
||||
phdr->p_flags = segment->flags();
|
||||
if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
|
||||
if (outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
|
||||
outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
|
||||
phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ? segment->pageSize()
|
||||
: slice->align2();
|
||||
else
|
||||
@@ -253,7 +253,7 @@ class SectionHeader : public Chunk<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
|
||||
|
||||
SectionHeader(const ELFTargetInfo &, int32_t order);
|
||||
SectionHeader(const ELFLinkingContext &, int32_t order);
|
||||
|
||||
void appendSection(MergedSections<ELFT> *section);
|
||||
|
||||
@@ -294,8 +294,9 @@ private:
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
SectionHeader<ELFT>::SectionHeader(const ELFTargetInfo &ti, int32_t order)
|
||||
: Chunk<ELFT>("shdr", Chunk<ELFT>::K_SectionHeader, ti) {
|
||||
SectionHeader<ELFT>::SectionHeader(const ELFLinkingContext &context,
|
||||
int32_t order)
|
||||
: Chunk<ELFT>("shdr", Chunk<ELFT>::K_SectionHeader, context) {
|
||||
this->_fsize = 0;
|
||||
this->_align2 = 8;
|
||||
this->setOrder(order);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
add_lld_library(lldHexagonELFTarget
|
||||
HexagonTargetHandler.cpp
|
||||
HexagonTargetInfo.cpp
|
||||
HexagonLinkingContext.cpp
|
||||
HexagonRelocationHandler.cpp
|
||||
HexagonTargetHandler.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lldHexagonELFTarget
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 4, false> HexagonELFType;
|
||||
class HexagonTargetInfo;
|
||||
class HexagonLinkingContext;
|
||||
|
||||
template <class HexagonELFType> class HexagonRuntimeFile
|
||||
: public CRuntimeFile<HexagonELFType> {
|
||||
public:
|
||||
HexagonRuntimeFile(const HexagonTargetInfo &hti)
|
||||
:CRuntimeFile<HexagonELFType>(hti, "Hexagon runtime file")
|
||||
{}
|
||||
|
||||
HexagonRuntimeFile(const HexagonLinkingContext &context)
|
||||
: CRuntimeFile<HexagonELFType>(context, "Hexagon runtime file") {}
|
||||
};
|
||||
} // elf
|
||||
} // lld
|
||||
|
||||
170
lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
Normal file
170
lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
//===- lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp -------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonLinkingContext.h"
|
||||
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/ReaderWriter/Simple.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
elf::HexagonLinkingContext::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str) LLD_CASE(R_HEX_NONE)
|
||||
LLD_CASE(R_HEX_B22_PCREL) LLD_CASE(R_HEX_B15_PCREL)
|
||||
LLD_CASE(R_HEX_B7_PCREL) LLD_CASE(R_HEX_LO16) LLD_CASE(R_HEX_HI16)
|
||||
LLD_CASE(R_HEX_32) LLD_CASE(R_HEX_16) LLD_CASE(R_HEX_8)
|
||||
LLD_CASE(R_HEX_GPREL16_0) LLD_CASE(R_HEX_GPREL16_1)
|
||||
LLD_CASE(R_HEX_GPREL16_2) LLD_CASE(R_HEX_GPREL16_3) LLD_CASE(R_HEX_HL16)
|
||||
LLD_CASE(R_HEX_B13_PCREL) LLD_CASE(R_HEX_B9_PCREL)
|
||||
LLD_CASE(R_HEX_B32_PCREL_X) LLD_CASE(R_HEX_32_6_X)
|
||||
LLD_CASE(R_HEX_B22_PCREL_X) LLD_CASE(R_HEX_B15_PCREL_X)
|
||||
LLD_CASE(R_HEX_B13_PCREL_X) LLD_CASE(R_HEX_B9_PCREL_X)
|
||||
LLD_CASE(R_HEX_B7_PCREL_X) LLD_CASE(R_HEX_16_X) LLD_CASE(R_HEX_12_X)
|
||||
LLD_CASE(R_HEX_11_X) LLD_CASE(R_HEX_10_X) LLD_CASE(R_HEX_9_X)
|
||||
LLD_CASE(R_HEX_8_X) LLD_CASE(R_HEX_7_X) LLD_CASE(R_HEX_6_X)
|
||||
LLD_CASE(R_HEX_32_PCREL) LLD_CASE(R_HEX_COPY) LLD_CASE(R_HEX_GLOB_DAT)
|
||||
LLD_CASE(R_HEX_JMP_SLOT) LLD_CASE(R_HEX_RELATIVE)
|
||||
LLD_CASE(R_HEX_PLT_B22_PCREL) LLD_CASE(R_HEX_GOTREL_LO16)
|
||||
LLD_CASE(R_HEX_GOTREL_HI16) LLD_CASE(R_HEX_GOTREL_32)
|
||||
LLD_CASE(R_HEX_GOT_LO16) LLD_CASE(R_HEX_GOT_HI16) LLD_CASE(R_HEX_GOT_32)
|
||||
LLD_CASE(R_HEX_GOT_16) LLD_CASE(R_HEX_DTPMOD_32)
|
||||
LLD_CASE(R_HEX_DTPREL_LO16) LLD_CASE(R_HEX_DTPREL_HI16)
|
||||
LLD_CASE(R_HEX_DTPREL_32) LLD_CASE(R_HEX_DTPREL_16)
|
||||
LLD_CASE(R_HEX_GD_PLT_B22_PCREL) LLD_CASE(R_HEX_GD_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GD_GOT_HI16) LLD_CASE(R_HEX_GD_GOT_32)
|
||||
LLD_CASE(R_HEX_GD_GOT_16) LLD_CASE(R_HEX_IE_LO16) LLD_CASE(R_HEX_IE_HI16)
|
||||
LLD_CASE(R_HEX_IE_32) LLD_CASE(R_HEX_IE_GOT_LO16)
|
||||
LLD_CASE(R_HEX_IE_GOT_HI16) LLD_CASE(R_HEX_IE_GOT_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_16) LLD_CASE(R_HEX_TPREL_LO16)
|
||||
LLD_CASE(R_HEX_TPREL_HI16) LLD_CASE(R_HEX_TPREL_32)
|
||||
LLD_CASE(R_HEX_TPREL_16) LLD_CASE(R_HEX_6_PCREL_X)
|
||||
LLD_CASE(R_HEX_GOTREL_32_6_X) LLD_CASE(R_HEX_GOTREL_16_X)
|
||||
LLD_CASE(R_HEX_GOTREL_11_X) LLD_CASE(R_HEX_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GOT_16_X) LLD_CASE(R_HEX_GOT_11_X)
|
||||
LLD_CASE(R_HEX_DTPREL_32_6_X) LLD_CASE(R_HEX_DTPREL_16_X)
|
||||
LLD_CASE(R_HEX_DTPREL_11_X) LLD_CASE(R_HEX_GD_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_16_X) LLD_CASE(R_HEX_GD_GOT_11_X)
|
||||
LLD_CASE(R_HEX_IE_32_6_X) LLD_CASE(R_HEX_IE_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_32_6_X) LLD_CASE(R_HEX_IE_GOT_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_11_X) LLD_CASE(R_HEX_TPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_TPREL_16_X) LLD_CASE(R_HEX_TPREL_11_X).Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) \
|
||||
case llvm::ELF::name: \
|
||||
return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::HexagonLinkingContext::stringFromRelocKind(int32_t kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_HEX_NONE)
|
||||
LLD_CASE(R_HEX_B22_PCREL)
|
||||
LLD_CASE(R_HEX_B15_PCREL)
|
||||
LLD_CASE(R_HEX_B7_PCREL)
|
||||
LLD_CASE(R_HEX_LO16)
|
||||
LLD_CASE(R_HEX_HI16)
|
||||
LLD_CASE(R_HEX_32)
|
||||
LLD_CASE(R_HEX_16)
|
||||
LLD_CASE(R_HEX_8)
|
||||
LLD_CASE(R_HEX_GPREL16_0)
|
||||
LLD_CASE(R_HEX_GPREL16_1)
|
||||
LLD_CASE(R_HEX_GPREL16_2)
|
||||
LLD_CASE(R_HEX_GPREL16_3)
|
||||
LLD_CASE(R_HEX_HL16)
|
||||
LLD_CASE(R_HEX_B13_PCREL)
|
||||
LLD_CASE(R_HEX_B9_PCREL)
|
||||
LLD_CASE(R_HEX_B32_PCREL_X)
|
||||
LLD_CASE(R_HEX_32_6_X)
|
||||
LLD_CASE(R_HEX_B22_PCREL_X)
|
||||
LLD_CASE(R_HEX_B15_PCREL_X)
|
||||
LLD_CASE(R_HEX_B13_PCREL_X)
|
||||
LLD_CASE(R_HEX_B9_PCREL_X)
|
||||
LLD_CASE(R_HEX_B7_PCREL_X)
|
||||
LLD_CASE(R_HEX_16_X)
|
||||
LLD_CASE(R_HEX_12_X)
|
||||
LLD_CASE(R_HEX_11_X)
|
||||
LLD_CASE(R_HEX_10_X)
|
||||
LLD_CASE(R_HEX_9_X)
|
||||
LLD_CASE(R_HEX_8_X)
|
||||
LLD_CASE(R_HEX_7_X)
|
||||
LLD_CASE(R_HEX_6_X)
|
||||
LLD_CASE(R_HEX_32_PCREL)
|
||||
LLD_CASE(R_HEX_COPY)
|
||||
LLD_CASE(R_HEX_GLOB_DAT)
|
||||
LLD_CASE(R_HEX_JMP_SLOT)
|
||||
LLD_CASE(R_HEX_RELATIVE)
|
||||
LLD_CASE(R_HEX_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GOTREL_LO16)
|
||||
LLD_CASE(R_HEX_GOTREL_HI16)
|
||||
LLD_CASE(R_HEX_GOTREL_32)
|
||||
LLD_CASE(R_HEX_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GOT_32)
|
||||
LLD_CASE(R_HEX_GOT_16)
|
||||
LLD_CASE(R_HEX_DTPMOD_32)
|
||||
LLD_CASE(R_HEX_DTPREL_LO16)
|
||||
LLD_CASE(R_HEX_DTPREL_HI16)
|
||||
LLD_CASE(R_HEX_DTPREL_32)
|
||||
LLD_CASE(R_HEX_DTPREL_16)
|
||||
LLD_CASE(R_HEX_GD_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GD_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GD_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GD_GOT_32)
|
||||
LLD_CASE(R_HEX_GD_GOT_16)
|
||||
LLD_CASE(R_HEX_IE_LO16)
|
||||
LLD_CASE(R_HEX_IE_HI16)
|
||||
LLD_CASE(R_HEX_IE_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_LO16)
|
||||
LLD_CASE(R_HEX_IE_GOT_HI16)
|
||||
LLD_CASE(R_HEX_IE_GOT_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_16)
|
||||
LLD_CASE(R_HEX_TPREL_LO16)
|
||||
LLD_CASE(R_HEX_TPREL_HI16)
|
||||
LLD_CASE(R_HEX_TPREL_32)
|
||||
LLD_CASE(R_HEX_TPREL_16)
|
||||
LLD_CASE(R_HEX_6_PCREL_X)
|
||||
LLD_CASE(R_HEX_GOTREL_32_6_X)
|
||||
LLD_CASE(R_HEX_GOTREL_16_X)
|
||||
LLD_CASE(R_HEX_GOTREL_11_X)
|
||||
LLD_CASE(R_HEX_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GOT_11_X)
|
||||
LLD_CASE(R_HEX_DTPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_DTPREL_16_X)
|
||||
LLD_CASE(R_HEX_DTPREL_11_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_11_X)
|
||||
LLD_CASE(R_HEX_IE_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_11_X)
|
||||
LLD_CASE(R_HEX_TPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_TPREL_16_X)
|
||||
LLD_CASE(R_HEX_TPREL_11_X)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h -------------------===//
|
||||
//===- lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h ---------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "HexagonTargetHandler.h"
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
@@ -20,11 +20,11 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
class HexagonTargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
class HexagonLinkingContext LLVM_FINAL : public ELFLinkingContext {
|
||||
public:
|
||||
HexagonTargetInfo(llvm::Triple triple)
|
||||
: ELFTargetInfo(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new HexagonTargetHandler(*this))) {}
|
||||
HexagonLinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new HexagonTargetHandler(*this))) {}
|
||||
|
||||
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
|
||||
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
|
||||
virtual bool isDynamicRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
switch (r.kind()){
|
||||
switch (r.kind()) {
|
||||
case llvm::ELF::R_HEX_RELATIVE:
|
||||
case llvm::ELF::R_HEX_GLOB_DAT:
|
||||
return true;
|
||||
@@ -42,9 +42,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isPLTRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
switch (r.kind()){
|
||||
virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const {
|
||||
switch (r.kind()) {
|
||||
case llvm::ELF::R_HEX_JMP_SLOT:
|
||||
return true;
|
||||
default:
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonTargetHandler.h"
|
||||
#include "HexagonTargetInfo.h"
|
||||
#include "HexagonLinkingContext.h"
|
||||
#include "HexagonRelocationHandler.h"
|
||||
#include "HexagonRelocationFunctions.h"
|
||||
|
||||
@@ -343,9 +343,9 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation(
|
||||
default : {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
auto name = _targetInfo.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: "
|
||||
<< (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")";
|
||||
auto name = _context.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: " << (name ? *name : "<unknown>") << " ("
|
||||
<< ref.kind() << ")";
|
||||
s.flush();
|
||||
llvm_unreachable(str.c_str());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 4, false> HexagonELFType;
|
||||
|
||||
class HexagonTargetInfo;
|
||||
class HexagonLinkingContext;
|
||||
class HexagonTargetHandler;
|
||||
template <class HexagonELFType> class HexagonTargetLayout;
|
||||
|
||||
@@ -25,15 +25,15 @@ class HexagonTargetRelocationHandler LLVM_FINAL :
|
||||
public TargetRelocationHandler<HexagonELFType> {
|
||||
public:
|
||||
HexagonTargetRelocationHandler(
|
||||
const HexagonTargetInfo &ti, const HexagonTargetHandler &tH,
|
||||
const HexagonLinkingContext &context, const HexagonTargetHandler &tH,
|
||||
const HexagonTargetLayout<HexagonELFType> &layout)
|
||||
: _targetInfo(ti), _targetHandler(tH), _targetLayout(layout) {}
|
||||
: _context(context), _targetHandler(tH), _targetLayout(layout) {}
|
||||
|
||||
virtual ErrorOr<void>
|
||||
applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &, const Reference &) const;
|
||||
private:
|
||||
const HexagonTargetInfo &_targetInfo;
|
||||
const HexagonLinkingContext &_context;
|
||||
const HexagonTargetHandler &_targetHandler;
|
||||
const HexagonTargetLayout<HexagonELFType> &_targetLayout;
|
||||
};
|
||||
|
||||
@@ -15,15 +15,15 @@ namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 4, false> HexagonELFType;
|
||||
template <typename ELFT> class HexagonTargetLayout;
|
||||
class HexagonTargetInfo;
|
||||
class HexagonLinkingContext;
|
||||
|
||||
/// \brief Handle Hexagon SData section
|
||||
template <class HexagonELFType>
|
||||
class SDataSection : public AtomSection<HexagonELFType> {
|
||||
public:
|
||||
SDataSection(const HexagonTargetInfo &hti)
|
||||
SDataSection(const HexagonLinkingContext &context)
|
||||
: AtomSection<HexagonELFType>(
|
||||
hti, ".sdata", DefinedAtom::typeDataFast, 0,
|
||||
context, ".sdata", DefinedAtom::typeDataFast, 0,
|
||||
HexagonTargetLayout<HexagonELFType>::ORDER_SDATA) {
|
||||
this->_type = SHT_PROGBITS;
|
||||
this->_flags = SHF_ALLOC | SHF_WRITE;
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonTargetInfo.h"
|
||||
#include "HexagonLinkingContext.h"
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonTargetHandler.h"
|
||||
#include "HexagonTargetInfo.h"
|
||||
#include "HexagonLinkingContext.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
|
||||
using namespace llvm::ELF;
|
||||
|
||||
HexagonTargetHandler::HexagonTargetHandler(HexagonTargetInfo &targetInfo)
|
||||
: DefaultTargetHandler(targetInfo), _targetLayout(targetInfo),
|
||||
_relocationHandler(targetInfo, *this, _targetLayout),
|
||||
_hexagonRuntimeFile(targetInfo) {}
|
||||
HexagonTargetHandler::HexagonTargetHandler(HexagonLinkingContext &context)
|
||||
: DefaultTargetHandler(context), _targetLayout(context),
|
||||
_relocationHandler(context, *this, _targetLayout),
|
||||
_hexagonRuntimeFile(context) {}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
|
||||
class ELFPassFile : public SimpleFile {
|
||||
public:
|
||||
ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {}
|
||||
ELFPassFile(const ELFLinkingContext &eti) : SimpleFile(eti, "ELFPassFile") {}
|
||||
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
@@ -144,7 +144,7 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
GOTPLTPass(const ELFTargetInfo &ti)
|
||||
GOTPLTPass(const ELFLinkingContext &ti)
|
||||
: _file(ti), _null(nullptr), _PLT0(nullptr), _got0(nullptr) {}
|
||||
|
||||
/// \brief Do the pass.
|
||||
@@ -212,7 +212,7 @@ protected:
|
||||
|
||||
class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> {
|
||||
public:
|
||||
DynamicGOTPLTPass(const elf::HexagonTargetInfo &ti) : GOTPLTPass(ti) {
|
||||
DynamicGOTPLTPass(const elf::HexagonLinkingContext &ti) : GOTPLTPass(ti) {
|
||||
_got0 = new (_file._alloc) HexagonGOTPLT0Atom(_file);
|
||||
#ifndef NDEBUG
|
||||
_got0->_name = "__got0";
|
||||
@@ -291,8 +291,8 @@ public:
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void elf::HexagonTargetInfo::addPasses(PassManager &pm) const {
|
||||
void elf::HexagonLinkingContext::addPasses(PassManager &pm) const {
|
||||
if (isDynamic())
|
||||
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
|
||||
ELFTargetInfo::addPasses(pm);
|
||||
ELFLinkingContext::addPasses(pm);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 4, false> HexagonELFType;
|
||||
class HexagonTargetInfo;
|
||||
|
||||
class HexagonLinkingContext;
|
||||
|
||||
/// \brief Handle Hexagon specific Atoms
|
||||
template <class HexagonELFType>
|
||||
@@ -85,7 +84,7 @@ public:
|
||||
ORDER_SDATA = 205
|
||||
};
|
||||
|
||||
HexagonTargetLayout(const HexagonTargetInfo &hti)
|
||||
HexagonTargetLayout(const HexagonLinkingContext &hti)
|
||||
: TargetLayout<HexagonELFType>(hti), _sdataSection(nullptr) {
|
||||
_sdataSection = new (_alloc) SDataSection<HexagonELFType>(hti);
|
||||
}
|
||||
@@ -145,7 +144,7 @@ private:
|
||||
class HexagonTargetHandler LLVM_FINAL :
|
||||
public DefaultTargetHandler<HexagonELFType> {
|
||||
public:
|
||||
HexagonTargetHandler(HexagonTargetInfo &targetInfo);
|
||||
HexagonTargetHandler(HexagonLinkingContext &targetInfo);
|
||||
|
||||
bool doesOverrideHeader() { return true; }
|
||||
|
||||
@@ -170,7 +169,7 @@ public:
|
||||
|
||||
void addDefaultAtoms() {
|
||||
_hexagonRuntimeFile.addAbsoluteAtom("_SDA_BASE_");
|
||||
if (_targetInfo.isDynamic()) {
|
||||
if (_context.isDynamic()) {
|
||||
_hexagonRuntimeFile.addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
|
||||
_hexagonRuntimeFile.addAbsoluteAtom("_DYNAMIC");
|
||||
}
|
||||
@@ -185,7 +184,7 @@ public:
|
||||
auto sdabaseAtomIter = _targetLayout.findAbsoluteAtom("_SDA_BASE_");
|
||||
(*sdabaseAtomIter)->_virtualAddr =
|
||||
_targetLayout.getSDataSection()->virtualAddr();
|
||||
if (_targetInfo.isDynamic()) {
|
||||
if (_context.isDynamic()) {
|
||||
auto gotAtomIter =
|
||||
_targetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
|
||||
_gotSymAtom = (*gotAtomIter);
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp -----------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonTargetInfo.h"
|
||||
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/ReaderWriter/Simple.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
elf::HexagonTargetInfo::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str)
|
||||
LLD_CASE(R_HEX_NONE)
|
||||
LLD_CASE(R_HEX_B22_PCREL)
|
||||
LLD_CASE(R_HEX_B15_PCREL)
|
||||
LLD_CASE(R_HEX_B7_PCREL)
|
||||
LLD_CASE(R_HEX_LO16)
|
||||
LLD_CASE(R_HEX_HI16)
|
||||
LLD_CASE(R_HEX_32)
|
||||
LLD_CASE(R_HEX_16)
|
||||
LLD_CASE(R_HEX_8)
|
||||
LLD_CASE(R_HEX_GPREL16_0)
|
||||
LLD_CASE(R_HEX_GPREL16_1)
|
||||
LLD_CASE(R_HEX_GPREL16_2)
|
||||
LLD_CASE(R_HEX_GPREL16_3)
|
||||
LLD_CASE(R_HEX_HL16)
|
||||
LLD_CASE(R_HEX_B13_PCREL)
|
||||
LLD_CASE(R_HEX_B9_PCREL)
|
||||
LLD_CASE(R_HEX_B32_PCREL_X)
|
||||
LLD_CASE(R_HEX_32_6_X)
|
||||
LLD_CASE(R_HEX_B22_PCREL_X)
|
||||
LLD_CASE(R_HEX_B15_PCREL_X)
|
||||
LLD_CASE(R_HEX_B13_PCREL_X)
|
||||
LLD_CASE(R_HEX_B9_PCREL_X)
|
||||
LLD_CASE(R_HEX_B7_PCREL_X)
|
||||
LLD_CASE(R_HEX_16_X)
|
||||
LLD_CASE(R_HEX_12_X)
|
||||
LLD_CASE(R_HEX_11_X)
|
||||
LLD_CASE(R_HEX_10_X)
|
||||
LLD_CASE(R_HEX_9_X)
|
||||
LLD_CASE(R_HEX_8_X)
|
||||
LLD_CASE(R_HEX_7_X)
|
||||
LLD_CASE(R_HEX_6_X)
|
||||
LLD_CASE(R_HEX_32_PCREL)
|
||||
LLD_CASE(R_HEX_COPY)
|
||||
LLD_CASE(R_HEX_GLOB_DAT)
|
||||
LLD_CASE(R_HEX_JMP_SLOT)
|
||||
LLD_CASE(R_HEX_RELATIVE)
|
||||
LLD_CASE(R_HEX_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GOTREL_LO16)
|
||||
LLD_CASE(R_HEX_GOTREL_HI16)
|
||||
LLD_CASE(R_HEX_GOTREL_32)
|
||||
LLD_CASE(R_HEX_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GOT_32)
|
||||
LLD_CASE(R_HEX_GOT_16)
|
||||
LLD_CASE(R_HEX_DTPMOD_32)
|
||||
LLD_CASE(R_HEX_DTPREL_LO16)
|
||||
LLD_CASE(R_HEX_DTPREL_HI16)
|
||||
LLD_CASE(R_HEX_DTPREL_32)
|
||||
LLD_CASE(R_HEX_DTPREL_16)
|
||||
LLD_CASE(R_HEX_GD_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GD_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GD_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GD_GOT_32)
|
||||
LLD_CASE(R_HEX_GD_GOT_16)
|
||||
LLD_CASE(R_HEX_IE_LO16)
|
||||
LLD_CASE(R_HEX_IE_HI16)
|
||||
LLD_CASE(R_HEX_IE_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_LO16)
|
||||
LLD_CASE(R_HEX_IE_GOT_HI16)
|
||||
LLD_CASE(R_HEX_IE_GOT_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_16)
|
||||
LLD_CASE(R_HEX_TPREL_LO16)
|
||||
LLD_CASE(R_HEX_TPREL_HI16)
|
||||
LLD_CASE(R_HEX_TPREL_32)
|
||||
LLD_CASE(R_HEX_TPREL_16)
|
||||
LLD_CASE(R_HEX_6_PCREL_X)
|
||||
LLD_CASE(R_HEX_GOTREL_32_6_X)
|
||||
LLD_CASE(R_HEX_GOTREL_16_X)
|
||||
LLD_CASE(R_HEX_GOTREL_11_X)
|
||||
LLD_CASE(R_HEX_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GOT_11_X)
|
||||
LLD_CASE(R_HEX_DTPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_DTPREL_16_X)
|
||||
LLD_CASE(R_HEX_DTPREL_11_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_11_X)
|
||||
LLD_CASE(R_HEX_IE_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_11_X)
|
||||
LLD_CASE(R_HEX_TPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_TPREL_16_X)
|
||||
LLD_CASE(R_HEX_TPREL_11_X)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
|
||||
|
||||
ErrorOr<std::string> elf::HexagonTargetInfo::stringFromRelocKind(
|
||||
int32_t kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_HEX_NONE)
|
||||
LLD_CASE(R_HEX_B22_PCREL)
|
||||
LLD_CASE(R_HEX_B15_PCREL)
|
||||
LLD_CASE(R_HEX_B7_PCREL)
|
||||
LLD_CASE(R_HEX_LO16)
|
||||
LLD_CASE(R_HEX_HI16)
|
||||
LLD_CASE(R_HEX_32)
|
||||
LLD_CASE(R_HEX_16)
|
||||
LLD_CASE(R_HEX_8)
|
||||
LLD_CASE(R_HEX_GPREL16_0)
|
||||
LLD_CASE(R_HEX_GPREL16_1)
|
||||
LLD_CASE(R_HEX_GPREL16_2)
|
||||
LLD_CASE(R_HEX_GPREL16_3)
|
||||
LLD_CASE(R_HEX_HL16)
|
||||
LLD_CASE(R_HEX_B13_PCREL)
|
||||
LLD_CASE(R_HEX_B9_PCREL)
|
||||
LLD_CASE(R_HEX_B32_PCREL_X)
|
||||
LLD_CASE(R_HEX_32_6_X)
|
||||
LLD_CASE(R_HEX_B22_PCREL_X)
|
||||
LLD_CASE(R_HEX_B15_PCREL_X)
|
||||
LLD_CASE(R_HEX_B13_PCREL_X)
|
||||
LLD_CASE(R_HEX_B9_PCREL_X)
|
||||
LLD_CASE(R_HEX_B7_PCREL_X)
|
||||
LLD_CASE(R_HEX_16_X)
|
||||
LLD_CASE(R_HEX_12_X)
|
||||
LLD_CASE(R_HEX_11_X)
|
||||
LLD_CASE(R_HEX_10_X)
|
||||
LLD_CASE(R_HEX_9_X)
|
||||
LLD_CASE(R_HEX_8_X)
|
||||
LLD_CASE(R_HEX_7_X)
|
||||
LLD_CASE(R_HEX_6_X)
|
||||
LLD_CASE(R_HEX_32_PCREL)
|
||||
LLD_CASE(R_HEX_COPY)
|
||||
LLD_CASE(R_HEX_GLOB_DAT)
|
||||
LLD_CASE(R_HEX_JMP_SLOT)
|
||||
LLD_CASE(R_HEX_RELATIVE)
|
||||
LLD_CASE(R_HEX_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GOTREL_LO16)
|
||||
LLD_CASE(R_HEX_GOTREL_HI16)
|
||||
LLD_CASE(R_HEX_GOTREL_32)
|
||||
LLD_CASE(R_HEX_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GOT_32)
|
||||
LLD_CASE(R_HEX_GOT_16)
|
||||
LLD_CASE(R_HEX_DTPMOD_32)
|
||||
LLD_CASE(R_HEX_DTPREL_LO16)
|
||||
LLD_CASE(R_HEX_DTPREL_HI16)
|
||||
LLD_CASE(R_HEX_DTPREL_32)
|
||||
LLD_CASE(R_HEX_DTPREL_16)
|
||||
LLD_CASE(R_HEX_GD_PLT_B22_PCREL)
|
||||
LLD_CASE(R_HEX_GD_GOT_LO16)
|
||||
LLD_CASE(R_HEX_GD_GOT_HI16)
|
||||
LLD_CASE(R_HEX_GD_GOT_32)
|
||||
LLD_CASE(R_HEX_GD_GOT_16)
|
||||
LLD_CASE(R_HEX_IE_LO16)
|
||||
LLD_CASE(R_HEX_IE_HI16)
|
||||
LLD_CASE(R_HEX_IE_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_LO16)
|
||||
LLD_CASE(R_HEX_IE_GOT_HI16)
|
||||
LLD_CASE(R_HEX_IE_GOT_32)
|
||||
LLD_CASE(R_HEX_IE_GOT_16)
|
||||
LLD_CASE(R_HEX_TPREL_LO16)
|
||||
LLD_CASE(R_HEX_TPREL_HI16)
|
||||
LLD_CASE(R_HEX_TPREL_32)
|
||||
LLD_CASE(R_HEX_TPREL_16)
|
||||
LLD_CASE(R_HEX_6_PCREL_X)
|
||||
LLD_CASE(R_HEX_GOTREL_32_6_X)
|
||||
LLD_CASE(R_HEX_GOTREL_16_X)
|
||||
LLD_CASE(R_HEX_GOTREL_11_X)
|
||||
LLD_CASE(R_HEX_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GOT_11_X)
|
||||
LLD_CASE(R_HEX_DTPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_DTPREL_16_X)
|
||||
LLD_CASE(R_HEX_DTPREL_11_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_16_X)
|
||||
LLD_CASE(R_HEX_GD_GOT_11_X)
|
||||
LLD_CASE(R_HEX_IE_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_32_6_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_16_X)
|
||||
LLD_CASE(R_HEX_IE_GOT_11_X)
|
||||
LLD_CASE(R_HEX_TPREL_32_6_X)
|
||||
LLD_CASE(R_HEX_TPREL_16_X)
|
||||
LLD_CASE(R_HEX_TPREL_11_X)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "lld/Core/Instrumentation.h"
|
||||
#include "lld/Core/Parallel.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
@@ -33,8 +33,8 @@ class OutputELFWriter;
|
||||
/// as -u, or --defsym option.
|
||||
template <class ELFT> class LinkerInternalFile : public CRuntimeFile<ELFT> {
|
||||
public:
|
||||
LinkerInternalFile(const ELFTargetInfo &ti)
|
||||
: CRuntimeFile<ELFT>(ti, "Linker Internal File") {};
|
||||
LinkerInternalFile(const ELFLinkingContext &context)
|
||||
: CRuntimeFile<ELFT>(context, "Linker Internal File") {};
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
typedef Elf_Sym_Impl<ELFT> Elf_Sym;
|
||||
typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
|
||||
|
||||
OutputELFWriter(const ELFTargetInfo &ti);
|
||||
OutputELFWriter(const ELFLinkingContext &context);
|
||||
|
||||
protected:
|
||||
// build the sections that need to be created
|
||||
@@ -103,7 +103,7 @@ protected:
|
||||
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
const ELFLinkingContext &_context;
|
||||
TargetHandler<ELFT> &_targetHandler;
|
||||
|
||||
typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
|
||||
@@ -130,9 +130,9 @@ protected:
|
||||
// OutputELFWriter
|
||||
//===----------------------------------------------------------------------===//
|
||||
template <class ELFT>
|
||||
OutputELFWriter<ELFT>::OutputELFWriter(const ELFTargetInfo &ti)
|
||||
: _targetInfo(ti), _targetHandler(ti.getTargetHandler<ELFT>()),
|
||||
_linkerInternalFile(ti) {
|
||||
OutputELFWriter<ELFT>::OutputELFWriter(const ELFLinkingContext &context)
|
||||
: _context(context), _targetHandler(context.getTargetHandler<ELFT>()),
|
||||
_linkerInternalFile(context) {
|
||||
_layout = &_targetHandler.targetLayout();
|
||||
}
|
||||
|
||||
@@ -240,26 +240,26 @@ void OutputELFWriter<ELFT>::addFiles(InputFiles &inputFiles) {
|
||||
_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 : _targetInfo.initialUndefinedSymbols())
|
||||
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() {
|
||||
_Header.reset(new (_alloc) Header<ELFT>(_targetInfo));
|
||||
_programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_targetInfo));
|
||||
_Header.reset(new (_alloc) Header<ELFT>(_context));
|
||||
_programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_context));
|
||||
_layout->setHeader(_Header.get());
|
||||
_layout->setProgramHeader(_programHeader.get());
|
||||
|
||||
_symtab.reset(new (_alloc) SymbolTable<ELFT>(
|
||||
_targetInfo, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
|
||||
_context, ".symtab", DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE));
|
||||
_strtab.reset(new (_alloc) StringTable<ELFT>(
|
||||
_targetInfo, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
|
||||
_context, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
|
||||
_shstrtab.reset(new (_alloc) StringTable<ELFT>(
|
||||
_targetInfo, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
|
||||
_context, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
|
||||
_shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
|
||||
_targetInfo, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
|
||||
_context, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
|
||||
_layout->addSection(_symtab.get());
|
||||
_layout->addSection(_strtab.get());
|
||||
_layout->addSection(_shstrtab.get());
|
||||
@@ -267,16 +267,15 @@ template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
|
||||
_symtab->setStringSection(_strtab.get());
|
||||
_layout->addSection(_shdrtab.get());
|
||||
|
||||
if (_targetInfo.isDynamic()) {
|
||||
if (_context.isDynamic()) {
|
||||
_dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
|
||||
_targetInfo, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
|
||||
_context, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
|
||||
_dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
|
||||
_targetInfo, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS,
|
||||
true));
|
||||
_context, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
|
||||
_dynamicSymbolTable.reset(new (_alloc) DynamicSymbolTable<ELFT>(
|
||||
_targetInfo, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
|
||||
_context, ".dynsym", DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
|
||||
_hashTable.reset(new (_alloc) HashSection<ELFT>(
|
||||
_targetInfo, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
|
||||
_context, ".hash", DefaultLayout<ELFT>::ORDER_HASH));
|
||||
// Set the hash table in the dynamic symbol table so that the entries in the
|
||||
// hash table can be created
|
||||
_dynamicSymbolTable->setHashTable(_hashTable.get());
|
||||
@@ -313,7 +312,7 @@ error_code OutputELFWriter<ELFT>::buildOutput(const File &file) {
|
||||
_layout->assignSectionsToSegments();
|
||||
|
||||
// Create the dynamic table entries
|
||||
if (_targetInfo.isDynamic()) {
|
||||
if (_context.isDynamic()) {
|
||||
_dynamicTable->createDefaultEntries();
|
||||
buildDynamicSymbolTable(file);
|
||||
}
|
||||
@@ -344,7 +343,7 @@ error_code OutputELFWriter<ELFT>::buildOutput(const File &file) {
|
||||
// for sections with no segments
|
||||
assignSectionsWithNoSegments();
|
||||
|
||||
if (_targetInfo.isDynamic())
|
||||
if (_context.isDynamic())
|
||||
_dynamicTable->updateDynamicTable();
|
||||
|
||||
return error_code::success();
|
||||
@@ -366,12 +365,12 @@ error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
_Header->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64 :
|
||||
ELF::ELFCLASS32);
|
||||
_Header->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian() ?
|
||||
ELF::ELFDATA2LSB : ELF::ELFDATA2MSB);
|
||||
_Header->e_type(_targetInfo.getOutputType());
|
||||
_Header->e_machine(_targetInfo.getOutputMachine());
|
||||
_Header->e_ident(ELF::EI_CLASS,
|
||||
_context.is64Bits() ? ELF::ELFCLASS64 : ELF::ELFCLASS32);
|
||||
_Header->e_ident(ELF::EI_DATA, _context.isLittleEndian() ? ELF::ELFDATA2LSB
|
||||
: ELF::ELFDATA2MSB);
|
||||
_Header->e_type(_context.getOutputType());
|
||||
_Header->e_machine(_context.getOutputMachine());
|
||||
|
||||
if (!_targetHandler.doesOverrideHeader()) {
|
||||
_Header->e_ident(ELF::EI_VERSION, 1);
|
||||
@@ -389,7 +388,7 @@ error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
|
||||
_Header->e_shnum(_shdrtab->numHeaders());
|
||||
_Header->e_shstrndx(_shstrtab->ordinal());
|
||||
uint64_t virtualAddr = 0;
|
||||
_layout->findAtomAddrByName(_targetInfo.entrySymbolName(), virtualAddr);
|
||||
_layout->findAtomAddrByName(_context.entrySymbolName(), virtualAddr);
|
||||
_Header->e_entry(virtualAddr);
|
||||
|
||||
// HACK: We have to write out the header and program header here even though
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
add_lld_library(lldPPCELFTarget
|
||||
PPCLinkingContext.cpp
|
||||
PPCTargetHandler.cpp
|
||||
PPCTargetInfo.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lldPPCELFTarget
|
||||
|
||||
36
lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp
Normal file
36
lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "PPCLinkingContext.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
elf::PPCLinkingContext::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str) LLD_CASE(R_PPC_NONE)
|
||||
LLD_CASE(R_PPC_ADDR32).Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) \
|
||||
case llvm::ELF::name: \
|
||||
return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::PPCLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_PPC_NONE)
|
||||
LLD_CASE(R_PPC_ADDR32)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/Hexagon/PPCTargetInfo.h -----------------------===//
|
||||
//===- lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h -----------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -12,17 +12,18 @@
|
||||
|
||||
#include "PPCTargetHandler.h"
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class PPCTargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
class PPCLinkingContext LLVM_FINAL : public ELFLinkingContext {
|
||||
public:
|
||||
PPCTargetInfo(llvm::Triple triple)
|
||||
: ELFTargetInfo(triple, std::unique_ptr<TargetHandlerBase>(new PPCTargetHandler(*this))) {}
|
||||
PPCLinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new PPCTargetHandler(*this))) {}
|
||||
|
||||
virtual bool isLittleEndian() const { return false; }
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCTargetInfo.h"
|
||||
#include "PPCLinkingContext.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCTargetHandler.h"
|
||||
#include "PPCTargetInfo.h"
|
||||
#include "PPCLinkingContext.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
@@ -56,9 +56,9 @@ ErrorOr<void> PPCTargetRelocationHandler::applyRelocation(
|
||||
default : {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
auto name = _targetInfo.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: "
|
||||
<< (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")";
|
||||
auto name = _context.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: " << (name ? *name : "<unknown>") << " ("
|
||||
<< ref.kind() << ")";
|
||||
s.flush();
|
||||
llvm_unreachable(str.c_str());
|
||||
}
|
||||
@@ -67,7 +67,6 @@ ErrorOr<void> PPCTargetRelocationHandler::applyRelocation(
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
PPCTargetHandler::PPCTargetHandler(PPCTargetInfo &targetInfo)
|
||||
PPCTargetHandler::PPCTargetHandler(PPCLinkingContext &targetInfo)
|
||||
: DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo),
|
||||
_targetLayout(targetInfo) {
|
||||
}
|
||||
_targetLayout(targetInfo) {}
|
||||
|
||||
@@ -16,25 +16,26 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::big, 4, false> PPCELFType;
|
||||
class PPCTargetInfo;
|
||||
class PPCLinkingContext;
|
||||
|
||||
class PPCTargetRelocationHandler LLVM_FINAL
|
||||
: public TargetRelocationHandler<PPCELFType> {
|
||||
public:
|
||||
PPCTargetRelocationHandler(const PPCTargetInfo &ti) : _targetInfo(ti) {}
|
||||
PPCTargetRelocationHandler(const PPCLinkingContext &context)
|
||||
: _context(context) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &)const;
|
||||
|
||||
private:
|
||||
const PPCTargetInfo &_targetInfo;
|
||||
const PPCLinkingContext &_context;
|
||||
};
|
||||
|
||||
class PPCTargetHandler LLVM_FINAL
|
||||
: public DefaultTargetHandler<PPCELFType> {
|
||||
public:
|
||||
PPCTargetHandler(PPCTargetInfo &targetInfo);
|
||||
PPCTargetHandler(PPCLinkingContext &targetInfo);
|
||||
|
||||
virtual TargetLayout<PPCELFType> &targetLayout() {
|
||||
return _targetLayout;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "PPCTargetInfo.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind> elf::PPCTargetInfo::relocKindFromString(
|
||||
StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str)
|
||||
LLD_CASE(R_PPC_NONE)
|
||||
LLD_CASE(R_PPC_ADDR32)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::PPCTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_PPC_NONE)
|
||||
LLD_CASE(R_PPC_ADDR32)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "File.h"
|
||||
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/ReaderArchive.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -53,7 +53,7 @@ struct DynamicFileCreateELFTraits {
|
||||
typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
|
||||
|
||||
template <class ELFT>
|
||||
static result_type create(const lld::ELFTargetInfo &ti,
|
||||
static result_type create(const lld::ELFLinkingContext &ti,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
return lld::elf::DynamicFile<ELFT>::create(ti, std::move(mb));
|
||||
}
|
||||
@@ -63,7 +63,7 @@ struct ELFFileCreateELFTraits {
|
||||
typedef std::unique_ptr<lld::File> result_type;
|
||||
|
||||
template <class ELFT>
|
||||
static result_type create(const lld::ELFTargetInfo &ti,
|
||||
static result_type create(const lld::ELFLinkingContext &ti,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||
lld::error_code &ec) {
|
||||
return std::unique_ptr<lld::File>(
|
||||
@@ -78,12 +78,11 @@ namespace elf {
|
||||
/// memory buffer for ELF class and bit width
|
||||
class ELFReader : public Reader {
|
||||
public:
|
||||
ELFReader(const ELFTargetInfo &ti)
|
||||
: lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, *this) {
|
||||
}
|
||||
ELFReader(const ELFLinkingContext &ti)
|
||||
: lld::Reader(ti), _elfLinkingContext(ti), _readerArchive(ti, *this) {}
|
||||
|
||||
error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const {
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
using llvm::object::ELFType;
|
||||
llvm::sys::fs::file_magic FileType =
|
||||
llvm::sys::fs::identify_magic(mb->getBuffer());
|
||||
@@ -95,7 +94,7 @@ public:
|
||||
switch (FileType) {
|
||||
case llvm::sys::fs::file_magic::elf_relocatable: {
|
||||
std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
|
||||
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb),
|
||||
getElfArchType(&*mb), MaxAlignment, _elfLinkingContext, std::move(mb),
|
||||
ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
@@ -105,10 +104,11 @@ public:
|
||||
case llvm::sys::fs::file_magic::elf_shared_object: {
|
||||
// If the link doesnot allow dynamic libraries to be present during the
|
||||
// link, lets not parse the file and just return
|
||||
if (!_elfTargetInfo.allowLinkWithDynamicLibraries())
|
||||
if (!_elfLinkingContext.allowLinkWithDynamicLibraries())
|
||||
return llvm::make_error_code(llvm::errc::executable_format_error);
|
||||
auto f = createELF<DynamicFileCreateELFTraits>(
|
||||
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
|
||||
getElfArchType(&*mb), MaxAlignment, _elfLinkingContext,
|
||||
std::move(mb));
|
||||
if (!f)
|
||||
return f;
|
||||
result.push_back(std::move(*f));
|
||||
@@ -129,12 +129,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const ELFTargetInfo &_elfTargetInfo;
|
||||
const ELFLinkingContext &_elfLinkingContext;
|
||||
ReaderArchive _readerArchive;
|
||||
};
|
||||
} // end namespace elf
|
||||
|
||||
std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &targetinfo) {
|
||||
return std::unique_ptr<Reader>(new elf::ELFReader(targetinfo));
|
||||
std::unique_ptr<Reader> createReaderELF(const ELFLinkingContext &context) {
|
||||
return std::unique_ptr<Reader>(new elf::ELFReader(context));
|
||||
}
|
||||
} // end namespace lld
|
||||
|
||||
@@ -47,9 +47,9 @@ template <class ELFT> class Segment;
|
||||
/// \brief An ELF section.
|
||||
template <class ELFT> class Section : public Chunk<ELFT> {
|
||||
public:
|
||||
Section(const ELFTargetInfo &ti, StringRef name,
|
||||
Section(const ELFLinkingContext &context, StringRef name,
|
||||
typename Chunk<ELFT>::Kind k = Chunk<ELFT>::K_ELFSection)
|
||||
: Chunk<ELFT>(name, k, ti), _parent(nullptr), _flags(0), _entSize(0),
|
||||
: Chunk<ELFT>(name, k, context), _parent(nullptr), _flags(0), _entSize(0),
|
||||
_type(0), _link(0), _info(0), _segmentType(SHT_NULL) {}
|
||||
|
||||
/// \brief Modify the section contents before assigning virtual addresses
|
||||
@@ -133,9 +133,9 @@ protected:
|
||||
/// \brief A section containing atoms.
|
||||
template <class ELFT> class AtomSection : public Section<ELFT> {
|
||||
public:
|
||||
AtomSection(const ELFTargetInfo &ti, StringRef name, int32_t contentType,
|
||||
int32_t permissions, int32_t order)
|
||||
: Section<ELFT>(ti, name, Chunk<ELFT>::K_AtomSection),
|
||||
AtomSection(const ELFLinkingContext &context, StringRef name,
|
||||
int32_t contentType, int32_t permissions, int32_t order)
|
||||
: Section<ELFT>(context, name, Chunk<ELFT>::K_AtomSection),
|
||||
_contentType(contentType), _contentPermissions(permissions) {
|
||||
this->setOrder(order);
|
||||
switch (contentType) {
|
||||
@@ -354,7 +354,7 @@ template <class ELFT>
|
||||
void AtomSection<ELFT>::write(ELFWriter *writer,
|
||||
llvm::FileOutputBuffer &buffer) {
|
||||
uint8_t *chunkBuffer = buffer.getBufferStart();
|
||||
parallel_for_each(_atoms.begin(), _atoms.end(), [&] (lld::AtomLayout *ai) {
|
||||
parallel_for_each(_atoms.begin(), _atoms.end(), [&](lld::AtomLayout * ai) {
|
||||
DEBUG_WITH_TYPE("Section",
|
||||
llvm::dbgs() << "Writing atom: " << ai->_atom->name()
|
||||
<< " | " << ai->_fileOffset << "\n");
|
||||
@@ -370,8 +370,7 @@ void AtomSection<ELFT>::write(ELFWriter *writer,
|
||||
uint8_t *atomContent = chunkBuffer + ai->_fileOffset;
|
||||
std::memcpy(atomContent, content.data(), contentSize);
|
||||
const TargetRelocationHandler<ELFT> &relHandler =
|
||||
this->_targetInfo.template getTargetHandler<ELFT>()
|
||||
.getRelocationHandler();
|
||||
this->_context.template getTargetHandler<ELFT>().getRelocationHandler();
|
||||
for (const auto ref : *definedAtom)
|
||||
relHandler.applyRelocation(*writer, buffer, *ai, *ref);
|
||||
});
|
||||
@@ -516,7 +515,7 @@ MergedSections<ELFT>::appendSection(Chunk<ELFT> *c) {
|
||||
template<class ELFT>
|
||||
class StringTable : public Section<ELFT> {
|
||||
public:
|
||||
StringTable(const ELFTargetInfo &, const char *str, int32_t order,
|
||||
StringTable(const ELFLinkingContext &, const char *str, int32_t order,
|
||||
bool dynamic = false);
|
||||
|
||||
uint64_t addString(StringRef symname);
|
||||
@@ -547,9 +546,9 @@ private:
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
StringTable<ELFT>::StringTable(const ELFTargetInfo &ti, const char *str,
|
||||
int32_t order, bool dynamic)
|
||||
: Section<ELFT>(ti, str) {
|
||||
StringTable<ELFT>::StringTable(const ELFLinkingContext &context,
|
||||
const char *str, int32_t order, bool dynamic)
|
||||
: Section<ELFT>(context, str) {
|
||||
// the string table has a NULL entry for which
|
||||
// add an empty string
|
||||
_strings.push_back("");
|
||||
@@ -612,7 +611,7 @@ class SymbolTable : public Section<ELFT> {
|
||||
};
|
||||
|
||||
public:
|
||||
SymbolTable(const ELFTargetInfo &ti, const char *str, int32_t order);
|
||||
SymbolTable(const ELFLinkingContext &context, const char *str, int32_t order);
|
||||
|
||||
/// \brief set the number of entries that would exist in the symbol
|
||||
/// table for the current link
|
||||
@@ -671,9 +670,9 @@ protected:
|
||||
|
||||
/// ELF Symbol Table
|
||||
template <class ELFT>
|
||||
SymbolTable<ELFT>::SymbolTable(const ELFTargetInfo &ti, const char *str,
|
||||
int32_t order)
|
||||
: Section<ELFT>(ti, str) {
|
||||
SymbolTable<ELFT>::SymbolTable(const ELFLinkingContext &context,
|
||||
const char *str, int32_t order)
|
||||
: Section<ELFT>(context, str) {
|
||||
this->setOrder(order);
|
||||
Elf_Sym symbol;
|
||||
std::memset(&symbol, 0, sizeof(Elf_Sym));
|
||||
@@ -850,8 +849,9 @@ template <class ELFT> class HashSection;
|
||||
|
||||
template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
|
||||
public:
|
||||
DynamicSymbolTable(const ELFTargetInfo &ti, const char *str, int32_t order)
|
||||
: SymbolTable<ELFT>(ti, str, order), _hashTable(nullptr) {
|
||||
DynamicSymbolTable(const ELFLinkingContext &context, const char *str,
|
||||
int32_t order)
|
||||
: SymbolTable<ELFT>(context, str, order), _hashTable(nullptr) {
|
||||
this->_type = SHT_DYNSYM;
|
||||
this->_flags = SHF_ALLOC;
|
||||
this->_msize = this->_fsize;
|
||||
@@ -895,8 +895,9 @@ template <class ELFT> class RelocationTable : public Section<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
|
||||
|
||||
RelocationTable(const ELFTargetInfo &ti, StringRef str, int32_t order)
|
||||
: Section<ELFT>(ti, str), _symbolTable(nullptr) {
|
||||
RelocationTable(const ELFLinkingContext &context, StringRef str,
|
||||
int32_t order)
|
||||
: Section<ELFT>(context, str), _symbolTable(nullptr) {
|
||||
this->setOrder(order);
|
||||
this->_entSize = sizeof(Elf_Rela);
|
||||
this->_align2 = llvm::alignOf<Elf_Rela>();
|
||||
@@ -949,13 +950,13 @@ public:
|
||||
writer->addressOfAtom(rel.first) + rel.second->offsetInAtom();
|
||||
r->r_addend = 0;
|
||||
// The addend is used only by relative relocations
|
||||
if (this->_targetInfo.isRelativeReloc(*rel.second))
|
||||
if (this->_context.isRelativeReloc(*rel.second))
|
||||
r->r_addend =
|
||||
writer->addressOfAtom(rel.second->target()) + rel.second->addend();
|
||||
dest += sizeof(Elf_Rela);
|
||||
DEBUG_WITH_TYPE(
|
||||
"ELFRelocationTable",
|
||||
llvm::dbgs() << kindOrUnknown(this->_targetInfo.stringFromRelocKind(
|
||||
llvm::dbgs() << kindOrUnknown(this->_context.stringFromRelocKind(
|
||||
rel.second->kind())) << " relocation at "
|
||||
<< rel.first->name() << "@" << r->r_offset << " to "
|
||||
<< rel.second->target()->name() << "@" << r->r_addend
|
||||
@@ -975,8 +976,8 @@ template <class ELFT> class DynamicTable : public Section<ELFT> {
|
||||
typedef std::vector<Elf_Dyn> EntriesT;
|
||||
|
||||
public:
|
||||
DynamicTable(const ELFTargetInfo &ti, StringRef str, int32_t order)
|
||||
: Section<ELFT>(ti, str) {
|
||||
DynamicTable(const ELFLinkingContext &context, StringRef str, int32_t order)
|
||||
: Section<ELFT>(context, str) {
|
||||
this->setOrder(order);
|
||||
this->_entSize = sizeof(Elf_Dyn);
|
||||
this->_align2 = llvm::alignOf<Elf_Dyn>();
|
||||
@@ -985,7 +986,7 @@ public:
|
||||
this->_msize = sizeof(Elf_Dyn);
|
||||
this->_type = SHT_DYNAMIC;
|
||||
this->_flags = SHF_ALLOC;
|
||||
_layout = &ti.getTargetHandler<ELFT>().targetLayout();
|
||||
_layout = &context.getTargetHandler<ELFT>().targetLayout();
|
||||
}
|
||||
|
||||
range<typename EntriesT::iterator> entries() { return _entries; }
|
||||
@@ -1105,10 +1106,9 @@ private:
|
||||
|
||||
template <class ELFT> class InterpSection : public Section<ELFT> {
|
||||
public:
|
||||
InterpSection(const ELFTargetInfo &ti, StringRef str, int32_t order,
|
||||
InterpSection(const ELFLinkingContext &context, StringRef str, int32_t order,
|
||||
StringRef interp)
|
||||
: Section<ELFT>(ti, str),
|
||||
_interp(interp){
|
||||
: Section<ELFT>(context, str), _interp(interp) {
|
||||
this->setOrder(order);
|
||||
this->_align2 = 1;
|
||||
// + 1 for null term.
|
||||
@@ -1155,14 +1155,14 @@ template <class ELFT> class HashSection : public Section<ELFT> {
|
||||
};
|
||||
|
||||
public:
|
||||
HashSection(const ELFTargetInfo &ti, StringRef name, int32_t order)
|
||||
: Section<ELFT>(ti, name), _symbolTable(nullptr) {
|
||||
HashSection(const ELFLinkingContext &context, StringRef name, int32_t order)
|
||||
: Section<ELFT>(context, name), _symbolTable(nullptr) {
|
||||
this->setOrder(order);
|
||||
this->_entSize = 4;
|
||||
this->_type = SHT_HASH;
|
||||
this->_flags = SHF_ALLOC;
|
||||
// Set the alignment properly depending on the target architecture
|
||||
if (ti.is64Bits())
|
||||
if (context.is64Bits())
|
||||
this->_align2 = 8;
|
||||
else
|
||||
this->_align2 = 4;
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
|
||||
typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
|
||||
|
||||
Segment(const ELFTargetInfo &ti, StringRef name,
|
||||
Segment(const ELFLinkingContext &context, StringRef name,
|
||||
const Layout::SegmentType type);
|
||||
|
||||
/// \brief the Order of segments that appear in the output file
|
||||
@@ -225,7 +225,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline int pageSize() const { return this->_targetInfo.getPageSize(); }
|
||||
inline int pageSize() const { return this->_context.getPageSize(); }
|
||||
|
||||
inline int rawflags() const { return _atomflags; }
|
||||
|
||||
@@ -275,13 +275,13 @@ private:
|
||||
/// \brief Check if the chunk needs to be aligned
|
||||
bool needAlign(Chunk<ELFT> *chunk) const {
|
||||
if (chunk->getContentType() == Chunk<ELFT>::CT_Data &&
|
||||
_outputMagic == ELFTargetInfo::OutputMagic::NMAGIC)
|
||||
_outputMagic == ELFLinkingContext::OutputMagic::NMAGIC)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cached value of outputMagic
|
||||
ELFTargetInfo::OutputMagic _outputMagic;
|
||||
ELFLinkingContext::OutputMagic _outputMagic;
|
||||
|
||||
protected:
|
||||
/// \brief Section or some other chunk type.
|
||||
@@ -297,8 +297,8 @@ protected:
|
||||
/// The segment doesnot contain any slice
|
||||
template <class ELFT> class ProgramHeaderSegment : public Segment<ELFT> {
|
||||
public:
|
||||
ProgramHeaderSegment(const ELFTargetInfo &ti)
|
||||
: Segment<ELFT>(ti, "PHDR", llvm::ELF::PT_PHDR) {
|
||||
ProgramHeaderSegment(const ELFLinkingContext &context)
|
||||
: Segment<ELFT>(context, "PHDR", llvm::ELF::PT_PHDR) {
|
||||
this->_align2 = 8;
|
||||
this->_flags = (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
|
||||
}
|
||||
@@ -325,13 +325,13 @@ protected:
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
Segment<ELFT>::Segment(const ELFTargetInfo &ti, StringRef name,
|
||||
Segment<ELFT>::Segment(const ELFLinkingContext &context, StringRef name,
|
||||
const Layout::SegmentType type)
|
||||
: Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment, ti), _segmentType(type),
|
||||
: Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment, context), _segmentType(type),
|
||||
_flags(0), _atomflags(0) {
|
||||
this->_align2 = 0;
|
||||
this->_fsize = 0;
|
||||
_outputMagic = ti.getOutputMagic();
|
||||
_outputMagic = context.getOutputMagic();
|
||||
}
|
||||
|
||||
// This function actually is used, but not in all instantiations of Segment.
|
||||
@@ -429,8 +429,8 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
|
||||
// If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
|
||||
// to a page boundary
|
||||
if (!isDataPageAlignedForNMagic && needAlign(*si)) {
|
||||
startOffset = llvm::RoundUpToAlignment(startOffset,
|
||||
this->_targetInfo.getPageSize());
|
||||
startOffset =
|
||||
llvm::RoundUpToAlignment(startOffset, this->_context.getPageSize());
|
||||
isDataPageAlignedForNMagic = true;
|
||||
}
|
||||
// align the startOffset to the section alignment
|
||||
@@ -447,17 +447,17 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
|
||||
// If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
|
||||
// to a page boundary
|
||||
if (!isDataPageAlignedForNMagic && needAlign(*si)) {
|
||||
curOffset = llvm::RoundUpToAlignment(curOffset,
|
||||
this->_targetInfo.getPageSize());
|
||||
curOffset =
|
||||
llvm::RoundUpToAlignment(curOffset, this->_context.getPageSize());
|
||||
isDataPageAlignedForNMagic = true;
|
||||
}
|
||||
uint64_t newOffset = llvm::RoundUpToAlignment(curOffset, (*si)->align2());
|
||||
SegmentSlice<ELFT> *slice = nullptr;
|
||||
// If the newOffset computed is more than a page away, lets create
|
||||
// a seperate segment, so that memory is not used up while running
|
||||
if (((newOffset - curOffset) > this->_targetInfo.getPageSize()) &&
|
||||
(_outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
|
||||
_outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)) {
|
||||
if (((newOffset - curOffset) > this->_context.getPageSize()) &&
|
||||
(_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
|
||||
_outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)) {
|
||||
|
||||
// TODO: use std::find here
|
||||
for (auto s : slices()) {
|
||||
@@ -475,8 +475,8 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
|
||||
slice->setSections(make_range(startSectionIter, endSectionIter));
|
||||
slice->setSize(curSliceSize);
|
||||
slice->setAlign(sliceAlign);
|
||||
uint64_t newPageOffset = llvm::RoundUpToAlignment(
|
||||
curOffset, this->_targetInfo.getPageSize());
|
||||
uint64_t newPageOffset =
|
||||
llvm::RoundUpToAlignment(curOffset, this->_context.getPageSize());
|
||||
newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
|
||||
curSliceFileOffset = newOffset;
|
||||
startSectionIter = endSectionIter;
|
||||
@@ -525,9 +525,9 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t &addr) {
|
||||
for (auto slice : slices()) {
|
||||
// Align to a page only if the output is not
|
||||
// OutputMagic::NMAGIC/OutputMagic::OMAGIC
|
||||
if (_outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
|
||||
_outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
|
||||
addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize());
|
||||
if (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
|
||||
_outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
|
||||
addr = llvm::RoundUpToAlignment(addr, this->_context.getPageSize());
|
||||
|
||||
// Align to the slice alignment
|
||||
addr = llvm::RoundUpToAlignment(addr, slice->align2());
|
||||
@@ -537,7 +537,7 @@ template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t &addr) {
|
||||
// If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
|
||||
// to a page boundary
|
||||
if (!isDataPageAlignedForNMagic && needAlign(section)) {
|
||||
addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize());
|
||||
addr = llvm::RoundUpToAlignment(addr, this->_context.getPageSize());
|
||||
isDataPageAlignedForNMagic = true;
|
||||
}
|
||||
// Align the section address
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/Support/FileOutputBuffer.h"
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
template <class ELFT> class TargetHandler : public TargetHandlerBase {
|
||||
|
||||
public:
|
||||
TargetHandler(ELFTargetInfo &targetInfo) : _targetInfo(targetInfo) {}
|
||||
TargetHandler(ELFLinkingContext &targetInfo) : _context(targetInfo) {}
|
||||
|
||||
/// If the target overrides ELF header information, this API would
|
||||
/// return true, so that the target can set all fields specific to
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
virtual void allocateCommons() = 0;
|
||||
|
||||
protected:
|
||||
const ELFTargetInfo &_targetInfo;
|
||||
const ELFLinkingContext &_context;
|
||||
};
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace elf {
|
||||
/// be changed in the final layout
|
||||
template <class ELFT> class TargetLayout : public DefaultLayout<ELFT> {
|
||||
public:
|
||||
TargetLayout(const ELFTargetInfo &targetInfo)
|
||||
: DefaultLayout<ELFT>(targetInfo) {}
|
||||
TargetLayout(const ELFLinkingContext &context)
|
||||
: DefaultLayout<ELFT>(context) {}
|
||||
};
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
@@ -17,7 +17,7 @@ using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
namespace lld {
|
||||
|
||||
std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &info) {
|
||||
std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &info) {
|
||||
using llvm::object::ELFType;
|
||||
// Set the default layout to be the static executable layout
|
||||
// We would set the layout to a dynamic executable layout
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_lld_library(lldX86ELFTarget
|
||||
X86TargetInfo.cpp
|
||||
X86LinkingContext.cpp
|
||||
X86TargetHandler.cpp
|
||||
)
|
||||
|
||||
|
||||
36
lld/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
Normal file
36
lld/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "X86LinkingContext.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
elf::X86LinkingContext::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str) LLD_CASE(R_386_NONE)
|
||||
LLD_CASE(R_386_PC32).Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) \
|
||||
case llvm::ELF::name: \
|
||||
return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::X86LinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_386_NONE)
|
||||
LLD_CASE(R_386_PC32)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/X86/X86TargetInfo.h ---------------------------===//
|
||||
//===- lib/ReaderWriter/ELF/X86/X86LinkingContext.h -----------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -12,18 +12,18 @@
|
||||
|
||||
#include "X86TargetHandler.h"
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class X86TargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
class X86LinkingContext LLVM_FINAL : public ELFLinkingContext {
|
||||
public:
|
||||
X86TargetInfo(llvm::Triple triple)
|
||||
: ELFTargetInfo(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new X86TargetHandler(*this))) {}
|
||||
X86LinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new X86TargetHandler(*this))) {}
|
||||
|
||||
/// \brief X86 has only two relative relocation
|
||||
/// a) for supporting IFUNC relocs - R_386_IRELATIVE
|
||||
@@ -7,4 +7,4 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86TargetInfo.h"
|
||||
#include "X86LinkingContext.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86TargetHandler.h"
|
||||
#include "X86TargetInfo.h"
|
||||
#include "X86LinkingContext.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
@@ -55,9 +55,9 @@ ErrorOr<void> X86TargetRelocationHandler::applyRelocation(
|
||||
default : {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
auto name = _targetInfo.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: "
|
||||
<< (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")";
|
||||
auto name = _context.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: " << (name ? *name : "<unknown>") << " ("
|
||||
<< ref.kind() << ")";
|
||||
s.flush();
|
||||
llvm_unreachable(str.c_str());
|
||||
}
|
||||
@@ -66,7 +66,6 @@ ErrorOr<void> X86TargetRelocationHandler::applyRelocation(
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
X86TargetHandler::X86TargetHandler(X86TargetInfo &targetInfo)
|
||||
X86TargetHandler::X86TargetHandler(X86LinkingContext &targetInfo)
|
||||
: DefaultTargetHandler(targetInfo), _relocationHandler(targetInfo),
|
||||
_targetLayout(targetInfo) {
|
||||
}
|
||||
_targetLayout(targetInfo) {}
|
||||
|
||||
@@ -16,25 +16,26 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 4, false> X86ELFType;
|
||||
class X86TargetInfo;
|
||||
class X86LinkingContext;
|
||||
|
||||
class X86TargetRelocationHandler LLVM_FINAL
|
||||
: public TargetRelocationHandler<X86ELFType> {
|
||||
public:
|
||||
X86TargetRelocationHandler(const X86TargetInfo &ti) : _targetInfo(ti) {}
|
||||
X86TargetRelocationHandler(const X86LinkingContext &context)
|
||||
: _context(context) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
const Reference &)const;
|
||||
|
||||
private:
|
||||
const X86TargetInfo &_targetInfo;
|
||||
const X86LinkingContext &_context;
|
||||
};
|
||||
|
||||
class X86TargetHandler LLVM_FINAL
|
||||
: public DefaultTargetHandler<X86ELFType> {
|
||||
public:
|
||||
X86TargetHandler(X86TargetInfo &targetInfo);
|
||||
X86TargetHandler(X86LinkingContext &context);
|
||||
|
||||
virtual TargetLayout<X86ELFType> &targetLayout() {
|
||||
return _targetLayout;
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "X86TargetInfo.h"
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind> elf::X86TargetInfo::relocKindFromString(
|
||||
StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str)
|
||||
LLD_CASE(R_386_NONE)
|
||||
LLD_CASE(R_386_PC32)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::X86TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_386_NONE)
|
||||
LLD_CASE(R_386_PC32)
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
add_lld_library(lldX86_64ELFTarget
|
||||
X86_64TargetInfo.cpp
|
||||
X86_64LinkingContext.cpp
|
||||
X86_64TargetHandler.cpp
|
||||
X86_64RelocationHandler.cpp
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp -------------------===//
|
||||
//===- lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp ---------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Atoms.h"
|
||||
#include "X86_64TargetInfo.h"
|
||||
#include "X86_64LinkingContext.h"
|
||||
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Instrumentation.h"
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
class ELFPassFile : public SimpleFile {
|
||||
public:
|
||||
ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {}
|
||||
ELFPassFile(const ELFLinkingContext &eti) : SimpleFile(eti, "ELFPassFile") {}
|
||||
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
@@ -201,7 +201,7 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
GOTPLTPass(const ELFTargetInfo &ti)
|
||||
GOTPLTPass(const ELFLinkingContext &ti)
|
||||
: _file(ti), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
|
||||
_got1(nullptr) {}
|
||||
|
||||
@@ -280,7 +280,7 @@ protected:
|
||||
/// TLS always assumes module 1 and attempts to remove indirection.
|
||||
class StaticGOTPLTPass LLVM_FINAL : public GOTPLTPass<StaticGOTPLTPass> {
|
||||
public:
|
||||
StaticGOTPLTPass(const elf::X86_64TargetInfo &ti) : GOTPLTPass(ti) {}
|
||||
StaticGOTPLTPass(const elf::X86_64LinkingContext &ti) : GOTPLTPass(ti) {}
|
||||
|
||||
ErrorOr<void> handlePLT32(const Reference &ref) {
|
||||
// __tls_get_addr is handled elsewhere.
|
||||
@@ -291,7 +291,8 @@ public:
|
||||
// Static code doesn't need PLTs.
|
||||
const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
|
||||
// Handle IFUNC.
|
||||
if (const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (const DefinedAtom *da =
|
||||
dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (da->contentType() == DefinedAtom::typeResolver)
|
||||
return handleIFUNC(ref);
|
||||
return error_code::success();
|
||||
@@ -302,7 +303,7 @@ public:
|
||||
|
||||
class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> {
|
||||
public:
|
||||
DynamicGOTPLTPass(const elf::X86_64TargetInfo &ti) : GOTPLTPass(ti) {}
|
||||
DynamicGOTPLTPass(const elf::X86_64LinkingContext &ti) : GOTPLTPass(ti) {}
|
||||
|
||||
const PLT0Atom *getPLT0() {
|
||||
if (_PLT0)
|
||||
@@ -351,7 +352,8 @@ public:
|
||||
// Turn this into a PC32 to the PLT entry.
|
||||
const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
|
||||
// Handle IFUNC.
|
||||
if (const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (const DefinedAtom *da =
|
||||
dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (da->contentType() == DefinedAtom::typeResolver)
|
||||
return handleIFUNC(ref);
|
||||
if (isa<const SharedLibraryAtom>(ref.target()))
|
||||
@@ -393,7 +395,7 @@ public:
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
void elf::X86_64TargetInfo::addPasses(PassManager &pm) const {
|
||||
void elf::X86_64LinkingContext::addPasses(PassManager &pm) const {
|
||||
switch (_outputFileType) {
|
||||
case llvm::ELF::ET_EXEC:
|
||||
if (_isStaticExecutable)
|
||||
@@ -409,15 +411,48 @@ void elf::X86_64TargetInfo::addPasses(PassManager &pm) const {
|
||||
default:
|
||||
llvm_unreachable("Unhandled output file type");
|
||||
}
|
||||
ELFTargetInfo::addPasses(pm);
|
||||
ELFLinkingContext::addPasses(pm);
|
||||
}
|
||||
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
elf::X86_64TargetInfo::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str)
|
||||
elf::X86_64LinkingContext::relocKindFromString(StringRef str) const {
|
||||
int32_t ret = llvm::StringSwitch<int32_t>(str) LLD_CASE(R_X86_64_NONE)
|
||||
LLD_CASE(R_X86_64_64) LLD_CASE(R_X86_64_PC32) LLD_CASE(R_X86_64_GOT32)
|
||||
LLD_CASE(R_X86_64_PLT32) LLD_CASE(R_X86_64_COPY)
|
||||
LLD_CASE(R_X86_64_GLOB_DAT) LLD_CASE(R_X86_64_JUMP_SLOT)
|
||||
LLD_CASE(R_X86_64_RELATIVE) LLD_CASE(R_X86_64_GOTPCREL)
|
||||
LLD_CASE(R_X86_64_32) LLD_CASE(R_X86_64_32S) LLD_CASE(R_X86_64_16)
|
||||
LLD_CASE(R_X86_64_PC16) LLD_CASE(R_X86_64_8) LLD_CASE(R_X86_64_PC8)
|
||||
LLD_CASE(R_X86_64_DTPMOD64) LLD_CASE(R_X86_64_DTPOFF64)
|
||||
LLD_CASE(R_X86_64_TPOFF64) LLD_CASE(R_X86_64_TLSGD)
|
||||
LLD_CASE(R_X86_64_TLSLD) LLD_CASE(R_X86_64_DTPOFF32)
|
||||
LLD_CASE(R_X86_64_GOTTPOFF) LLD_CASE(R_X86_64_TPOFF32)
|
||||
LLD_CASE(R_X86_64_PC64) LLD_CASE(R_X86_64_GOTOFF64)
|
||||
LLD_CASE(R_X86_64_GOTPC32) LLD_CASE(R_X86_64_GOT64)
|
||||
LLD_CASE(R_X86_64_GOTPCREL64) LLD_CASE(R_X86_64_GOTPC64)
|
||||
LLD_CASE(R_X86_64_GOTPLT64) LLD_CASE(R_X86_64_PLTOFF64)
|
||||
LLD_CASE(R_X86_64_SIZE32) LLD_CASE(R_X86_64_SIZE64)
|
||||
LLD_CASE(R_X86_64_GOTPC32_TLSDESC) LLD_CASE(R_X86_64_TLSDESC_CALL)
|
||||
LLD_CASE(R_X86_64_TLSDESC) LLD_CASE(R_X86_64_IRELATIVE)
|
||||
.Case("LLD_R_X86_64_GOTRELINDEX", LLD_R_X86_64_GOTRELINDEX)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) \
|
||||
case llvm::ELF::name: \
|
||||
return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::X86_64LinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_X86_64_NONE)
|
||||
LLD_CASE(R_X86_64_64)
|
||||
LLD_CASE(R_X86_64_PC32)
|
||||
@@ -456,59 +491,6 @@ elf::X86_64TargetInfo::relocKindFromString(StringRef str) const {
|
||||
LLD_CASE(R_X86_64_TLSDESC_CALL)
|
||||
LLD_CASE(R_X86_64_TLSDESC)
|
||||
LLD_CASE(R_X86_64_IRELATIVE)
|
||||
.Case("LLD_R_X86_64_GOTRELINDEX", LLD_R_X86_64_GOTRELINDEX)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef LLD_CASE
|
||||
|
||||
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
|
||||
|
||||
ErrorOr<std::string>
|
||||
elf::X86_64TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
switch (kind) {
|
||||
LLD_CASE(R_X86_64_NONE)
|
||||
LLD_CASE(R_X86_64_64)
|
||||
LLD_CASE(R_X86_64_PC32)
|
||||
LLD_CASE(R_X86_64_GOT32)
|
||||
LLD_CASE(R_X86_64_PLT32)
|
||||
LLD_CASE(R_X86_64_COPY)
|
||||
LLD_CASE(R_X86_64_GLOB_DAT)
|
||||
LLD_CASE(R_X86_64_JUMP_SLOT)
|
||||
LLD_CASE(R_X86_64_RELATIVE)
|
||||
LLD_CASE(R_X86_64_GOTPCREL)
|
||||
LLD_CASE(R_X86_64_32)
|
||||
LLD_CASE(R_X86_64_32S)
|
||||
LLD_CASE(R_X86_64_16)
|
||||
LLD_CASE(R_X86_64_PC16)
|
||||
LLD_CASE(R_X86_64_8)
|
||||
LLD_CASE(R_X86_64_PC8)
|
||||
LLD_CASE(R_X86_64_DTPMOD64)
|
||||
LLD_CASE(R_X86_64_DTPOFF64)
|
||||
LLD_CASE(R_X86_64_TPOFF64)
|
||||
LLD_CASE(R_X86_64_TLSGD)
|
||||
LLD_CASE(R_X86_64_TLSLD)
|
||||
LLD_CASE(R_X86_64_DTPOFF32)
|
||||
LLD_CASE(R_X86_64_GOTTPOFF)
|
||||
LLD_CASE(R_X86_64_TPOFF32)
|
||||
LLD_CASE(R_X86_64_PC64)
|
||||
LLD_CASE(R_X86_64_GOTOFF64)
|
||||
LLD_CASE(R_X86_64_GOTPC32)
|
||||
LLD_CASE(R_X86_64_GOT64)
|
||||
LLD_CASE(R_X86_64_GOTPCREL64)
|
||||
LLD_CASE(R_X86_64_GOTPC64)
|
||||
LLD_CASE(R_X86_64_GOTPLT64)
|
||||
LLD_CASE(R_X86_64_PLTOFF64)
|
||||
LLD_CASE(R_X86_64_SIZE32)
|
||||
LLD_CASE(R_X86_64_SIZE64)
|
||||
LLD_CASE(R_X86_64_GOTPC32_TLSDESC)
|
||||
LLD_CASE(R_X86_64_TLSDESC_CALL)
|
||||
LLD_CASE(R_X86_64_TLSDESC)
|
||||
LLD_CASE(R_X86_64_IRELATIVE)
|
||||
case LLD_R_X86_64_GOTRELINDEX:
|
||||
return std::string("LLD_R_X86_64_GOTRELINDEX");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h ---------------------===//
|
||||
//===- lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h -----------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,12 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
|
||||
#define LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H
|
||||
#ifndef LLD_READER_WRITER_ELF_X86_64_LINKER_CONTEXT_H
|
||||
#define LLD_READER_WRITER_ELF_X86_64_LINKER_CONTEXT_H
|
||||
|
||||
#include "X86_64TargetHandler.h"
|
||||
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
@@ -26,11 +26,11 @@ enum {
|
||||
LLD_R_X86_64_GOTRELINDEX = 1024,
|
||||
};
|
||||
|
||||
class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
class X86_64LinkingContext LLVM_FINAL : public ELFLinkingContext {
|
||||
public:
|
||||
X86_64TargetInfo(llvm::Triple triple)
|
||||
: ELFTargetInfo(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new X86_64TargetHandler(*this))) {}
|
||||
X86_64LinkingContext(llvm::Triple triple)
|
||||
: ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
|
||||
new X86_64TargetHandler(*this))) {}
|
||||
|
||||
virtual void addPasses(PassManager &) const;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual bool isDynamicRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
switch (r.kind()){
|
||||
switch (r.kind()) {
|
||||
case llvm::ELF::R_X86_64_RELATIVE:
|
||||
case llvm::ELF::R_X86_64_GLOB_DAT:
|
||||
return true;
|
||||
@@ -51,9 +51,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isPLTRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
switch (r.kind()){
|
||||
virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const {
|
||||
switch (r.kind()) {
|
||||
case llvm::ELF::R_X86_64_JUMP_SLOT:
|
||||
case llvm::ELF::R_X86_64_IRELATIVE:
|
||||
return true;
|
||||
@@ -77,7 +76,6 @@ public:
|
||||
|
||||
virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
|
||||
virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
|
||||
|
||||
};
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
@@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86_64TargetHandler.h"
|
||||
#include "X86_64TargetInfo.h"
|
||||
#include "X86_64LinkingContext.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
@@ -85,8 +85,8 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||
case R_X86_64_TPOFF64:
|
||||
case R_X86_64_DTPOFF32:
|
||||
case R_X86_64_TPOFF32: {
|
||||
_tlsSize = _targetInfo.getTargetHandler<X86_64ELFType>().targetLayout()
|
||||
.getTLSSize();
|
||||
_tlsSize =
|
||||
_context.getTargetHandler<X86_64ELFType>().targetLayout().getTLSSize();
|
||||
if (ref.kind() == R_X86_64_TPOFF32 || ref.kind() == R_X86_64_DTPOFF32) {
|
||||
int32_t result = (int32_t)(targetVAddress - _tlsSize);
|
||||
*reinterpret_cast<llvm::support::little32_t *>(location) = result;
|
||||
@@ -109,7 +109,7 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||
for (const Reference *r : *target) {
|
||||
if (r->kind() == R_X86_64_JUMP_SLOT) {
|
||||
uint32_t index;
|
||||
if (!_targetInfo.getTargetHandler<X86_64ELFType>().targetLayout()
|
||||
if (!_context.getTargetHandler<X86_64ELFType>().targetLayout()
|
||||
.getPLTRelocationTable()->getRelocationIndex(*r, index))
|
||||
llvm_unreachable("Relocation doesn't exist");
|
||||
reloc32(location, 0, index, 0);
|
||||
@@ -133,7 +133,7 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
||||
default: {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
auto name = _targetInfo.stringFromRelocKind(ref.kind());
|
||||
auto name = _context.stringFromRelocKind(ref.kind());
|
||||
s << "Unhandled relocation: " << atom._atom->file().path() << ":"
|
||||
<< atom._atom->name() << "@" << ref.offsetInAtom() << " "
|
||||
<< (name ? *name : "<unknown>") << " (" << ref.kind() << ")";
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 8, true> X86_64ELFType;
|
||||
class X86_64TargetInfo;
|
||||
class X86_64LinkingContext;
|
||||
|
||||
class X86_64TargetRelocationHandler LLVM_FINAL
|
||||
: public TargetRelocationHandler<X86_64ELFType> {
|
||||
public:
|
||||
X86_64TargetRelocationHandler(const X86_64TargetInfo &ti)
|
||||
: _tlsSize(0), _targetInfo(ti) {}
|
||||
X86_64TargetRelocationHandler(const X86_64LinkingContext &context)
|
||||
: _tlsSize(0), _context(context) {}
|
||||
|
||||
virtual ErrorOr<void> applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
|
||||
const lld::AtomLayout &,
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
private:
|
||||
// Cached size of the TLS segment.
|
||||
mutable uint64_t _tlsSize;
|
||||
const X86_64TargetInfo &_targetInfo;
|
||||
const X86_64LinkingContext &_context;
|
||||
};
|
||||
|
||||
} // end namespace elf
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86_64TargetInfo.h"
|
||||
#include "X86_64LinkingContext.h"
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
#include "Atoms.h"
|
||||
#include "X86_64TargetHandler.h"
|
||||
#include "X86_64TargetInfo.h"
|
||||
#include "X86_64LinkingContext.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace elf;
|
||||
|
||||
X86_64TargetHandler::X86_64TargetHandler(X86_64TargetInfo &targetInfo)
|
||||
: DefaultTargetHandler(targetInfo), _gotFile(targetInfo),
|
||||
_relocationHandler(targetInfo), _targetLayout(targetInfo) {}
|
||||
X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &context)
|
||||
: DefaultTargetHandler(context), _gotFile(context),
|
||||
_relocationHandler(context), _targetLayout(context) {}
|
||||
|
||||
void X86_64TargetHandler::addFiles(InputFiles &f) {
|
||||
_gotFile.addAtom(*new (_gotFile._alloc) GLOBAL_OFFSET_TABLEAtom(_gotFile));
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 8, true> X86_64ELFType;
|
||||
class X86_64TargetInfo;
|
||||
class X86_64LinkingContext;
|
||||
|
||||
class X86_64TargetHandler LLVM_FINAL
|
||||
: public DefaultTargetHandler<X86_64ELFType> {
|
||||
public:
|
||||
X86_64TargetHandler(X86_64TargetInfo &targetInfo);
|
||||
X86_64TargetHandler(X86_64LinkingContext &targetInfo);
|
||||
|
||||
virtual TargetLayout<X86_64ELFType> &targetLayout() {
|
||||
return _targetLayout;
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
private:
|
||||
class GOTFile : public SimpleFile {
|
||||
public:
|
||||
GOTFile(const ELFTargetInfo &eti) : SimpleFile(eti, "GOTFile") {}
|
||||
GOTFile(const ELFLinkingContext &eti) : SimpleFile(eti, "GOTFile") {}
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
} _gotFile;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
add_lld_library(lldMachO
|
||||
MachOTargetInfo.cpp
|
||||
WriterMachO.cpp
|
||||
MachOLinkingContext.cpp
|
||||
ReferenceKinds.cpp
|
||||
WriterMachO.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(lldMachO
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/Core/LinkingContext.h"
|
||||
#include "lld/ReaderWriter/Simple.h"
|
||||
|
||||
namespace lld {
|
||||
@@ -28,10 +28,11 @@ namespace mach_o {
|
||||
//
|
||||
class CRuntimeFile : public SimpleFile {
|
||||
public:
|
||||
CRuntimeFile(const MachOTargetInfo &ti)
|
||||
: SimpleFile(ti, "C runtime"), _undefMain(*this, ti.entrySymbolName()) {
|
||||
CRuntimeFile(const MachOLinkingContext &context)
|
||||
: SimpleFile(context, "C runtime"),
|
||||
_undefMain(*this, context.entrySymbolName()) {
|
||||
// only main executables need _main
|
||||
if (ti.outputFileType() == MH_EXECUTE) {
|
||||
if (context.outputFileType() == MH_EXECUTE) {
|
||||
this->addAtom(_undefMain);
|
||||
}
|
||||
}
|
||||
@@ -40,10 +41,7 @@ private:
|
||||
SimpleUndefinedAtom _undefMain;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace mach_o
|
||||
} // namespace lld
|
||||
|
||||
} // namespace mach_o
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/MachO/MachOTargetInfo.cpp -------------------------===//
|
||||
//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/ReaderWriter/MachOTargetInfo.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
#include "GOTPass.hpp"
|
||||
#include "StubsPass.hpp"
|
||||
#include "ReferenceKinds.h"
|
||||
@@ -23,34 +23,32 @@
|
||||
|
||||
using lld::mach_o::KindHandler;
|
||||
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
||||
MachOTargetInfo::PackedVersion::PackedVersion(StringRef str) {
|
||||
MachOLinkingContext::PackedVersion::PackedVersion(StringRef str) {
|
||||
if (parse(str, *this))
|
||||
llvm_unreachable("bad version string");
|
||||
}
|
||||
|
||||
/// Construct 32-bit PackedVersion from string "X.Y.Z" where
|
||||
/// bits are xxxx.yy.zz. Largest number is 65535.255.255
|
||||
bool MachOTargetInfo::PackedVersion::parse(StringRef str,
|
||||
MachOTargetInfo::PackedVersion &result) {
|
||||
bool MachOLinkingContext::PackedVersion::parse(
|
||||
StringRef str, MachOLinkingContext::PackedVersion &result) {
|
||||
result._value = 0;
|
||||
|
||||
if (str.empty())
|
||||
if (str.empty())
|
||||
return false;
|
||||
|
||||
|
||||
SmallVector<StringRef, 3> parts;
|
||||
llvm::SplitString(str, parts, ".");
|
||||
|
||||
|
||||
unsigned long long num;
|
||||
if (llvm::getAsUnsignedInteger(parts[0], 10, num))
|
||||
return true;
|
||||
if (num > 65535)
|
||||
return true;
|
||||
result._value = num << 16;
|
||||
|
||||
|
||||
if (parts.size() > 1) {
|
||||
if (llvm::getAsUnsignedInteger(parts[1], 10, num))
|
||||
return true;
|
||||
@@ -58,7 +56,7 @@ bool MachOTargetInfo::PackedVersion::parse(StringRef str,
|
||||
return true;
|
||||
result._value |= (num << 8);
|
||||
}
|
||||
|
||||
|
||||
if (parts.size() > 2) {
|
||||
if (llvm::getAsUnsignedInteger(parts[2], 10, num))
|
||||
return true;
|
||||
@@ -66,58 +64,58 @@ bool MachOTargetInfo::PackedVersion::parse(StringRef str,
|
||||
return true;
|
||||
result._value |= num;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::PackedVersion::operator<(
|
||||
const PackedVersion &rhs) const {
|
||||
bool MachOLinkingContext::PackedVersion::
|
||||
operator<(const PackedVersion &rhs) const {
|
||||
return _value < rhs._value;
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::PackedVersion::operator>=(
|
||||
const PackedVersion &rhs) const {
|
||||
bool MachOLinkingContext::PackedVersion::
|
||||
operator>=(const PackedVersion &rhs) const {
|
||||
return _value >= rhs._value;
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::PackedVersion::operator==(
|
||||
const PackedVersion &rhs) const {
|
||||
bool MachOLinkingContext::PackedVersion::
|
||||
operator==(const PackedVersion &rhs) const {
|
||||
return _value == rhs._value;
|
||||
}
|
||||
|
||||
struct ArchInfo {
|
||||
StringRef archName;
|
||||
MachOTargetInfo::Arch arch;
|
||||
uint32_t cputype;
|
||||
uint32_t cpusubtype;
|
||||
StringRef archName;
|
||||
MachOLinkingContext::Arch arch;
|
||||
uint32_t cputype;
|
||||
uint32_t cpusubtype;
|
||||
};
|
||||
|
||||
static ArchInfo archInfos[] = {
|
||||
{ "x86_64", MachOTargetInfo::arch_x86_64, mach_o::CPU_TYPE_X86_64,
|
||||
mach_o::CPU_SUBTYPE_X86_64_ALL },
|
||||
{ "i386", MachOTargetInfo::arch_x86, mach_o::CPU_TYPE_I386,
|
||||
mach_o::CPU_SUBTYPE_X86_ALL },
|
||||
{ "armv6", MachOTargetInfo::arch_armv6, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V6 },
|
||||
{ "armv7", MachOTargetInfo::arch_armv7, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V7 },
|
||||
{ "armv7s", MachOTargetInfo::arch_armv7s, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V7S },
|
||||
{ StringRef(), MachOTargetInfo::arch_unknown, 0, 0 }
|
||||
|
||||
{ "x86_64", MachOLinkingContext::arch_x86_64, mach_o::CPU_TYPE_X86_64,
|
||||
mach_o::CPU_SUBTYPE_X86_64_ALL },
|
||||
{ "i386", MachOLinkingContext::arch_x86, mach_o::CPU_TYPE_I386,
|
||||
mach_o::CPU_SUBTYPE_X86_ALL },
|
||||
{ "armv6", MachOLinkingContext::arch_armv6, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V6 },
|
||||
{ "armv7", MachOLinkingContext::arch_armv7, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V7 },
|
||||
{ "armv7s", MachOLinkingContext::arch_armv7s, mach_o::CPU_TYPE_ARM,
|
||||
mach_o::CPU_SUBTYPE_ARM_V7S },
|
||||
{ StringRef(), MachOLinkingContext::arch_unknown, 0, 0 }
|
||||
};
|
||||
|
||||
MachOTargetInfo::Arch
|
||||
MachOTargetInfo::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
|
||||
MachOLinkingContext::Arch
|
||||
MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
|
||||
for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
|
||||
if ( (info->cputype == cputype) && (info->cpusubtype == cpusubtype)) {
|
||||
if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype)) {
|
||||
return info->arch;
|
||||
}
|
||||
}
|
||||
return arch_unknown;
|
||||
}
|
||||
|
||||
MachOTargetInfo::Arch MachOTargetInfo::archFromName(StringRef archName) {
|
||||
MachOLinkingContext::Arch
|
||||
MachOLinkingContext::archFromName(StringRef archName) {
|
||||
for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
|
||||
if (info->archName.equals(archName)) {
|
||||
return info->arch;
|
||||
@@ -126,7 +124,7 @@ MachOTargetInfo::Arch MachOTargetInfo::archFromName(StringRef archName) {
|
||||
return arch_unknown;
|
||||
}
|
||||
|
||||
uint32_t MachOTargetInfo::cpuTypeFromArch(Arch arch) {
|
||||
uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
|
||||
assert(arch != arch_unknown);
|
||||
for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
|
||||
if (info->arch == arch) {
|
||||
@@ -136,7 +134,7 @@ uint32_t MachOTargetInfo::cpuTypeFromArch(Arch arch) {
|
||||
llvm_unreachable("Unknown arch type");
|
||||
}
|
||||
|
||||
uint32_t MachOTargetInfo::cpuSubtypeFromArch(Arch arch) {
|
||||
uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
|
||||
assert(arch != arch_unknown);
|
||||
for (ArchInfo *info = archInfos; !info->archName.empty(); ++info) {
|
||||
if (info->arch == arch) {
|
||||
@@ -146,32 +144,22 @@ uint32_t MachOTargetInfo::cpuSubtypeFromArch(Arch arch) {
|
||||
llvm_unreachable("Unknown arch type");
|
||||
}
|
||||
|
||||
MachOLinkingContext::MachOLinkingContext()
|
||||
: _outputFileType(mach_o::MH_EXECUTE), _outputFileTypeStatic(false),
|
||||
_doNothing(false), _arch(arch_unknown), _os(OS::macOSX),
|
||||
_osMinVersion("0.0"), _pageZeroSize(0x1000), _kindHandler(nullptr) {}
|
||||
|
||||
MachOTargetInfo::MachOTargetInfo()
|
||||
: _outputFileType(mach_o::MH_EXECUTE)
|
||||
, _outputFileTypeStatic(false)
|
||||
, _doNothing(false)
|
||||
, _arch(arch_unknown)
|
||||
, _os(OS::macOSX)
|
||||
, _osMinVersion("0.0")
|
||||
, _pageZeroSize(0x1000)
|
||||
, _kindHandler(nullptr) {
|
||||
}
|
||||
MachOLinkingContext::~MachOLinkingContext() {}
|
||||
|
||||
|
||||
MachOTargetInfo::~MachOTargetInfo() {
|
||||
}
|
||||
|
||||
uint32_t MachOTargetInfo::getCPUType() const {
|
||||
uint32_t MachOLinkingContext::getCPUType() const {
|
||||
return cpuTypeFromArch(_arch);
|
||||
}
|
||||
|
||||
uint32_t MachOTargetInfo::getCPUSubType() const {
|
||||
uint32_t MachOLinkingContext::getCPUSubType() const {
|
||||
return cpuSubtypeFromArch(_arch);
|
||||
}
|
||||
|
||||
|
||||
bool MachOTargetInfo::outputTypeHasEntry() const {
|
||||
bool MachOLinkingContext::outputTypeHasEntry() const {
|
||||
switch (_outputFileType) {
|
||||
case mach_o::MH_EXECUTE:
|
||||
case mach_o::MH_DYLINKER:
|
||||
@@ -182,8 +170,7 @@ bool MachOTargetInfo::outputTypeHasEntry() const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MachOTargetInfo::minOS(StringRef mac, StringRef iOS) const {
|
||||
bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
|
||||
switch (_os) {
|
||||
case OS::macOSX:
|
||||
return (_osMinVersion >= PackedVersion(mac));
|
||||
@@ -194,14 +181,14 @@ bool MachOTargetInfo::minOS(StringRef mac, StringRef iOS) const {
|
||||
llvm_unreachable("target not configured for iOS or MacOSX");
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::addEntryPointLoadCommand() const {
|
||||
bool MachOLinkingContext::addEntryPointLoadCommand() const {
|
||||
if ((_outputFileType == mach_o::MH_EXECUTE) && !_outputFileTypeStatic) {
|
||||
return minOS("10.8", "6.0");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::addUnixThreadLoadCommand() const {
|
||||
bool MachOLinkingContext::addUnixThreadLoadCommand() const {
|
||||
switch (_outputFileType) {
|
||||
case mach_o::MH_EXECUTE:
|
||||
if (_outputFileTypeStatic)
|
||||
@@ -217,7 +204,7 @@ bool MachOTargetInfo::addUnixThreadLoadCommand() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
||||
if (_inputFiles.empty()) {
|
||||
diagnostics << "no object files specified\n";
|
||||
return true;
|
||||
@@ -226,8 +213,7 @@ bool MachOTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
|
||||
if (_outputFileTypeStatic) {
|
||||
_entrySymbolName = "start";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If targeting newer OS, use _main
|
||||
if (addEntryPointLoadCommand())
|
||||
_entrySymbolName = "_main";
|
||||
@@ -241,52 +227,51 @@ bool MachOTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachOTargetInfo::setOS(OS os, StringRef minOSVersion) {
|
||||
bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) {
|
||||
_os = os;
|
||||
return PackedVersion::parse(minOSVersion, _osMinVersion);
|
||||
}
|
||||
|
||||
void MachOTargetInfo::addPasses(PassManager &pm) const {
|
||||
void MachOLinkingContext::addPasses(PassManager &pm) const {
|
||||
pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
|
||||
pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
|
||||
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
|
||||
}
|
||||
|
||||
error_code MachOTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
// if (!_machoReader)
|
||||
// _machoReader = createReaderMachO(*this);
|
||||
// error_code ec = _machoReader->parseFile(mb,result);
|
||||
// if (ec) {
|
||||
return _yamlReader->parseFile(mb, result);
|
||||
// }
|
||||
error_code MachOLinkingContext::parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
// if (!_machoReader)
|
||||
// _machoReader = createReaderMachO(*this);
|
||||
// error_code ec = _machoReader->parseFile(mb,result);
|
||||
// if (ec) {
|
||||
return _yamlReader->parseFile(mb, result);
|
||||
// }
|
||||
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
|
||||
Writer &MachOTargetInfo::writer() const {
|
||||
Writer &MachOLinkingContext::writer() const {
|
||||
if (!_writer) {
|
||||
_writer = createWriterMachO(*this);
|
||||
}
|
||||
return *_writer;
|
||||
}
|
||||
|
||||
KindHandler &MachOTargetInfo::kindHandler() const {
|
||||
KindHandler &MachOLinkingContext::kindHandler() const {
|
||||
if (!_kindHandler)
|
||||
_kindHandler = KindHandler::create(_arch);
|
||||
return *_kindHandler;
|
||||
}
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
MachOTargetInfo::relocKindFromString(StringRef str) const {
|
||||
ErrorOr<Reference::Kind>
|
||||
MachOLinkingContext::relocKindFromString(StringRef str) const {
|
||||
return kindHandler().stringToKind(str);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<std::string>
|
||||
MachOTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
ErrorOr<std::string>
|
||||
MachOLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
return std::string(kindHandler().kindToString(kind));
|
||||
}
|
||||
|
||||
|
||||
} // end namespace lld
|
||||
@@ -30,16 +30,16 @@ KindHandler::KindHandler() {
|
||||
KindHandler::~KindHandler() {
|
||||
}
|
||||
|
||||
std::unique_ptr<mach_o::KindHandler> KindHandler::create(
|
||||
MachOTargetInfo::Arch arch) {
|
||||
switch( arch ) {
|
||||
case MachOTargetInfo::arch_x86_64:
|
||||
return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86_64());
|
||||
case MachOTargetInfo::arch_x86:
|
||||
return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86());
|
||||
case MachOTargetInfo::arch_armv6:
|
||||
case MachOTargetInfo::arch_armv7:
|
||||
case MachOTargetInfo::arch_armv7s:
|
||||
std::unique_ptr<mach_o::KindHandler>
|
||||
KindHandler::create(MachOLinkingContext::Arch arch) {
|
||||
switch (arch) {
|
||||
case MachOLinkingContext::arch_x86_64:
|
||||
return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86_64());
|
||||
case MachOLinkingContext::arch_x86:
|
||||
return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86());
|
||||
case MachOLinkingContext::arch_armv6:
|
||||
case MachOLinkingContext::arch_armv7:
|
||||
case MachOLinkingContext::arch_armv7s:
|
||||
return std::unique_ptr<mach_o::KindHandler>(new KindHandler_arm());
|
||||
default:
|
||||
llvm_unreachable("Unknown arch");
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/ReaderWriter/MachOTargetInfo.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
@@ -30,9 +30,9 @@ class KindHandler {
|
||||
public:
|
||||
typedef Reference::Kind Kind;
|
||||
|
||||
static std::unique_ptr<mach_o::KindHandler> create(MachOTargetInfo::Arch);
|
||||
virtual ~KindHandler();
|
||||
virtual Kind stringToKind(StringRef str) = 0;
|
||||
static std::unique_ptr<mach_o::KindHandler> create(MachOLinkingContext::Arch);
|
||||
virtual ~KindHandler();
|
||||
virtual Kind stringToKind(StringRef str) = 0;
|
||||
virtual StringRef kindToString(Kind) = 0;
|
||||
virtual bool isCallSite(Kind) = 0;
|
||||
virtual bool isPointer(Kind) = 0;
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace mach_o {
|
||||
|
||||
class StubsPass : public lld::StubsPass {
|
||||
public:
|
||||
StubsPass(const MachOTargetInfo &ti)
|
||||
: _targetInfo(ti)
|
||||
, _kindHandler(_targetInfo.kindHandler())
|
||||
, _file(ti)
|
||||
StubsPass(const MachOLinkingContext &context)
|
||||
: _context(context)
|
||||
, _kindHandler(_context.kindHandler())
|
||||
, _file(context)
|
||||
, _helperCommonAtom(nullptr)
|
||||
, _helperCacheAtom(nullptr)
|
||||
, _helperBinderAtom(nullptr) {
|
||||
@@ -59,14 +59,14 @@ public:
|
||||
}
|
||||
|
||||
const DefinedAtom* makeStub(const Atom& target) {
|
||||
switch (_targetInfo.arch()) {
|
||||
case MachOTargetInfo::arch_x86_64:
|
||||
switch (_context.arch()) {
|
||||
case MachOLinkingContext::arch_x86_64:
|
||||
return makeStub_x86_64(target);
|
||||
case MachOTargetInfo::arch_x86:
|
||||
case MachOLinkingContext::arch_x86:
|
||||
return makeStub_x86(target);
|
||||
case MachOTargetInfo::arch_armv6:
|
||||
case MachOTargetInfo::arch_armv7:
|
||||
case MachOTargetInfo::arch_armv7s:
|
||||
case MachOLinkingContext::arch_armv6:
|
||||
case MachOLinkingContext::arch_armv7:
|
||||
case MachOLinkingContext::arch_armv7s:
|
||||
return makeStub_arm(target);
|
||||
default:
|
||||
llvm_unreachable("Unknown mach-o arch");
|
||||
@@ -149,11 +149,11 @@ private:
|
||||
|
||||
class File : public SimpleFile {
|
||||
public:
|
||||
File(const MachOTargetInfo &ti) : SimpleFile(ti, "MachO Stubs pass") {
|
||||
}
|
||||
File(const MachOLinkingContext &context)
|
||||
: SimpleFile(context, "MachO Stubs pass") {}
|
||||
};
|
||||
|
||||
const MachOTargetInfo &_targetInfo;
|
||||
const MachOLinkingContext &_context;
|
||||
mach_o::KindHandler &_kindHandler;
|
||||
File _file;
|
||||
llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/ReaderWriter/MachOTargetInfo.h"
|
||||
#include "lld/ReaderWriter/MachOLinkingContext.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -145,9 +145,8 @@ private:
|
||||
//
|
||||
class MachHeaderChunk : public Chunk {
|
||||
public:
|
||||
MachHeaderChunk(const MachOTargetInfo &ti,
|
||||
const File &file);
|
||||
virtual StringRef segmentName() const;
|
||||
MachHeaderChunk(const MachOLinkingContext &context, const File &file);
|
||||
virtual StringRef segmentName() const;
|
||||
virtual void write(uint8_t *fileBuffer);
|
||||
virtual const char* info();
|
||||
void recordLoadCommand(load_command*);
|
||||
@@ -168,10 +167,9 @@ private:
|
||||
//
|
||||
class LoadCommandsChunk : public Chunk {
|
||||
public:
|
||||
LoadCommandsChunk(MachHeaderChunk&,
|
||||
const MachOTargetInfo &,
|
||||
MachOWriter&);
|
||||
virtual StringRef segmentName() const;
|
||||
LoadCommandsChunk(MachHeaderChunk &, const MachOLinkingContext &,
|
||||
MachOWriter &);
|
||||
virtual StringRef segmentName() const;
|
||||
virtual void write(uint8_t *fileBuffer);
|
||||
virtual const char* info();
|
||||
void computeSize(const lld::File &file);
|
||||
@@ -195,9 +193,9 @@ private:
|
||||
};
|
||||
|
||||
MachHeaderChunk &_mh;
|
||||
const MachOTargetInfo &_targetInfo;
|
||||
MachOWriter &_writer;
|
||||
segment_command *_linkEditSegment;
|
||||
const MachOLinkingContext &_context;
|
||||
MachOWriter &_writer;
|
||||
segment_command *_linkEditSegment;
|
||||
symtab_command *_symbolTableLoadCommand;
|
||||
entry_point_command *_entryPointLoadCommand;
|
||||
thread_command *_threadLoadCommand;
|
||||
@@ -338,7 +336,7 @@ private:
|
||||
//
|
||||
class MachOWriter : public Writer {
|
||||
public:
|
||||
MachOWriter(const MachOTargetInfo &ti);
|
||||
MachOWriter(const MachOLinkingContext &context);
|
||||
|
||||
virtual error_code writeFile(const lld::File &file, StringRef path);
|
||||
virtual void addFiles(InputFiles&);
|
||||
@@ -369,9 +367,9 @@ private:
|
||||
|
||||
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
|
||||
|
||||
const MachOTargetInfo &_targetInfo;
|
||||
mach_o::KindHandler &_referenceKindHandler;
|
||||
CRuntimeFile _cRuntimeFile;
|
||||
const MachOLinkingContext &_context;
|
||||
mach_o::KindHandler &_referenceKindHandler;
|
||||
CRuntimeFile _cRuntimeFile;
|
||||
LoadCommandsChunk *_loadCommandsChunk;
|
||||
LoadCommandPaddingChunk *_paddingChunk;
|
||||
AtomToAddress _atomToAddress;
|
||||
@@ -581,13 +579,14 @@ void SectionChunk::write(uint8_t *chunkBuffer) {
|
||||
// MachHeaderChunk
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MachHeaderChunk::MachHeaderChunk(const MachOTargetInfo &ti, const File &file) {
|
||||
MachHeaderChunk::MachHeaderChunk(const MachOLinkingContext &context,
|
||||
const File &file) {
|
||||
// Set up mach_header based on options
|
||||
_mh.magic = this->magic(ti.getCPUType());
|
||||
_mh.cputype = ti.getCPUType();
|
||||
_mh.cpusubtype = ti.getCPUSubType();
|
||||
_mh.filetype = ti.outputFileType();
|
||||
_mh.ncmds = 0;
|
||||
_mh.magic = this->magic(context.getCPUType());
|
||||
_mh.cputype = context.getCPUType();
|
||||
_mh.cpusubtype = context.getCPUSubType();
|
||||
_mh.filetype = context.outputFileType();
|
||||
_mh.ncmds = 0;
|
||||
_mh.sizeofcmds = 0;
|
||||
_mh.flags = 0;
|
||||
_mh.reserved = 0;
|
||||
@@ -635,14 +634,11 @@ uint32_t MachHeaderChunk::magic(uint32_t cpuType) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh,
|
||||
const MachOTargetInfo &ti,
|
||||
MachOWriter& writer)
|
||||
: _mh(mh), _targetInfo(ti), _writer(writer),
|
||||
_linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr),
|
||||
_entryPointLoadCommand(nullptr), _threadLoadCommand(nullptr),
|
||||
_dyldInfoLoadCommand(nullptr) {
|
||||
}
|
||||
|
||||
const MachOLinkingContext &context,
|
||||
MachOWriter &writer)
|
||||
: _mh(mh), _context(context), _writer(writer), _linkEditSegment(nullptr),
|
||||
_symbolTableLoadCommand(nullptr), _entryPointLoadCommand(nullptr),
|
||||
_threadLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) {}
|
||||
|
||||
StringRef LoadCommandsChunk::segmentName() const {
|
||||
return StringRef("__TEXT");
|
||||
@@ -685,8 +681,8 @@ uint32_t LoadCommandsChunk::permissionsFromSections(
|
||||
void LoadCommandsChunk::computeSize(const lld::File &file) {
|
||||
const bool is64 = _writer.use64BitMachO();
|
||||
// Main executables have a __PAGEZERO segment.
|
||||
uint64_t pageZeroSize = _targetInfo.pageZeroSize();
|
||||
if ( pageZeroSize != 0 ) {
|
||||
uint64_t pageZeroSize = _context.pageZeroSize();
|
||||
if (pageZeroSize != 0) {
|
||||
assert(is64 || (pageZeroSize < 0xFFFFFFFF));
|
||||
segment_command* pzSegCmd = new segment_command(0, is64);
|
||||
strcpy(pzSegCmd->segname, "__PAGEZERO");
|
||||
@@ -767,11 +763,11 @@ void LoadCommandsChunk::computeSize(const lld::File &file) {
|
||||
this->addLoadCommand(_dyldInfoLoadCommand);
|
||||
|
||||
// Add entry point load command to main executables
|
||||
if (_targetInfo.addEntryPointLoadCommand()) {
|
||||
if (_context.addEntryPointLoadCommand()) {
|
||||
_entryPointLoadCommand = new entry_point_command(is64);
|
||||
this->addLoadCommand(_entryPointLoadCommand);
|
||||
} else if (_targetInfo.addUnixThreadLoadCommand()) {
|
||||
_threadLoadCommand = new thread_command(_targetInfo.getCPUType(), is64);
|
||||
} else if (_context.addUnixThreadLoadCommand()) {
|
||||
_threadLoadCommand = new thread_command(_context.getCPUType(), is64);
|
||||
this->addLoadCommand(_threadLoadCommand);
|
||||
}
|
||||
|
||||
@@ -1265,14 +1261,11 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
|
||||
// MachOWriter
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MachOWriter::MachOWriter(const MachOTargetInfo &ti)
|
||||
: _targetInfo(ti),
|
||||
_referenceKindHandler(ti.kindHandler()),
|
||||
_cRuntimeFile(ti),
|
||||
_bindingInfo(nullptr), _lazyBindingInfo(nullptr),
|
||||
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr),
|
||||
_linkEditStartOffset(0), _linkEditStartAddress(0) {
|
||||
}
|
||||
MachOWriter::MachOWriter(const MachOLinkingContext &context)
|
||||
: _context(context), _referenceKindHandler(context.kindHandler()),
|
||||
_cRuntimeFile(context), _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
|
||||
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr),
|
||||
_linkEditStartOffset(0), _linkEditStartAddress(0) {}
|
||||
|
||||
void MachOWriter::build(const lld::File &file) {
|
||||
// Create objects for each chunk.
|
||||
@@ -1322,10 +1315,10 @@ void MachOWriter::createChunks(const lld::File &file) {
|
||||
|
||||
|
||||
// Make chunks in __TEXT for mach_header and load commands at start.
|
||||
MachHeaderChunk *mhc = new MachHeaderChunk(_targetInfo, file);
|
||||
MachHeaderChunk *mhc = new MachHeaderChunk(_context, file);
|
||||
_chunks.push_back(mhc);
|
||||
|
||||
_loadCommandsChunk = new LoadCommandsChunk(*mhc, _targetInfo, *this);
|
||||
_loadCommandsChunk = new LoadCommandsChunk(*mhc, _context, *this);
|
||||
_chunks.push_back(_loadCommandsChunk);
|
||||
|
||||
_paddingChunk = new LoadCommandPaddingChunk(*_loadCommandsChunk);
|
||||
@@ -1358,14 +1351,13 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
|
||||
void MachOWriter::buildAtomToAddressMap() {
|
||||
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
|
||||
<< "assign atom addresses:\n");
|
||||
const bool lookForEntry = _targetInfo.outputTypeHasEntry();
|
||||
for (SectionChunk *chunk : _sectionChunks ) {
|
||||
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
|
||||
const bool lookForEntry = _context.outputTypeHasEntry();
|
||||
for (SectionChunk *chunk : _sectionChunks) {
|
||||
for (const SectionChunk::AtomInfo &info : chunk->atoms()) {
|
||||
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
|
||||
if ( lookForEntry
|
||||
&& (info.atom->contentType() == DefinedAtom::typeCode)
|
||||
&& (info.atom->size() != 0)
|
||||
&& info.atom->name() == _targetInfo.entrySymbolName()) {
|
||||
if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
|
||||
(info.atom->size() != 0) &&
|
||||
info.atom->name() == _context.entrySymbolName()) {
|
||||
_entryAtom = info.atom;
|
||||
}
|
||||
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
|
||||
@@ -1388,9 +1380,9 @@ void MachOWriter::assignFileOffsets() {
|
||||
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
|
||||
<< "assign file offsets:\n");
|
||||
uint64_t offset = 0;
|
||||
uint64_t address = _targetInfo.pageZeroSize();
|
||||
for ( Chunk *chunk : _chunks ) {
|
||||
if ( chunk->segmentName().equals("__LINKEDIT") ) {
|
||||
uint64_t address = _context.pageZeroSize();
|
||||
for (Chunk *chunk : _chunks) {
|
||||
if (chunk->segmentName().equals("__LINKEDIT")) {
|
||||
_linkEditStartOffset = Chunk::alignTo(offset, 12);
|
||||
_linkEditStartAddress = Chunk::alignTo(address, 12);
|
||||
break;
|
||||
@@ -1426,8 +1418,8 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
|
||||
const uint64_t kInvalidAddress = (uint64_t)(-1);
|
||||
StringRef lastSegName("__TEXT");
|
||||
*segIndex = 0;
|
||||
if ( _targetInfo.pageZeroSize() != 0 ) {
|
||||
*segIndex = 1;
|
||||
if (_context.pageZeroSize() != 0) {
|
||||
*segIndex = 1;
|
||||
}
|
||||
*segStartAddr = kInvalidAddress;
|
||||
*segEndAddr = kInvalidAddress;
|
||||
@@ -1450,14 +1442,14 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
|
||||
}
|
||||
|
||||
bool MachOWriter::use64BitMachO() const {
|
||||
switch (_targetInfo.arch()) {
|
||||
case MachOTargetInfo::arch_x86_64:
|
||||
return true;
|
||||
case MachOTargetInfo::arch_x86:
|
||||
case MachOTargetInfo::arch_armv6:
|
||||
case MachOTargetInfo::arch_armv7:
|
||||
case MachOTargetInfo::arch_armv7s:
|
||||
return false;
|
||||
switch (_context.arch()) {
|
||||
case MachOLinkingContext::arch_x86_64:
|
||||
return true;
|
||||
case MachOLinkingContext::arch_x86:
|
||||
case MachOLinkingContext::arch_armv6:
|
||||
case MachOLinkingContext::arch_armv7:
|
||||
case MachOLinkingContext::arch_armv7s:
|
||||
return false;
|
||||
default:
|
||||
llvm_unreachable("Unknown mach-o arch");
|
||||
}
|
||||
@@ -1501,9 +1493,8 @@ void MachOWriter::addFiles(InputFiles &inputFiles) {
|
||||
|
||||
} // namespace mach_o
|
||||
|
||||
|
||||
std::unique_ptr<Writer> createWriterMachO(const MachOTargetInfo &ti) {
|
||||
return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(ti));
|
||||
std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &context) {
|
||||
return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(context));
|
||||
}
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -238,9 +238,10 @@ public:
|
||||
|
||||
/// Instantiates a File object from a native object file. Ownership
|
||||
/// of the MemoryBuffer is transfered to the resulting File object.
|
||||
static error_code make(
|
||||
const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
StringRef path, std::vector<std::unique_ptr<lld::File> > &result) {
|
||||
static error_code make(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
StringRef path,
|
||||
std::vector<std::unique_ptr<lld::File>> &result) {
|
||||
const uint8_t *const base =
|
||||
reinterpret_cast<const uint8_t *>(mb->getBufferStart());
|
||||
const NativeFileHeader* const header =
|
||||
@@ -262,7 +263,7 @@ public:
|
||||
<< header->chunkCount << "\n");
|
||||
|
||||
// instantiate NativeFile object and add values to it as found
|
||||
std::unique_ptr<File> file(new File(ti, std::move(mb), path));
|
||||
std::unique_ptr<File> file(new File(context, std::move(mb), path));
|
||||
|
||||
// process each chunk
|
||||
for (uint32_t i = 0; i < header->chunkCount; ++i) {
|
||||
@@ -367,7 +368,7 @@ public:
|
||||
virtual const atom_collection<AbsoluteAtom> &absolute() const {
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
private:
|
||||
friend NativeDefinedAtomV1;
|
||||
@@ -722,14 +723,14 @@ private:
|
||||
}
|
||||
|
||||
// private constructor, only called by make()
|
||||
File(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||
File(const LinkingContext &context, std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||
StringRef path)
|
||||
: lld::File(path, kindObject),
|
||||
_buffer(std::move(mb)), // Reader now takes ownership of buffer
|
||||
_header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
|
||||
_strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
|
||||
_addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
|
||||
_targetInfo(ti) {
|
||||
_context(context) {
|
||||
_header =
|
||||
reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
|
||||
}
|
||||
@@ -794,7 +795,7 @@ private:
|
||||
uint32_t _addendsMaxIndex;
|
||||
const uint8_t *_contentStart;
|
||||
const uint8_t *_contentEnd;
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
inline const lld::File &NativeDefinedAtomV1::file() const {
|
||||
@@ -909,18 +910,17 @@ inline void NativeReferenceV1::setAddend(Addend a) {
|
||||
|
||||
class Reader : public lld::Reader {
|
||||
public:
|
||||
Reader(const TargetInfo &ti)
|
||||
: lld::Reader(ti) {}
|
||||
Reader(const LinkingContext &context) : lld::Reader(context) {}
|
||||
|
||||
virtual error_code parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<lld::File> > &result) const {
|
||||
return File::make(_targetInfo, mb, mb->getBufferIdentifier(), result);
|
||||
virtual error_code
|
||||
parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<lld::File>> &result) const {
|
||||
return File::make(_context, mb, mb->getBufferIdentifier(), result);
|
||||
}
|
||||
};
|
||||
} // end namespace native
|
||||
|
||||
std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) {
|
||||
return std::unique_ptr<Reader>(new lld::native::Reader(ti));
|
||||
std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
|
||||
return std::unique_ptr<Reader>(new lld::native::Reader(context));
|
||||
}
|
||||
} // end namespace lld
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace native {
|
||||
///
|
||||
class Writer : public lld::Writer {
|
||||
public:
|
||||
Writer(const TargetInfo &ti) {}
|
||||
Writer(const LinkingContext &context) {}
|
||||
|
||||
virtual error_code writeFile(const lld::File &file, StringRef outPath) {
|
||||
// reserve first byte for unnamed atoms
|
||||
@@ -552,7 +552,7 @@ private:
|
||||
out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<StringRef, uint32_t> > NameToOffsetVector;
|
||||
typedef std::vector<std::pair<StringRef, uint32_t>> NameToOffsetVector;
|
||||
|
||||
typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
|
||||
typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
|
||||
@@ -579,7 +579,7 @@ private:
|
||||
};
|
||||
} // end namespace native
|
||||
|
||||
std::unique_ptr<Writer> createWriterNative(const TargetInfo &ti) {
|
||||
return std::unique_ptr<Writer>(new native::Writer(ti));
|
||||
std::unique_ptr<Writer> createWriterNative(const LinkingContext &context) {
|
||||
return std::unique_ptr<Writer>(new native::Writer(context));
|
||||
}
|
||||
} // end namespace lld
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_lld_library(lldPECOFF
|
||||
PECOFFTargetInfo.cpp
|
||||
PECOFFLinkingContext.cpp
|
||||
ReaderCOFF.cpp
|
||||
ReaderImportHeader.cpp
|
||||
WriterPECOFF.cpp
|
||||
|
||||
@@ -92,9 +92,9 @@ protected:
|
||||
/// field in the import directory table entry.
|
||||
class DLLNameAtom : public IdataAtom {
|
||||
public:
|
||||
DLLNameAtom(Context &ctx, StringRef name)
|
||||
: IdataAtom(ctx.file, stringRefToVector(name)) {
|
||||
ctx.dllNameAtoms.push_back(this);
|
||||
DLLNameAtom(Context &context, StringRef name)
|
||||
: IdataAtom(context.file, stringRefToVector(name)) {
|
||||
context.dllNameAtoms.push_back(this);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -116,10 +116,10 @@ private:
|
||||
/// loader can find the symbol quickly.
|
||||
class HintNameAtom : public IdataAtom {
|
||||
public:
|
||||
HintNameAtom(Context &ctx, uint16_t hint, StringRef importName)
|
||||
: IdataAtom(ctx.file, assembleRawContent(hint, importName)),
|
||||
HintNameAtom(Context &context, uint16_t hint, StringRef importName)
|
||||
: IdataAtom(context.file, assembleRawContent(hint, importName)),
|
||||
_importName(importName) {
|
||||
ctx.hintNameAtoms.push_back(this);
|
||||
context.hintNameAtoms.push_back(this);
|
||||
}
|
||||
|
||||
StringRef getContentString() { return _importName; }
|
||||
@@ -128,7 +128,8 @@ private:
|
||||
// The first two bytes of the content is a hint, followed by a null-terminated
|
||||
// symbol name. The total size needs to be multiple of 2.
|
||||
vector<uint8_t> assembleRawContent(uint16_t hint, StringRef importName) {
|
||||
size_t size = llvm::RoundUpToAlignment(sizeof(hint) + importName.size() + 1, 2);
|
||||
size_t size =
|
||||
llvm::RoundUpToAlignment(sizeof(hint) + importName.size() + 1, 2);
|
||||
vector<uint8_t> ret(size);
|
||||
ret[importName.size()] = 0;
|
||||
ret[importName.size() - 1] = 0;
|
||||
@@ -142,8 +143,8 @@ private:
|
||||
|
||||
class ImportTableEntryAtom : public IdataAtom {
|
||||
public:
|
||||
explicit ImportTableEntryAtom(Context &ctx, uint32_t contents)
|
||||
: IdataAtom(ctx.file, assembleRawContent(contents)) {}
|
||||
explicit ImportTableEntryAtom(Context &context, uint32_t contents)
|
||||
: IdataAtom(context.file, assembleRawContent(contents)) {}
|
||||
|
||||
private:
|
||||
vector<uint8_t> assembleRawContent(uint32_t contents) {
|
||||
@@ -159,38 +160,40 @@ private:
|
||||
/// items. The executable has one ImportDirectoryAtom per one imported DLL.
|
||||
class ImportDirectoryAtom : public IdataAtom {
|
||||
public:
|
||||
ImportDirectoryAtom(Context &ctx, StringRef loadName,
|
||||
ImportDirectoryAtom(Context &context, StringRef loadName,
|
||||
const vector<COFFSharedLibraryAtom *> &sharedAtoms)
|
||||
: IdataAtom(ctx.file, vector<uint8_t>(20, 0)) {
|
||||
addRelocations(ctx, loadName, sharedAtoms);
|
||||
ctx.importDirectories.push_back(this);
|
||||
: IdataAtom(context.file, vector<uint8_t>(20, 0)) {
|
||||
addRelocations(context, loadName, sharedAtoms);
|
||||
context.importDirectories.push_back(this);
|
||||
}
|
||||
|
||||
private:
|
||||
void addRelocations(Context &ctx, StringRef loadName,
|
||||
void addRelocations(Context &context, StringRef loadName,
|
||||
const vector<COFFSharedLibraryAtom *> &sharedAtoms) {
|
||||
size_t lookupEnd = ctx.importLookupTables.size();
|
||||
size_t addressEnd = ctx.importAddressTables.size();
|
||||
size_t lookupEnd = context.importLookupTables.size();
|
||||
size_t addressEnd = context.importAddressTables.size();
|
||||
|
||||
// Create parallel arrays. The contents of the two are initially the
|
||||
// same. The PE/COFF loader overwrites the import address tables with the
|
||||
// pointers to the referenced items after loading the executable into
|
||||
// memory.
|
||||
addImportTableAtoms(ctx, sharedAtoms, false, ctx.importLookupTables);
|
||||
addImportTableAtoms(ctx, sharedAtoms, true, ctx.importAddressTables);
|
||||
addImportTableAtoms(context, sharedAtoms, false,
|
||||
context.importLookupTables);
|
||||
addImportTableAtoms(context, sharedAtoms, true,
|
||||
context.importAddressTables);
|
||||
|
||||
addDir32NBReloc(this, ctx.importLookupTables[lookupEnd],
|
||||
addDir32NBReloc(this, context.importLookupTables[lookupEnd],
|
||||
offsetof(ImportDirectoryTableEntry, ImportLookupTableRVA));
|
||||
addDir32NBReloc(this, ctx.importAddressTables[addressEnd],
|
||||
addDir32NBReloc(this, context.importAddressTables[addressEnd],
|
||||
offsetof(ImportDirectoryTableEntry, ImportAddressTableRVA));
|
||||
addDir32NBReloc(this, new (_alloc) DLLNameAtom(ctx, loadName),
|
||||
addDir32NBReloc(this, new (_alloc) DLLNameAtom(context, loadName),
|
||||
offsetof(ImportDirectoryTableEntry, NameRVA));
|
||||
}
|
||||
|
||||
// Creates atoms for an import lookup table. The import lookup table is an
|
||||
// array of pointers to hint/name atoms. The array needs to be terminated with
|
||||
// the NULL entry.
|
||||
void addImportTableAtoms(Context &ctx,
|
||||
void addImportTableAtoms(Context &context,
|
||||
const vector<COFFSharedLibraryAtom *> &sharedAtoms,
|
||||
bool shouldAddReference,
|
||||
vector<ImportTableEntryAtom *> &ret) const {
|
||||
@@ -199,11 +202,11 @@ private:
|
||||
if (atom->importName().empty()) {
|
||||
// Import by ordinal
|
||||
uint32_t hint = (1U << 31) | atom->hint();
|
||||
entry = new (_alloc) ImportTableEntryAtom(ctx, hint);
|
||||
entry = new (_alloc) ImportTableEntryAtom(context, hint);
|
||||
} else {
|
||||
// Import by name
|
||||
entry = new (_alloc) ImportTableEntryAtom(ctx, 0);
|
||||
HintNameAtom *hintName = createHintNameAtom(ctx, atom);
|
||||
entry = new (_alloc) ImportTableEntryAtom(context, 0);
|
||||
HintNameAtom *hintName = createHintNameAtom(context, atom);
|
||||
addDir32NBReloc(entry, hintName);
|
||||
}
|
||||
ret.push_back(entry);
|
||||
@@ -211,12 +214,12 @@ private:
|
||||
atom->setImportTableEntry(entry);
|
||||
}
|
||||
// Add the NULL entry.
|
||||
ret.push_back(new (_alloc) ImportTableEntryAtom(ctx, 0));
|
||||
ret.push_back(new (_alloc) ImportTableEntryAtom(context, 0));
|
||||
}
|
||||
|
||||
HintNameAtom *createHintNameAtom(
|
||||
Context &ctx, const COFFSharedLibraryAtom *atom) const {
|
||||
return new (_alloc) HintNameAtom(ctx, atom->hint(), atom->importName());
|
||||
HintNameAtom *createHintNameAtom(Context &context,
|
||||
const COFFSharedLibraryAtom *atom) const {
|
||||
return new (_alloc) HintNameAtom(context, atom->hint(), atom->importName());
|
||||
}
|
||||
|
||||
mutable llvm::BumpPtrAllocator _alloc;
|
||||
@@ -225,9 +228,9 @@ private:
|
||||
/// The last NULL entry in the import directory.
|
||||
class NullImportDirectoryAtom : public IdataAtom {
|
||||
public:
|
||||
explicit NullImportDirectoryAtom(Context &ctx)
|
||||
: IdataAtom(ctx.file, vector<uint8_t>(20, 0)) {
|
||||
ctx.importDirectories.push_back(this);
|
||||
explicit NullImportDirectoryAtom(Context &context)
|
||||
: IdataAtom(context.file, vector<uint8_t>(20, 0)) {
|
||||
context.importDirectories.push_back(this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -239,18 +242,18 @@ public:
|
||||
if (file.sharedLibrary().size() == 0)
|
||||
return;
|
||||
|
||||
Context ctx(file);
|
||||
map<StringRef, vector<COFFSharedLibraryAtom *>> sharedAtoms =
|
||||
Context context(file);
|
||||
map<StringRef, vector<COFFSharedLibraryAtom *> > sharedAtoms =
|
||||
groupByLoadName(file);
|
||||
for (auto i : sharedAtoms) {
|
||||
StringRef loadName = i.first;
|
||||
vector<COFFSharedLibraryAtom *> &atoms = i.second;
|
||||
createImportDirectory(ctx, loadName, atoms);
|
||||
createImportDirectory(context, loadName, atoms);
|
||||
}
|
||||
new (_alloc) NullImportDirectoryAtom(ctx);
|
||||
connectAtoms(ctx);
|
||||
createDataDirectoryAtoms(ctx);
|
||||
replaceSharedLibraryAtoms(ctx);
|
||||
new (_alloc) NullImportDirectoryAtom(context);
|
||||
connectAtoms(context);
|
||||
createDataDirectoryAtoms(context);
|
||||
replaceSharedLibraryAtoms(context);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -268,18 +271,17 @@ private:
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
void
|
||||
createImportDirectory(Context &ctx, StringRef loadName,
|
||||
vector<COFFSharedLibraryAtom *> &dllAtoms) {
|
||||
new (_alloc) ImportDirectoryAtom(ctx, loadName, dllAtoms);
|
||||
void createImportDirectory(Context &context, StringRef loadName,
|
||||
vector<COFFSharedLibraryAtom *> &dllAtoms) {
|
||||
new (_alloc) ImportDirectoryAtom(context, loadName, dllAtoms);
|
||||
}
|
||||
|
||||
void connectAtoms(Context &ctx) {
|
||||
coff::connectAtomsWithLayoutEdge(ctx.importDirectories);
|
||||
coff::connectAtomsWithLayoutEdge(ctx.importLookupTables);
|
||||
coff::connectAtomsWithLayoutEdge(ctx.importAddressTables);
|
||||
coff::connectAtomsWithLayoutEdge(ctx.hintNameAtoms);
|
||||
coff::connectAtomsWithLayoutEdge(ctx.dllNameAtoms);
|
||||
void connectAtoms(Context &context) {
|
||||
coff::connectAtomsWithLayoutEdge(context.importDirectories);
|
||||
coff::connectAtomsWithLayoutEdge(context.importLookupTables);
|
||||
coff::connectAtomsWithLayoutEdge(context.importAddressTables);
|
||||
coff::connectAtomsWithLayoutEdge(context.hintNameAtoms);
|
||||
coff::connectAtomsWithLayoutEdge(context.dllNameAtoms);
|
||||
}
|
||||
|
||||
/// The addresses of the import dirctory and the import address table needs to
|
||||
@@ -287,23 +289,25 @@ private:
|
||||
/// represents an entry in the data directory header. We create atoms of class
|
||||
/// COFFDataDirectoryAtom and set relocations to them, so that the address
|
||||
/// will be set by the writer.
|
||||
void createDataDirectoryAtoms(Context &ctx) {
|
||||
void createDataDirectoryAtoms(Context &context) {
|
||||
auto *dir = new (_alloc) coff::COFFDataDirectoryAtom(
|
||||
ctx.file, llvm::COFF::DataDirectoryIndex::IMPORT_TABLE,
|
||||
ctx.importDirectories.size() * ctx.importDirectories[0]->size());
|
||||
addDir32NBReloc(dir, ctx.importDirectories[0]);
|
||||
ctx.file.addAtom(*dir);
|
||||
context.file, llvm::COFF::DataDirectoryIndex::IMPORT_TABLE,
|
||||
context.importDirectories.size() *
|
||||
context.importDirectories[0]->size());
|
||||
addDir32NBReloc(dir, context.importDirectories[0]);
|
||||
context.file.addAtom(*dir);
|
||||
|
||||
auto *iat = new (_alloc) coff::COFFDataDirectoryAtom(
|
||||
ctx.file, llvm::COFF::DataDirectoryIndex::IAT,
|
||||
ctx.importAddressTables.size() * ctx.importAddressTables[0]->size());
|
||||
addDir32NBReloc(iat, ctx.importAddressTables[0]);
|
||||
ctx.file.addAtom(*iat);
|
||||
context.file, llvm::COFF::DataDirectoryIndex::IAT,
|
||||
context.importAddressTables.size() *
|
||||
context.importAddressTables[0]->size());
|
||||
addDir32NBReloc(iat, context.importAddressTables[0]);
|
||||
context.file.addAtom(*iat);
|
||||
}
|
||||
|
||||
/// Transforms a reference to a COFFSharedLibraryAtom to a real reference.
|
||||
void replaceSharedLibraryAtoms(Context &ctx) {
|
||||
for (const DefinedAtom *atom : ctx.file.defined()) {
|
||||
void replaceSharedLibraryAtoms(Context &context) {
|
||||
for (const DefinedAtom *atom : context.file.defined()) {
|
||||
for (const Reference *ref : *atom) {
|
||||
const Atom *target = ref->target();
|
||||
auto *sharedAtom = dyn_cast<SharedLibraryAtom>(target);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//===- lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp -----------------------===//
|
||||
//===- lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp -------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Passes/LayoutPass.h"
|
||||
#include "lld/ReaderWriter/PECOFFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Simple.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
@@ -37,26 +37,26 @@ bool containDirectoryName(StringRef path) {
|
||||
/// symbols.
|
||||
class UndefinedSymbolFile : public SimpleFile {
|
||||
public:
|
||||
UndefinedSymbolFile(const TargetInfo &ti)
|
||||
UndefinedSymbolFile(const LinkingContext &ti)
|
||||
: SimpleFile(ti, "Linker Internal File") {
|
||||
for (StringRef symbol : ti.initialUndefinedSymbols()) {
|
||||
UndefinedAtom *atom = new (_alloc) coff::COFFUndefinedAtom(*this, symbol);
|
||||
addAtom(*atom);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::BumpPtrAllocator _alloc;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
error_code PECOFFTargetInfo::parseFile(
|
||||
error_code PECOFFLinkingContext::parseFile(
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
return _reader->parseFile(mb, result);
|
||||
}
|
||||
|
||||
bool PECOFFTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
||||
if (_inputFiles.empty()) {
|
||||
diagnostics << "No input files\n";
|
||||
return true;
|
||||
@@ -64,15 +64,15 @@ bool PECOFFTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
|
||||
if (_stackReserve < _stackCommit) {
|
||||
diagnostics << "Invalid stack size: reserve size must be equal to or "
|
||||
<< "greater than commit size, but got "
|
||||
<< _stackCommit << " and " << _stackReserve << ".\n";
|
||||
<< "greater than commit size, but got " << _stackCommit
|
||||
<< " and " << _stackReserve << ".\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_heapReserve < _heapCommit) {
|
||||
diagnostics << "Invalid heap size: reserve size must be equal to or "
|
||||
<< "greater than commit size, but got "
|
||||
<< _heapCommit << " and " << _heapReserve << ".\n";
|
||||
<< "greater than commit size, but got " << _heapCommit
|
||||
<< " and " << _heapReserve << ".\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ bool PECOFFTargetInfo::validateImpl(raw_ostream &diagnostics) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PECOFFTargetInfo::addImplicitFiles(InputFiles &files) const {
|
||||
void PECOFFLinkingContext::addImplicitFiles(InputFiles &files) const {
|
||||
// Add a pseudo file for "/include" linker option.
|
||||
auto *file = new (_alloc) UndefinedSymbolFile(*this);
|
||||
files.prependFile(*file);
|
||||
@@ -89,7 +89,7 @@ void PECOFFTargetInfo::addImplicitFiles(InputFiles &files) const {
|
||||
|
||||
/// Append the given file to the input file list. The file must be an object
|
||||
/// file or an import library file.
|
||||
void PECOFFTargetInfo::appendInputFileOrLibrary(std::string path) {
|
||||
void PECOFFLinkingContext::appendInputFileOrLibrary(std::string path) {
|
||||
StringRef ext = llvm::sys::path::extension(path);
|
||||
// This is an import library file. Look for the library file in the search
|
||||
// paths, unless the path contains a directory name.
|
||||
@@ -110,7 +110,7 @@ void PECOFFTargetInfo::appendInputFileOrLibrary(std::string path) {
|
||||
|
||||
/// Try to find the input library file from the search paths and append it to
|
||||
/// the input file list. Returns true if the library file is found.
|
||||
void PECOFFTargetInfo::appendLibraryFile(StringRef filename) {
|
||||
void PECOFFLinkingContext::appendLibraryFile(StringRef filename) {
|
||||
// Current directory always takes precedence over the search paths.
|
||||
if (llvm::sys::fs::exists(filename)) {
|
||||
appendInputFile(filename);
|
||||
@@ -128,21 +128,19 @@ void PECOFFTargetInfo::appendLibraryFile(StringRef filename) {
|
||||
appendInputFile(filename);
|
||||
}
|
||||
|
||||
Writer &PECOFFTargetInfo::writer() const {
|
||||
return *_writer;
|
||||
}
|
||||
Writer &PECOFFLinkingContext::writer() const { return *_writer; }
|
||||
|
||||
ErrorOr<Reference::Kind>
|
||||
PECOFFTargetInfo::relocKindFromString(StringRef str) const {
|
||||
PECOFFLinkingContext::relocKindFromString(StringRef str) const {
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
|
||||
ErrorOr<std::string>
|
||||
PECOFFTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
|
||||
PECOFFLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
|
||||
void PECOFFTargetInfo::addPasses(PassManager &pm) const {
|
||||
void PECOFFLinkingContext::addPasses(PassManager &pm) const {
|
||||
pm.add(std::unique_ptr<Pass>(new pecoff::GroupedSectionsPass()));
|
||||
pm.add(std::unique_ptr<Pass>(new pecoff::IdataPass()));
|
||||
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
|
||||
@@ -84,13 +84,13 @@ private:
|
||||
typedef vector<const coff_symbol *> SymbolVectorT;
|
||||
typedef std::map<const coff_section *, SymbolVectorT> SectionToSymbolsT;
|
||||
typedef std::map<const StringRef, Atom *> SymbolNameToAtomT;
|
||||
typedef std::map<const coff_section *, vector<COFFDefinedFileAtom *> >
|
||||
SectionToAtomsT;
|
||||
typedef std::map<const coff_section *, vector<COFFDefinedFileAtom *>>
|
||||
SectionToAtomsT;
|
||||
|
||||
public:
|
||||
FileCOFF(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||
error_code &ec)
|
||||
: File(mb->getBufferIdentifier(), kindObject), _targetInfo(ti) {
|
||||
FileCOFF(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb, error_code &ec)
|
||||
: File(mb->getBufferIdentifier(), kindObject), _context(context) {
|
||||
llvm::OwningPtr<llvm::object::Binary> bin;
|
||||
ec = llvm::object::createBinary(mb.release(), bin);
|
||||
if (ec)
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
StringRef getLinkerDirectives() const { return _directives; }
|
||||
|
||||
@@ -525,7 +525,7 @@ private:
|
||||
std::map<uint32_t, COFFDefinedAtom *>> _definedAtomLocations;
|
||||
|
||||
mutable llvm::BumpPtrAllocator _alloc;
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
class BumpPtrStringSaver : public llvm::cl::StringSaver {
|
||||
@@ -543,18 +543,18 @@ private:
|
||||
|
||||
class ReaderCOFF : public Reader {
|
||||
public:
|
||||
explicit ReaderCOFF(const TargetInfo &ti)
|
||||
: Reader(ti), _readerArchive(ti, *this) {}
|
||||
explicit ReaderCOFF(const LinkingContext &context)
|
||||
: Reader(context), _readerArchive(context, *this) {}
|
||||
|
||||
error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const {
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
StringRef magic(mb->getBufferStart(), mb->getBufferSize());
|
||||
llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(magic);
|
||||
if (fileType == llvm::sys::fs::file_magic::coff_object)
|
||||
return parseCOFFFile(mb, result);
|
||||
if (fileType == llvm::sys::fs::file_magic::archive)
|
||||
return _readerArchive.parseFile(mb, result);
|
||||
return lld::coff::parseCOFFImportLibrary(_targetInfo, mb, result);
|
||||
return lld::coff::parseCOFFImportLibrary(_context, mb, result);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -569,10 +569,11 @@ private:
|
||||
llvm::dbgs() << ".drectve: " << directives << "\n";
|
||||
});
|
||||
|
||||
// Remove const from _targetInfo.
|
||||
// FIXME: Rename TargetInfo -> LinkingContext and treat it a mutable object
|
||||
// Remove const from _context.
|
||||
// FIXME: Rename LinkingContext -> LinkingContext and treat it a mutable
|
||||
// object
|
||||
// in the core linker.
|
||||
PECOFFTargetInfo *targetInfo = (PECOFFTargetInfo *)&_targetInfo;
|
||||
PECOFFLinkingContext *targetInfo = (PECOFFLinkingContext *)&_context;
|
||||
|
||||
// Split the string into tokens, as the shell would do for argv.
|
||||
SmallVector<const char *, 16> tokens;
|
||||
@@ -601,11 +602,10 @@ private:
|
||||
}
|
||||
|
||||
error_code parseCOFFFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const {
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
// Parse the memory buffer as PECOFF file.
|
||||
error_code ec;
|
||||
std::unique_ptr<FileCOFF> file(
|
||||
new FileCOFF(_targetInfo, std::move(mb), ec));
|
||||
std::unique_ptr<FileCOFF> file(new FileCOFF(_context, std::move(mb), ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
@@ -635,8 +635,7 @@ private:
|
||||
} // end namespace anonymous
|
||||
|
||||
namespace lld {
|
||||
std::unique_ptr<Reader> createReaderPECOFF(const TargetInfo & ti) {
|
||||
return std::unique_ptr<Reader>(new ReaderCOFF(ti));
|
||||
std::unique_ptr<Reader> createReaderPECOFF(const LinkingContext &context) {
|
||||
return std::unique_ptr<Reader>(new ReaderCOFF(context));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -181,10 +181,10 @@ std::vector<uint8_t> FuncAtom::rawContent(
|
||||
|
||||
class FileImportLibrary : public File {
|
||||
public:
|
||||
FileImportLibrary(const TargetInfo &ti,
|
||||
FileImportLibrary(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||
llvm::error_code &ec)
|
||||
: File(mb->getBufferIdentifier(), kindSharedLibrary), _targetInfo(ti) {
|
||||
: File(mb->getBufferIdentifier(), kindSharedLibrary), _context(context) {
|
||||
const char *buf = mb->getBufferStart();
|
||||
const char *end = mb->getBufferEnd();
|
||||
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
private:
|
||||
const COFFSharedLibraryAtom *
|
||||
@@ -263,7 +263,7 @@ private:
|
||||
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
mutable llvm::BumpPtrAllocator _alloc;
|
||||
|
||||
// Convert the given symbol name to the import symbol name exported by the
|
||||
@@ -295,9 +295,9 @@ private:
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
error_code parseCOFFImportLibrary(const TargetInfo &targetInfo,
|
||||
error_code parseCOFFImportLibrary(const LinkingContext &targetInfo,
|
||||
std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) {
|
||||
std::vector<std::unique_ptr<File>> &result) {
|
||||
// Check the file magic.
|
||||
const char *buf = mb->getBufferStart();
|
||||
const char *end = mb->getBufferEnd();
|
||||
|
||||
@@ -19,15 +19,15 @@ class error_code;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
class TargetInfo;
|
||||
class LinkingContext;
|
||||
class File;
|
||||
|
||||
namespace coff {
|
||||
|
||||
llvm::error_code
|
||||
parseCOFFImportLibrary(const TargetInfo &targetInfo,
|
||||
std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result);
|
||||
parseCOFFImportLibrary(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/ReaderWriter/AtomLayout.h"
|
||||
#include "lld/ReaderWriter/PECOFFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
@@ -137,7 +137,7 @@ private:
|
||||
/// A PEHeaderChunk represents PE header including COFF header.
|
||||
class PEHeaderChunk : public HeaderChunk {
|
||||
public:
|
||||
explicit PEHeaderChunk(const PECOFFTargetInfo &targetInfo) : HeaderChunk() {
|
||||
explicit PEHeaderChunk(const PECOFFLinkingContext &context) : HeaderChunk() {
|
||||
// Set the size of the chunk and initialize the header with null bytes.
|
||||
_size = sizeof(llvm::COFF::PEMagic) + sizeof(_coffHeader)
|
||||
+ sizeof(_peHeader);
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
// Attributes of the executable.
|
||||
uint16_t characteristics = llvm::COFF::IMAGE_FILE_32BIT_MACHINE |
|
||||
llvm::COFF::IMAGE_FILE_EXECUTABLE_IMAGE;
|
||||
if (targetInfo.getLargeAddressAware())
|
||||
if (context.getLargeAddressAware())
|
||||
characteristics |= llvm::COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE;
|
||||
_coffHeader.Characteristics = characteristics;
|
||||
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
|
||||
// The address of the executable when loaded into memory. The default for
|
||||
// DLLs is 0x10000000. The default for executables is 0x400000.
|
||||
_peHeader.ImageBase = targetInfo.getBaseAddress();
|
||||
_peHeader.ImageBase = context.getBaseAddress();
|
||||
|
||||
// Sections should be page-aligned when loaded into memory, which is 4KB on
|
||||
// x86.
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
// The required Windows version number. This is the internal version and
|
||||
// shouldn't be confused with product name. Windows 7 is version 6.1 and
|
||||
// Windows 8 is 6.2, for example.
|
||||
PECOFFTargetInfo::OSVersion minOSVersion = targetInfo.getMinOSVersion();
|
||||
PECOFFLinkingContext::OSVersion minOSVersion = context.getMinOSVersion();
|
||||
_peHeader.MajorOperatingSystemVersion = minOSVersion.majorVersion;
|
||||
_peHeader.MinorOperatingSystemVersion = minOSVersion.minorVersion;
|
||||
_peHeader.MajorSubsystemVersion = minOSVersion.majorVersion;
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
// between the end of the header and the beginning of the first section.
|
||||
// Must be multiple of FileAlignment.
|
||||
_peHeader.SizeOfHeaders = 512;
|
||||
_peHeader.Subsystem = targetInfo.getSubsystem();
|
||||
_peHeader.Subsystem = context.getSubsystem();
|
||||
|
||||
// Despite its name, DLL characteristics field has meaning both for
|
||||
// executables and DLLs. We are not very sure if the following bits must
|
||||
@@ -196,19 +196,19 @@ public:
|
||||
// them.
|
||||
uint16_t dllCharacteristics =
|
||||
llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_SEH;
|
||||
if (targetInfo.isTerminalServerAware())
|
||||
if (context.isTerminalServerAware())
|
||||
dllCharacteristics |=
|
||||
llvm::COFF::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
|
||||
if (targetInfo.isNxCompat())
|
||||
if (context.isNxCompat())
|
||||
dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
|
||||
if (targetInfo.getBaseRelocationEnabled())
|
||||
if (context.getBaseRelocationEnabled())
|
||||
dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
|
||||
_peHeader.DLLCharacteristics = dllCharacteristics;
|
||||
|
||||
_peHeader.SizeOfStackReserve = targetInfo.getStackReserve();
|
||||
_peHeader.SizeOfStackCommit = targetInfo.getStackCommit();
|
||||
_peHeader.SizeOfHeapReserve = targetInfo.getHeapReserve();
|
||||
_peHeader.SizeOfHeapCommit = targetInfo.getHeapCommit();
|
||||
_peHeader.SizeOfStackReserve = context.getStackReserve();
|
||||
_peHeader.SizeOfStackCommit = context.getStackCommit();
|
||||
_peHeader.SizeOfHeapReserve = context.getHeapReserve();
|
||||
_peHeader.SizeOfHeapCommit = context.getHeapCommit();
|
||||
|
||||
// The number of data directory entries. We always have 16 entries.
|
||||
_peHeader.NumberOfRvaAndSize = 16;
|
||||
@@ -727,15 +727,15 @@ private:
|
||||
|
||||
class ExecutableWriter : public Writer {
|
||||
public:
|
||||
explicit ExecutableWriter(const PECOFFTargetInfo &targetInfo)
|
||||
: _PECOFFTargetInfo(targetInfo), _numSections(0),
|
||||
_imageSizeInMemory(PAGE_SIZE), _imageSizeOnDisk(0) {}
|
||||
explicit ExecutableWriter(const PECOFFLinkingContext &context)
|
||||
: _PECOFFLinkingContext(context), _numSections(0),
|
||||
_imageSizeInMemory(PAGE_SIZE), _imageSizeOnDisk(0) {}
|
||||
|
||||
// Create all chunks that consist of the output file.
|
||||
void build(const File &linkedFile) {
|
||||
// Create file chunks and add them to the list.
|
||||
auto *dosStub = new DOSStubChunk();
|
||||
auto *peHeader = new PEHeaderChunk(_PECOFFTargetInfo);
|
||||
auto *peHeader = new PEHeaderChunk(_PECOFFLinkingContext);
|
||||
auto *dataDirectory = new DataDirectoryChunk(linkedFile);
|
||||
auto *sectionTable = new SectionHeaderTableChunk();
|
||||
auto *text = new TextSectionChunk(linkedFile);
|
||||
@@ -743,7 +743,7 @@ public:
|
||||
auto *data = new DataSectionChunk(linkedFile);
|
||||
auto *bss = new BssSectionChunk(linkedFile);
|
||||
BaseRelocChunk *baseReloc = nullptr;
|
||||
if (_PECOFFTargetInfo.getBaseRelocationEnabled())
|
||||
if (_PECOFFLinkingContext.getBaseRelocationEnabled())
|
||||
baseReloc = new BaseRelocChunk(linkedFile);
|
||||
|
||||
addChunk(dosStub);
|
||||
@@ -818,7 +818,7 @@ private:
|
||||
for (auto &cp : _chunks)
|
||||
if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
|
||||
chunk->applyRelocations(bufferStart, atomRva,
|
||||
_PECOFFTargetInfo.getBaseAddress());
|
||||
_PECOFFLinkingContext.getBaseAddress());
|
||||
}
|
||||
|
||||
void addChunk(Chunk *chunk) {
|
||||
@@ -851,7 +851,7 @@ private:
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Chunk>> _chunks;
|
||||
const PECOFFTargetInfo &_PECOFFTargetInfo;
|
||||
const PECOFFLinkingContext &_PECOFFLinkingContext;
|
||||
uint32_t _numSections;
|
||||
|
||||
// The size of the image in memory. This is initialized with PAGE_SIZE, as the
|
||||
@@ -870,7 +870,7 @@ private:
|
||||
|
||||
} // end namespace pecoff
|
||||
|
||||
std::unique_ptr<Writer> createWriterPECOFF(const PECOFFTargetInfo &info) {
|
||||
std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &info) {
|
||||
return std::unique_ptr<Writer>(new pecoff::ExecutableWriter(info));
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
OwningPtr<MemoryBuffer> buff;
|
||||
if (ci->getMemoryBuffer(buff, true))
|
||||
return nullptr;
|
||||
if (_targetInfo.logInputFiles())
|
||||
if (_context.logInputFiles())
|
||||
llvm::outs() << buff->getBufferIdentifier() << "\n";
|
||||
std::unique_ptr<MemoryBuffer> mb(buff.take());
|
||||
if (_targetInfo.parseFile(mb, result))
|
||||
if (_context.parseFile(mb, result))
|
||||
return nullptr;
|
||||
|
||||
assert(result.size() == 1);
|
||||
@@ -131,9 +131,9 @@ private:
|
||||
|
||||
public:
|
||||
/// only subclasses of ArchiveLibraryFile can be instantiated
|
||||
FileArchive(const TargetInfo &ti,
|
||||
FileArchive(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb, error_code &ec)
|
||||
: ArchiveLibraryFile(ti, mb->getBufferIdentifier()) {
|
||||
: ArchiveLibraryFile(context, mb->getBufferIdentifier()) {
|
||||
std::unique_ptr<llvm::object::Archive> archive_obj(
|
||||
new llvm::object::Archive(mb.release(), ec));
|
||||
if (ec)
|
||||
@@ -163,7 +163,7 @@ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
error_code ec;
|
||||
|
||||
if (_targetInfo.forceLoadAllArchives()) {
|
||||
if (_context.forceLoadAllArchives()) {
|
||||
_archive.reset(new llvm::object::Archive(mb.release(), ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
@@ -174,14 +174,14 @@ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
if ((ec = mf->getMemoryBuffer(buff, true)))
|
||||
return ec;
|
||||
std::unique_ptr<MemoryBuffer> mbc(buff.take());
|
||||
if (_targetInfo.logInputFiles())
|
||||
if (_context.logInputFiles())
|
||||
llvm::outs() << buff->getBufferIdentifier() << "\n";
|
||||
if ((ec = _targetInfo.parseFile(mbc, result)))
|
||||
if ((ec = _context.parseFile(mbc, result)))
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
std::unique_ptr<File> f;
|
||||
f.reset(new FileArchive(_targetInfo, std::move(mb), ec));
|
||||
f.reset(new FileArchive(_context, std::move(mb), ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
|
||||
@@ -19,10 +19,11 @@ using namespace script;
|
||||
namespace {
|
||||
class LinkerScriptFile : public File {
|
||||
public:
|
||||
static ErrorOr<std::unique_ptr<LinkerScriptFile> >
|
||||
create(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
static ErrorOr<std::unique_ptr<LinkerScriptFile>>
|
||||
create(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
std::unique_ptr<LinkerScriptFile> file(
|
||||
new LinkerScriptFile(ti, std::move(mb)));
|
||||
new LinkerScriptFile(context, std::move(mb)));
|
||||
file->_script = file->_parser.parse();
|
||||
if (!file->_script)
|
||||
return linker_script_reader_error::parse_error;
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
_ordinal = ordinal++;
|
||||
}
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||
virtual const LinkingContext &getLinkingContext() const { return _context; }
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
return _definedAtoms;
|
||||
@@ -60,14 +61,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
LinkerScriptFile(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb)
|
||||
: File(mb->getBufferIdentifier(), kindLinkerScript),
|
||||
_targetInfo(ti),
|
||||
_lexer(std::move(mb)),
|
||||
_parser(_lexer),
|
||||
_script(nullptr) {}
|
||||
LinkerScriptFile(const LinkingContext &context,
|
||||
std::unique_ptr<llvm::MemoryBuffer> mb)
|
||||
: File(mb->getBufferIdentifier(), kindLinkerScript), _context(context),
|
||||
_lexer(std::move(mb)), _parser(_lexer), _script(nullptr) {}
|
||||
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
@@ -79,10 +78,10 @@ private:
|
||||
} // end anon namespace
|
||||
|
||||
namespace lld {
|
||||
error_code
|
||||
ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File> > &result) const {
|
||||
auto lsf = LinkerScriptFile::create(_targetInfo, std::move(mb));
|
||||
error_code ReaderLinkerScript::parseFile(
|
||||
std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
auto lsf = LinkerScriptFile::create(_context, std::move(mb));
|
||||
if (!lsf)
|
||||
return lsf;
|
||||
const LinkerScript *ls = (*lsf)->getScript();
|
||||
@@ -90,7 +89,7 @@ ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
|
||||
for (const auto &c : ls->_commands) {
|
||||
if (auto group = dyn_cast<Group>(c))
|
||||
for (const auto &path : group->getPaths()) {
|
||||
if (error_code ec = _targetInfo.readFile(path._path, result))
|
||||
if (error_code ec = _context.readFile(path._path, result))
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,11 @@ namespace {
|
||||
/// supplies contextual information.
|
||||
class ContextInfo {
|
||||
public:
|
||||
ContextInfo(const TargetInfo &ti) : _currentFile(nullptr), _targetInfo(ti) {}
|
||||
ContextInfo(const LinkingContext &context)
|
||||
: _currentFile(nullptr), _context(context) {}
|
||||
|
||||
lld::File *_currentFile;
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
/// Used when writing yaml files.
|
||||
@@ -300,7 +301,7 @@ struct ScalarTraits<RefKind> {
|
||||
out << "in-group";
|
||||
break;
|
||||
default:
|
||||
if (auto relocStr = info->_targetInfo.stringFromRelocKind(value))
|
||||
if (auto relocStr = info->_context.stringFromRelocKind(value))
|
||||
out << *relocStr;
|
||||
else
|
||||
out << "<unknown>";
|
||||
@@ -311,7 +312,7 @@ struct ScalarTraits<RefKind> {
|
||||
static StringRef input(StringRef scalar, void *ctxt, RefKind &value) {
|
||||
assert(ctxt != nullptr);
|
||||
ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
|
||||
auto relocKind = info->_targetInfo.relocKindFromString(scalar);
|
||||
auto relocKind = info->_context.relocKindFromString(scalar);
|
||||
if (!relocKind) {
|
||||
if (scalar.equals("layout-after")) {
|
||||
value = lld::Reference::kindLayoutAfter;
|
||||
@@ -615,9 +616,8 @@ struct ScalarTraits<ImplicitHex8> {
|
||||
|
||||
|
||||
// YAML conversion for std::vector<const lld::File*>
|
||||
template<>
|
||||
struct DocumentListTraits< std::vector<const lld::File*> > {
|
||||
static size_t size(IO &io, std::vector<const lld::File*> &seq) {
|
||||
template <> struct DocumentListTraits<std::vector<const lld::File *>> {
|
||||
static size_t size(IO &io, std::vector<const lld::File *> &seq) {
|
||||
return seq.size();
|
||||
}
|
||||
static const lld::File *&element(IO &io, std::vector<const lld::File*> &seq,
|
||||
@@ -636,12 +636,10 @@ struct MappingTraits<const lld::File*> {
|
||||
class NormArchiveFile : public lld::ArchiveLibraryFile {
|
||||
public:
|
||||
NormArchiveFile(IO &io)
|
||||
: ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo,
|
||||
""),
|
||||
_path() {
|
||||
}
|
||||
: ArchiveLibraryFile(((ContextInfo *)io.getContext())->_context, ""),
|
||||
_path() {}
|
||||
NormArchiveFile(IO &io, const lld::File *file)
|
||||
: ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo,
|
||||
: ArchiveLibraryFile(((ContextInfo *)io.getContext())->_context,
|
||||
file->path()),
|
||||
_path(file->path()) {
|
||||
// If we want to support writing archives, this constructor would
|
||||
@@ -725,8 +723,8 @@ struct MappingTraits<const lld::File*> {
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
|
||||
virtual const TargetInfo &getTargetInfo() const {
|
||||
return ((ContextInfo *)_IO.getContext())->_targetInfo;
|
||||
virtual const LinkingContext &getLinkingContext() const {
|
||||
return ((ContextInfo *)_IO.getContext())->_context;
|
||||
}
|
||||
|
||||
// Allocate a new copy of this string and keep track of allocations
|
||||
@@ -1314,7 +1312,7 @@ namespace yaml {
|
||||
|
||||
class Writer : public lld::Writer {
|
||||
public:
|
||||
Writer(const TargetInfo &ti) : _targetInfo(ti) {}
|
||||
Writer(const LinkingContext &context) : _context(context) {}
|
||||
|
||||
virtual error_code writeFile(const lld::File &file, StringRef outPath) {
|
||||
// Create stream to path.
|
||||
@@ -1324,7 +1322,7 @@ public:
|
||||
return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
|
||||
|
||||
// Create yaml Output writer, using yaml options for context.
|
||||
ContextInfo context(_targetInfo);
|
||||
ContextInfo context(_context);
|
||||
llvm::yaml::Output yout(out, &context);
|
||||
|
||||
// Write yaml output.
|
||||
@@ -1335,12 +1333,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const TargetInfo &_targetInfo;
|
||||
const LinkingContext &_context;
|
||||
};
|
||||
|
||||
class ReaderYAML : public Reader {
|
||||
public:
|
||||
ReaderYAML(const TargetInfo &ti) : Reader(ti) {}
|
||||
ReaderYAML(const LinkingContext &context) : Reader(context) {}
|
||||
|
||||
error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
@@ -1352,7 +1350,7 @@ public:
|
||||
// is deallocated.
|
||||
|
||||
// Create YAML Input parser.
|
||||
ContextInfo context(_targetInfo);
|
||||
ContextInfo context(_context);
|
||||
llvm::yaml::Input yin(mb->getBuffer(), &context);
|
||||
|
||||
// Fill vector with File objects created by parsing yaml.
|
||||
@@ -1373,11 +1371,11 @@ public:
|
||||
};
|
||||
} // end namespace yaml
|
||||
|
||||
std::unique_ptr<Writer> createWriterYAML(const TargetInfo &ti) {
|
||||
return std::unique_ptr<Writer>(new lld::yaml::Writer(ti));
|
||||
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
|
||||
return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
|
||||
}
|
||||
|
||||
std::unique_ptr<Reader> createReaderYAML(const TargetInfo &ti) {
|
||||
return std::unique_ptr<Reader>(new lld::yaml::ReaderYAML(ti));
|
||||
std::unique_ptr<Reader> createReaderYAML(const LinkingContext &context) {
|
||||
return std::unique_ptr<Reader>(new lld::yaml::ReaderYAML(context));
|
||||
}
|
||||
} // end namespace lld
|
||||
|
||||
@@ -108,7 +108,7 @@ TEST(Range, passing) {
|
||||
// MSVC Can't compile make_ptr_range.
|
||||
#ifndef _MSC_VER
|
||||
static_assert(
|
||||
std::is_same<decltype(make_ptr_range(v)), lld::range<int *> >::value,
|
||||
std::is_same<decltype(make_ptr_range(v)), lld::range<int *>>::value,
|
||||
"make_ptr_range should return a range of pointers");
|
||||
takes_range(make_ptr_range(v));
|
||||
takes_range(make_ptr_range(implicit_cast<const std::vector<int> &>(v)));
|
||||
@@ -185,12 +185,12 @@ TEST(Range, slice) {
|
||||
// -fsanitize=undefined complains about this, but only if optimizations are
|
||||
// enabled.
|
||||
#if 0
|
||||
test_slice<std::forward_list<int> >();
|
||||
test_slice<std::forward_list<int>>();
|
||||
#endif
|
||||
test_slice<std::list<int> >();
|
||||
// This doesn't build with libstdc++ 4.7
|
||||
test_slice<std::list<int>>();
|
||||
// This doesn't build with libstdc++ 4.7
|
||||
#if 0
|
||||
test_slice<std::deque<int> >();
|
||||
test_slice<std::deque<int>>();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ TEST(Range, istream_range) {
|
||||
// MSVC interprets input as a function declaration if you don't declare start
|
||||
// and instead directly pass std::istream_iterator<int>(stream).
|
||||
auto start = std::istream_iterator<int>(stream);
|
||||
lld::range<std::istream_iterator<int> > input(
|
||||
lld::range<std::istream_iterator<int>> input(
|
||||
start, std::istream_iterator<int>());
|
||||
EXPECT_TRUE(input.front() == 1);
|
||||
input.pop_front();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user