aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:57:38 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:57:38 +0000
commit5a5c549fe9a3fef595297bd21d36bed8409dc37d (patch)
treea964c8f5ac85b7b641cac022c5f9bf4eed3d2b9b /include
parentfb911942f1434f3d1750f83f25f5e42c80e60638 (diff)
downloadsrc-5a5c549fe9a3fef595297bd21d36bed8409dc37d.tar.gz
src-5a5c549fe9a3fef595297bd21d36bed8409dc37d.zip
Vendor import of lld trunk r256633:vendor/lld/lld-trunk-r256633
Notes
Notes: svn path=/vendor/lld/dist/; revision=292934 svn path=/vendor/lld/lld-trunk-r256633/; revision=292935; tag=vendor/lld/lld-trunk-r256633
Diffstat (limited to 'include')
-rw-r--r--include/Makefile4
-rw-r--r--include/lld/Config/Makefile32
-rw-r--r--include/lld/Core/Alias.h10
-rw-r--r--include/lld/Core/DefinedAtom.h14
-rw-r--r--include/lld/Core/Error.h26
-rw-r--r--include/lld/Core/File.h178
-rw-r--r--include/lld/Core/LLVM.h2
-rw-r--r--include/lld/Core/LinkingContext.h15
-rw-r--r--include/lld/Core/Parallel.h106
-rw-r--r--include/lld/Core/Pass.h4
-rw-r--r--include/lld/Core/PassManager.h7
-rw-r--r--include/lld/Core/Reader.h19
-rw-r--r--include/lld/Core/Reference.h2
-rw-r--r--include/lld/Core/Resolver.h2
-rw-r--r--include/lld/Core/SharedLibraryFile.h16
-rw-r--r--include/lld/Core/Simple.h87
-rw-r--r--include/lld/Core/SymbolTable.h2
-rw-r--r--include/lld/Core/TODO.txt2
-rw-r--r--include/lld/Core/Writer.h12
-rw-r--r--include/lld/Driver/Driver.h48
-rw-r--r--include/lld/Driver/WinLinkModuleDef.h200
-rw-r--r--include/lld/Makefile44
-rw-r--r--include/lld/ReaderWriter/ELFLinkingContext.h268
-rw-r--r--include/lld/ReaderWriter/ELFTargets.h38
-rw-r--r--include/lld/ReaderWriter/LinkerScript.h187
-rw-r--r--include/lld/ReaderWriter/MachOLinkingContext.h76
-rw-r--r--include/lld/ReaderWriter/PECOFFLinkingContext.h463
-rw-r--r--include/lld/ReaderWriter/RelocationHelperFunctions.h57
-rw-r--r--include/lld/ReaderWriter/YamlContext.h12
29 files changed, 586 insertions, 1347 deletions
diff --git a/include/Makefile b/include/Makefile
deleted file mode 100644
index d8903356d9fb..000000000000
--- a/include/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-LLD_LEVEL := ..
-DIRS := lld
-
-include $(LLD_LEVEL)/Makefile
diff --git a/include/lld/Config/Makefile b/include/lld/Config/Makefile
deleted file mode 100644
index e2139220e3df..000000000000
--- a/include/lld/Config/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-LLD_LEVEL := ../../..
-
-BUILT_SOURCES = Version.inc
-
-TABLEGEN_INC_FILES_COMMON = 1
-
-include $(LLD_LEVEL)/Makefile
-
-# Compute the lld version from the LLVM version, unless specified explicitly.
-ifndef LLD_VERSION
-LLD_VERSION := $(subst svn,,$(LLVMVersion))
-LLD_VERSION := $(subst rc,,$(LLD_VERSION))
-endif
-
-LLD_VERSION_COMPONENTS := $(subst ., ,$(LLD_VERSION))
-LLD_VERSION_MAJOR := $(word 1,$(LLD_VERSION_COMPONENTS))
-LLD_VERSION_MINOR := $(word 2,$(LLD_VERSION_COMPONENTS))
-
-LLD_REVISION := $(strip \
- $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(LLVM_SRC_ROOT)/tools/lld))
-
-LLD_REPOSITORY := $(strip \
- $(shell $(LLVM_SRC_ROOT)/utils/GetRepositoryPath $(LLVM_SRC_ROOT)/tools/lld))
-
-$(ObjDir)/Version.inc.tmp : Version.inc.in Makefile $(LLVM_OBJ_ROOT)/Makefile.config $(ObjDir)/.dir
- $(Echo) "Updating LLD version info."
- $(Verb)sed -e "s#@LLD_VERSION@#$(LLD_VERSION)#g" \
- -e "s#@LLD_VERSION_MAJOR@#$(LLD_VERSION_MAJOR)#g" \
- -e "s#@LLD_VERSION_MINOR@#$(LLD_VERSION_MINOR)#g" \
- -e "s#@LLD_REVISION@#$(LLD_REVISION)#g" \
- -e "s#@LLD_REPOSITORY@#$(LLD_REPOSITORY)#g" \
- $< > $@
diff --git a/include/lld/Core/Alias.h b/include/lld/Core/Alias.h
index 610022525ecb..fa999292fbd3 100644
--- a/include/lld/Core/Alias.h
+++ b/include/lld/Core/Alias.h
@@ -33,9 +33,7 @@ namespace lld {
class AliasAtom : public SimpleDefinedAtom {
public:
AliasAtom(const File &file, StringRef name)
- : SimpleDefinedAtom(file), _target(nullptr), _name(name),
- _merge(DefinedAtom::mergeNo), _deadStrip(DefinedAtom::deadStripNormal) {
- }
+ : SimpleDefinedAtom(file), _name(name) {}
StringRef name() const override { return _name; }
uint64_t size() const override { return 0; }
@@ -91,10 +89,10 @@ private:
}
}
- mutable const DefinedAtom *_target;
std::string _name;
- llvm::Optional<Merge> _merge;
- DeadStripKind _deadStrip;
+ mutable const DefinedAtom *_target = nullptr;
+ llvm::Optional<Merge> _merge = DefinedAtom::mergeNo;
+ DeadStripKind _deadStrip = DefinedAtom::deadStripNormal;
};
} // end namespace lld
diff --git a/include/lld/Core/DefinedAtom.h b/include/lld/Core/DefinedAtom.h
index 86d880c659b4..e4d4488ccdca 100644
--- a/include/lld/Core/DefinedAtom.h
+++ b/include/lld/Core/DefinedAtom.h
@@ -151,6 +151,7 @@ public:
typeNoAlloc, // Identifies non allocatable sections [ELF]
typeGroupComdat, // Identifies a section group [ELF, COFF]
typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
+ typeSectCreate, // Created via the -sectcreate option [Darwin]
};
// Permission bits for atoms and segments. The order of these values are
@@ -190,23 +191,26 @@ public:
// Attributes describe a code model used by the atom.
enum CodeModel {
codeNA, // no specific code model
+ // MIPS code models
codeMipsPIC, // PIC function in a PIC / non-PIC mixed file
codeMipsMicro, // microMIPS instruction encoding
codeMipsMicroPIC, // microMIPS instruction encoding + PIC
codeMips16, // MIPS-16 instruction encoding
+ // ARM code models
codeARMThumb, // ARM Thumb instruction set
+ codeARM_a, // $a-like mapping symbol (for ARM code)
+ codeARM_d, // $d-like mapping symbol (for data)
+ codeARM_t, // $t-like mapping symbol (for Thumb code)
};
struct Alignment {
- Alignment(int p2, int m = 0)
- : powerOf2(p2)
- , modulus(m) {}
+ Alignment(int v, int m = 0) : value(v), modulus(m) {}
- uint16_t powerOf2;
+ uint16_t value;
uint16_t modulus;
bool operator==(const Alignment &rhs) const {
- return (powerOf2 == rhs.powerOf2) && (modulus == rhs.modulus);
+ return (value == rhs.value) && (modulus == rhs.modulus);
}
};
diff --git a/include/lld/Core/Error.h b/include/lld/Core/Error.h
index 7caa25018f40..a7e61f91d8e9 100644
--- a/include/lld/Core/Error.h
+++ b/include/lld/Core/Error.h
@@ -19,26 +19,9 @@
namespace lld {
-const std::error_category &native_reader_category();
-
-enum class NativeReaderError {
- success = 0,
- unknown_file_format,
- file_too_short,
- file_malformed,
- unknown_chunk_type,
- memory_error,
- conflicting_target_machine,
-};
-
-inline std::error_code make_error_code(NativeReaderError e) {
- return std::error_code(static_cast<int>(e), native_reader_category());
-}
-
const std::error_category &YamlReaderCategory();
enum class YamlReaderError {
- success = 0,
unknown_keyword,
illegal_value
};
@@ -53,7 +36,11 @@ enum class LinkerScriptReaderError {
success = 0,
parse_error,
unknown_symbol_in_expr,
- unrecognized_function_in_expr
+ unrecognized_function_in_expr,
+ unknown_phdr_ids,
+ extra_program_phdr,
+ misplaced_program_phdr,
+ program_phdr_wrong_phdrs,
};
inline std::error_code make_error_code(LinkerScriptReaderError e) {
@@ -66,14 +53,13 @@ inline std::error_code make_error_code(LinkerScriptReaderError e) {
/// supplied error string.
/// Note: Once ErrorOr<> is updated to work with errors other than error_code,
/// this can be updated to return some other kind of error.
+std::error_code make_dynamic_error_code(const char *msg);
std::error_code make_dynamic_error_code(StringRef msg);
std::error_code make_dynamic_error_code(const Twine &msg);
} // end namespace lld
namespace std {
-template <>
-struct is_error_code_enum<lld::NativeReaderError> : std::true_type {};
template <> struct is_error_code_enum<lld::YamlReaderError> : std::true_type {};
template <>
struct is_error_code_enum<lld::LinkerScriptReaderError> : std::true_type {};
diff --git a/include/lld/Core/File.h b/include/lld/Core/File.h
index 25b177ec879c..494e50065340 100644
--- a/include/lld/Core/File.h
+++ b/include/lld/Core/File.h
@@ -86,90 +86,48 @@ public:
/// Sets the command line order of the file.
void setOrdinal(uint64_t ordinal) const { _ordinal = ordinal; }
- template <typename T> class atom_iterator; // forward reference
+ /// Returns the ordinal for the next atom to be defined in this file.
+ uint64_t getNextAtomOrdinalAndIncrement() const {
+ return _nextAtomOrdinal++;
+ }
/// For allocating any objects owned by this File.
llvm::BumpPtrAllocator &allocator() const {
return _allocator;
}
- /// \brief For use interating over DefinedAtoms in this File.
- typedef atom_iterator<DefinedAtom> defined_iterator;
-
- /// \brief For use interating over UndefinedAtoms in this File.
- typedef atom_iterator<UndefinedAtom> undefined_iterator;
-
- /// \brief For use interating over SharedLibraryAtoms in this File.
- typedef atom_iterator<SharedLibraryAtom> shared_library_iterator;
+ /// The type of atom mutable container.
+ template <typename T> using AtomVector = std::vector<const T *>;
- /// \brief For use interating over AbsoluteAtoms in this File.
- typedef atom_iterator<AbsoluteAtom> absolute_iterator;
-
- /// \brief Different object file readers may instantiate and manage atoms with
- /// different data structures. This class is a collection abstraction.
- /// Each concrete File instance must implement these atom_collection
- /// methods to enable clients to interate the File's atoms.
- template <typename T>
- class atom_collection {
+ /// The range type for the atoms. It's backed by a std::vector, but hides
+ /// its member functions so that you can only call begin or end.
+ template <typename T> class AtomRange {
public:
- virtual ~atom_collection() { }
- virtual atom_iterator<T> begin() const = 0;
- virtual atom_iterator<T> end() const = 0;
- virtual const T *deref(const void *it) const = 0;
- virtual void next(const void *&it) const = 0;
- virtual uint64_t size() const = 0;
- bool empty() const { return size() == 0; }
- };
+ AtomRange(AtomVector<T> v) : _v(v) {}
+ typename AtomVector<T>::const_iterator begin() const { return _v.begin(); }
+ typename AtomVector<T>::const_iterator end() const { return _v.end(); }
+ typename AtomVector<T>::iterator begin() { return _v.begin(); }
+ typename AtomVector<T>::iterator end() { return _v.end(); }
- /// \brief The class is the iterator type used to iterate through a File's
- /// Atoms. This iterator delegates the work to the associated atom_collection
- /// object. There are four kinds of Atoms, so this iterator is templated on
- /// the four base Atom kinds.
- template <typename T>
- class atom_iterator : public std::iterator<std::forward_iterator_tag, T> {
- public:
- atom_iterator(const atom_collection<T> &c, const void *it)
- : _collection(&c), _it(it) { }
-
- const T *operator*() const {
- return _collection->deref(_it);
- }
- const T *operator->() const {
- return _collection->deref(_it);
- }
-
- friend bool operator==(const atom_iterator<T> &lhs, const atom_iterator<T> &rhs) {
- return lhs._it == rhs._it;
- }
-
- friend bool operator!=(const atom_iterator<T> &lhs, const atom_iterator<T> &rhs) {
- return !(lhs == rhs);
- }
-
- atom_iterator<T> &operator++() {
- _collection->next(_it);
- return *this;
- }
private:
- const atom_collection<T> *_collection;
- const void *_it;
+ AtomVector<T> &_v;
};
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
- virtual const atom_collection<DefinedAtom> &defined() const = 0;
+ virtual const AtomVector<DefinedAtom> &defined() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
- virtual const atom_collection<UndefinedAtom> &undefined() const = 0;
+ virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
- virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const = 0;
+ virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
- virtual const atom_collection<AbsoluteAtom> &absolute() const = 0;
+ virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
/// \brief If a file is parsed using a different method than doParse(),
/// one must use this method to set the last error status, so that
@@ -199,67 +157,18 @@ public:
protected:
/// \brief only subclasses of File can be instantiated
File(StringRef p, Kind kind)
- : _path(p), _kind(kind), _ordinal(UINT64_MAX) {}
+ : _path(p), _kind(kind), _ordinal(UINT64_MAX),
+ _nextAtomOrdinal(0) {}
/// \brief Subclasses should override this method to parse the
/// memory buffer passed to this file's constructor.
virtual std::error_code doParse() { return std::error_code(); }
- /// \brief This is a convenience class for File subclasses which manage their
- /// atoms as a simple std::vector<>.
- template <typename T>
- class atom_collection_vector : public atom_collection<T> {
- public:
- atom_iterator<T> begin() const override {
- auto *it = _atoms.empty() ? nullptr
- : reinterpret_cast<const void *>(_atoms.data());
- return atom_iterator<T>(*this, it);
- }
-
- atom_iterator<T> end() const override {
- auto *it = _atoms.empty() ? nullptr : reinterpret_cast<const void *>(
- _atoms.data() + _atoms.size());
- return atom_iterator<T>(*this, it);
- }
-
- const T *deref(const void *it) const override {
- return *reinterpret_cast<const T *const *>(it);
- }
-
- void next(const void *&it) const override {
- const T *const *p = reinterpret_cast<const T *const *>(it);
- ++p;
- it = reinterpret_cast<const void*>(p);
- }
-
- uint64_t size() const override { return _atoms.size(); }
-
- std::vector<const T *> _atoms;
- };
-
- /// \brief This is a convenience class for File subclasses which need to
- /// return an empty collection.
- template <typename T>
- class atom_collection_empty : public atom_collection<T> {
- public:
- atom_iterator<T> begin() const override {
- return atom_iterator<T>(*this, nullptr);
- }
- atom_iterator<T> end() const override {
- return atom_iterator<T>(*this, nullptr);
- }
- const T *deref(const void *it) const override {
- llvm_unreachable("empty collection should never be accessed");
- }
- void next(const void *&it) const override {}
- uint64_t size() const override { return 0; }
- };
-
- static atom_collection_empty<DefinedAtom> _noDefinedAtoms;
- static atom_collection_empty<UndefinedAtom> _noUndefinedAtoms;
- static atom_collection_empty<SharedLibraryAtom> _noSharedLibraryAtoms;
- static atom_collection_empty<AbsoluteAtom> _noAbsoluteAtoms;
- mutable llvm::BumpPtrAllocator _allocator;
+ static AtomVector<DefinedAtom> _noDefinedAtoms;
+ static AtomVector<UndefinedAtom> _noUndefinedAtoms;
+ static AtomVector<SharedLibraryAtom> _noSharedLibraryAtoms;
+ static AtomVector<AbsoluteAtom> _noAbsoluteAtoms;
+ mutable llvm::BumpPtrAllocator _allocator;
private:
StringRef _path;
@@ -267,29 +176,12 @@ private:
mutable std::string _archiveMemberPath;
Kind _kind;
mutable uint64_t _ordinal;
+ mutable uint64_t _nextAtomOrdinal;
std::shared_ptr<MemoryBuffer> _sharedMemoryBuffer;
llvm::Optional<std::error_code> _lastError;
std::mutex _parseMutex;
};
-/// \brief A mutable File.
-class MutableFile : public File {
-public:
- /// \brief Add an atom to the file. Invalidates iterators for all returned
- /// containters.
- virtual void addAtom(const Atom&) = 0;
-
- typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
- virtual DefinedAtomRange definedAtoms() = 0;
-
- virtual void
- removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) = 0;
-
-protected:
- /// \brief only subclasses of MutableFile can be instantiated
- MutableFile(StringRef p) : File(p, kindObject) {}
-};
-
/// An ErrorFile represents a file that doesn't exist.
/// If you try to parse a file which doesn't exist, an instance of this
/// class will be returned. That's parse method always returns an error.
@@ -302,16 +194,16 @@ public:
std::error_code doParse() override { return _ec; }
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
llvm_unreachable("internal error");
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
llvm_unreachable("internal error");
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
llvm_unreachable("internal error");
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
llvm_unreachable("internal error");
}
diff --git a/include/lld/Core/LLVM.h b/include/lld/Core/LLVM.h
index 1bc1173bd48b..d532c17fbfdf 100644
--- a/include/lld/Core/LLVM.h
+++ b/include/lld/Core/LLVM.h
@@ -26,6 +26,7 @@ namespace llvm {
class StringRef;
class Twine;
class MemoryBuffer;
+ class MemoryBufferRef;
template<typename T> class ArrayRef;
template<unsigned InternalLen> class SmallString;
template<typename T, unsigned N> class SmallVector;
@@ -53,6 +54,7 @@ namespace lld {
using llvm::StringRef;
using llvm::Twine;
using llvm::MemoryBuffer;
+ using llvm::MemoryBufferRef;
using llvm::ArrayRef;
using llvm::SmallString;
using llvm::SmallVector;
diff --git a/include/lld/Core/LinkingContext.h b/include/lld/Core/LinkingContext.h
index 81a3b4b4eb71..a723854b3c91 100644
--- a/include/lld/Core/LinkingContext.h
+++ b/include/lld/Core/LinkingContext.h
@@ -41,7 +41,6 @@ public:
enum class OutputFileType : uint8_t {
Default, // The default output type for this target
YAML, // The output type is set to YAML
- Native // The output file format is Native (Atoms)
};
virtual ~LinkingContext();
@@ -62,7 +61,7 @@ public:
/// should be marked live (along with all Atoms they reference). Usually
/// this method returns false for main executables, but true for dynamic
/// shared libraries.
- bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; };
+ bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; }
/// Only used if deadStrip() returns true. This method returns the names
/// of DefinedAtoms that should be marked live (along with all Atoms they
@@ -273,13 +272,11 @@ public:
/// Set the various output file types that the linker would
/// create
bool setOutputFileType(StringRef outputFileType) {
- if (outputFileType.equals_lower("yaml"))
+ if (outputFileType.equals_lower("yaml")) {
_outputFileType = OutputFileType::YAML;
- else if (outputFileType.equals_lower("native"))
- _outputFileType = OutputFileType::YAML;
- else
- return false;
- return true;
+ return true;
+ }
+ return false;
}
/// Returns the output file type that that the linker needs to create.
@@ -292,7 +289,7 @@ public:
/// 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 bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &);
/// 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.
diff --git a/include/lld/Core/Parallel.h b/include/lld/Core/Parallel.h
index 65176ac2b04d..e2c38308b768 100644
--- a/include/lld/Core/Parallel.h
+++ b/include/lld/Core/Parallel.h
@@ -14,21 +14,15 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/range.h"
#include "llvm/Support/MathExtras.h"
-
-#ifdef _MSC_VER
-// concrt.h depends on eh.h for __uncaught_exception declaration
-// even if we disable exceptions.
-#include <eh.h>
-#endif
+#include "llvm/Support/thread.h"
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <mutex>
-#include <thread>
#include <stack>
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && LLVM_ENABLE_THREADS
#include <concrt.h>
#include <ppl.h>
#endif
@@ -104,13 +98,55 @@ private:
std::condition_variable _cond;
};
+// Classes in this namespace are implementation details of this header.
+namespace internal {
+
/// \brief An abstract class that takes closures and runs them asynchronously.
class Executor {
public:
- virtual ~Executor() {}
+ virtual ~Executor() = default;
virtual void add(std::function<void()> func) = 0;
};
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+class SyncExecutor : public Executor {
+public:
+ virtual void add(std::function<void()> func) {
+ func();
+ }
+};
+
+inline Executor *getDefaultExecutor() {
+ static SyncExecutor exec;
+ return &exec;
+}
+#elif defined(_MSC_VER)
+/// \brief An Executor that runs tasks via ConcRT.
+class ConcRTExecutor : public Executor {
+ struct Taskish {
+ Taskish(std::function<void()> task) : _task(task) {}
+
+ std::function<void()> _task;
+
+ static void run(void *p) {
+ Taskish *self = static_cast<Taskish *>(p);
+ self->_task();
+ concurrency::Free(self);
+ }
+ };
+
+public:
+ virtual void add(std::function<void()> func) {
+ Concurrency::CurrentScheduler::ScheduleTask(Taskish::run,
+ new (concurrency::Alloc(sizeof(Taskish))) Taskish(func));
+ }
+};
+
+inline Executor *getDefaultExecutor() {
+ static ConcRTExecutor exec;
+ return &exec;
+}
+#else
/// \brief An implementation of an Executor that runs closures on a thread pool
/// in filo order.
class ThreadPoolExecutor : public Executor {
@@ -130,7 +166,7 @@ public:
}).detach();
}
- ~ThreadPoolExecutor() {
+ ~ThreadPoolExecutor() override {
std::unique_lock<std::mutex> lock(_mutex);
_stop = true;
lock.unlock();
@@ -169,39 +205,14 @@ private:
Latch _done;
};
-#ifdef _MSC_VER
-/// \brief An Executor that runs tasks via ConcRT.
-class ConcRTExecutor : public Executor {
- struct Taskish {
- Taskish(std::function<void()> task) : _task(task) {}
-
- std::function<void()> _task;
-
- static void run(void *p) {
- Taskish *self = static_cast<Taskish *>(p);
- self->_task();
- concurrency::Free(self);
- }
- };
-
-public:
- virtual void add(std::function<void()> func) {
- Concurrency::CurrentScheduler::ScheduleTask(Taskish::run,
- new (concurrency::Alloc(sizeof(Taskish))) Taskish(func));
- }
-};
-
-inline Executor *getDefaultExecutor() {
- static ConcRTExecutor exec;
- return &exec;
-}
-#else
inline Executor *getDefaultExecutor() {
static ThreadPoolExecutor exec;
return &exec;
}
#endif
+} // namespace internal
+
/// \brief Allows launching a number of tasks and waiting for them to finish
/// either explicitly via sync() or implicitly on destruction.
class TaskGroup {
@@ -210,7 +221,7 @@ class TaskGroup {
public:
void spawn(std::function<void()> f) {
_latch.inc();
- getDefaultExecutor()->add([&, f] {
+ internal::getDefaultExecutor()->add([&, f] {
f();
_latch.dec();
});
@@ -219,7 +230,15 @@ public:
void sync() const { _latch.sync(); }
};
-#ifdef _MSC_VER
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+template <class RandomAccessIterator, class Comp>
+void parallel_sort(
+ RandomAccessIterator start, RandomAccessIterator end,
+ const Comp &comp = std::less<
+ typename std::iterator_traits<RandomAccessIterator>::value_type>()) {
+ std::sort(start, end, comp);
+}
+#elif defined(_MSC_VER)
// Use ppl parallel_sort on Windows.
template <class RandomAccessIterator, class Comp>
void parallel_sort(
@@ -286,7 +305,12 @@ template <class T> void parallel_sort(T *start, T *end) {
parallel_sort(start, end, std::less<T>());
}
-#ifdef _MSC_VER
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+template <class Iterator, class Func>
+void parallel_for_each(Iterator begin, Iterator end, Func func) {
+ std::for_each(begin, end, func);
+}
+#elif defined(_MSC_VER)
// Use ppl parallel_for_each on Windows.
template <class Iterator, class Func>
void parallel_for_each(Iterator begin, Iterator end, Func func) {
@@ -306,4 +330,4 @@ void parallel_for_each(Iterator begin, Iterator end, Func func) {
#endif
} // end namespace lld
-#endif
+#endif // LLD_CORE_PARALLEL_H
diff --git a/include/lld/Core/Pass.h b/include/lld/Core/Pass.h
index 7a9d2453f482..2e49cd1b8eee 100644
--- a/include/lld/Core/Pass.h
+++ b/include/lld/Core/Pass.h
@@ -17,7 +17,7 @@
#include <vector>
namespace lld {
-class MutableFile;
+class SimpleFile;
/// Once the core linking is done (which resolves references, coalesces atoms
/// and produces a complete Atom graph), the linker runs a series of passes
@@ -34,7 +34,7 @@ public:
virtual ~Pass() { }
/// Do the actual work of the Pass.
- virtual void perform(std::unique_ptr<MutableFile> &mergedFile) = 0;
+ virtual std::error_code perform(SimpleFile &mergedFile) = 0;
protected:
// Only subclassess can be instantiated.
diff --git a/include/lld/Core/PassManager.h b/include/lld/Core/PassManager.h
index 65fc4d806ceb..62aa119f8f76 100644
--- a/include/lld/Core/PassManager.h
+++ b/include/lld/Core/PassManager.h
@@ -16,7 +16,7 @@
#include <vector>
namespace lld {
-class MutableFile;
+class SimpleFile;
class Pass;
/// \brief Owns and runs a collection of passes.
@@ -31,9 +31,10 @@ public:
_passes.push_back(std::move(pass));
}
- std::error_code runOnFile(std::unique_ptr<MutableFile> &file) {
+ std::error_code runOnFile(SimpleFile &file) {
for (std::unique_ptr<Pass> &pass : _passes)
- pass->perform(file);
+ if (std::error_code EC = pass->perform(file))
+ return EC;
return std::error_code();
}
diff --git a/include/lld/Core/Reader.h b/include/lld/Core/Reader.h
index ac90c5a7e85c..9324da475e3d 100644
--- a/include/lld/Core/Reader.h
+++ b/include/lld/Core/Reader.h
@@ -31,13 +31,12 @@ class ELFLinkingContext;
class File;
class LinkingContext;
class PECOFFLinkingContext;
-class TargetHandlerBase;
class MachOLinkingContext;
/// \brief An abstract class for reading object files, library files, and
/// executable files.
///
-/// Each file format (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete
+/// Each file format (e.g. ELF, mach-o, PECOFF, etc) have a concrete
/// subclass of Reader.
class Reader {
public:
@@ -46,17 +45,14 @@ public:
/// Sniffs the file to determine if this Reader can parse it.
/// The method is called with:
/// 1) the file_magic enumeration returned by identify_magic()
- /// 2) the file extension (e.g. ".obj")
- /// 3) the whole file content buffer if the above is not enough.
- virtual bool canParse(file_magic magic, StringRef fileExtension,
- const MemoryBuffer &mb) const = 0;
+ /// 2) the whole file content buffer if the above is not enough.
+ virtual bool canParse(file_magic magic, MemoryBufferRef mb) const = 0;
/// \brief Parse a supplied buffer (already filled with the contents of a
/// file) and create a File object.
/// The resulting File object takes ownership of the MemoryBuffer.
- virtual std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const = 0;
+ virtual ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &) const = 0;
};
@@ -93,8 +89,8 @@ public:
/// Walk the list of registered Readers and find one that can parse the
/// supplied file and parse it.
- std::error_code loadFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result) const;
+ ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb) const;
/// Walk the list of registered kind tables to convert a Reference Kind
/// name to a value.
@@ -118,7 +114,6 @@ public:
// as parameters to the addSupport*() method.
void addSupportArchives(bool logLoading);
void addSupportYamlFiles();
- void addSupportNativeObjects();
void addSupportCOFFObjects(PECOFFLinkingContext &);
void addSupportCOFFImportLibraries(PECOFFLinkingContext &);
void addSupportMachOObjects(MachOLinkingContext &);
diff --git a/include/lld/Core/Reference.h b/include/lld/Core/Reference.h
index 7a804c31e182..971721eb7d54 100644
--- a/include/lld/Core/Reference.h
+++ b/include/lld/Core/Reference.h
@@ -56,7 +56,7 @@ public:
void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
// Which architecture the kind value is for.
- enum class KindArch { all, AArch64, ARM, Hexagon, Mips, x86, x86_64 };
+ enum class KindArch { all, AArch64, AMDGPU, ARM, Hexagon, Mips, x86, x86_64 };
KindArch kindArch() const { return (KindArch)_kindArch; }
void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
diff --git a/include/lld/Core/Resolver.h b/include/lld/Core/Resolver.h
index e16c07b839fa..05af7d9573ea 100644
--- a/include/lld/Core/Resolver.h
+++ b/include/lld/Core/Resolver.h
@@ -54,7 +54,7 @@ public:
/// @brief do work of merging and resolving and return list
bool resolve();
- std::unique_ptr<MutableFile> resultFile() { return std::move(_result); }
+ std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
private:
typedef std::function<void(StringRef, bool)> UndefCallback;
diff --git a/include/lld/Core/SharedLibraryFile.h b/include/lld/Core/SharedLibraryFile.h
index 2f84624287d8..a2907287862d 100644
--- a/include/lld/Core/SharedLibraryFile.h
+++ b/include/lld/Core/SharedLibraryFile.h
@@ -34,19 +34,19 @@ public:
// the import name (Windows).
virtual StringRef getDSOName() const = 0;
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
return _definedAtoms;
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
return _undefinedAtoms;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
return _absoluteAtoms;
}
@@ -54,10 +54,10 @@ protected:
/// only subclasses of SharedLibraryFile can be instantiated
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _definedAtoms;
+ AtomVector<UndefinedAtom> _undefinedAtoms;
+ AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ AtomVector<AbsoluteAtom> _absoluteAtoms;
};
} // namespace lld
diff --git a/include/lld/Core/Simple.h b/include/lld/Core/Simple.h
index 71d0c0702301..3c204f8ba284 100644
--- a/include/lld/Core/Simple.h
+++ b/include/lld/Core/Simple.h
@@ -23,59 +23,61 @@
#include "lld/Core/UndefinedAtom.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include <atomic>
namespace lld {
-class SimpleFile : public MutableFile {
+class SimpleFile : public File {
public:
- SimpleFile(StringRef path) : MutableFile(path) {}
-
- void addAtom(const Atom &atom) override {
- if (auto *defAtom = dyn_cast<DefinedAtom>(&atom)) {
- _definedAtoms._atoms.push_back(defAtom);
- } else if (auto *undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
- _undefinedAtoms._atoms.push_back(undefAtom);
- } else if (auto *shlibAtom = dyn_cast<SharedLibraryAtom>(&atom)) {
- _sharedLibraryAtoms._atoms.push_back(shlibAtom);
- } else if (auto *absAtom = dyn_cast<AbsoluteAtom>(&atom)) {
- _absoluteAtoms._atoms.push_back(absAtom);
+ SimpleFile(StringRef path) : File(path, kindObject) {}
+
+ void addAtom(const DefinedAtom &a) { _defined.push_back(&a); }
+ void addAtom(const UndefinedAtom &a) { _undefined.push_back(&a); }
+ void addAtom(const SharedLibraryAtom &a) { _shared.push_back(&a); }
+ void addAtom(const AbsoluteAtom &a) { _absolute.push_back(&a); }
+
+ void addAtom(const Atom &atom) {
+ if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
+ _defined.push_back(p);
+ } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
+ _undefined.push_back(p);
+ } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
+ _shared.push_back(p);
+ } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
+ _absolute.push_back(p);
} else {
llvm_unreachable("atom has unknown definition kind");
}
}
- void
- removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) override {
- auto &atoms = _definedAtoms._atoms;
+ void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
+ auto &atoms = _defined;
auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
atoms.erase(newEnd, atoms.end());
}
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
+ const AtomVector<DefinedAtom> &defined() const override { return _defined; }
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _undefined;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _shared;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _absolute;
}
- DefinedAtomRange definedAtoms() override {
- return make_range(_definedAtoms._atoms);
- }
+ typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
+ DefinedAtomRange definedAtoms() { return make_range(_defined); }
private:
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _defined;
+ AtomVector<UndefinedAtom> _undefined;
+ AtomVector<SharedLibraryAtom> _shared;
+ AtomVector<AbsoluteAtom> _absolute;
};
/// \brief Archive library file that may be used as a virtual container
@@ -86,19 +88,19 @@ public:
SimpleArchiveLibraryFile(StringRef filename)
: ArchiveLibraryFile(filename) {}
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
return _definedAtoms;
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
return _undefinedAtoms;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
return _absoluteAtoms;
}
@@ -114,10 +116,10 @@ public:
}
private:
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _definedAtoms;
+ AtomVector<UndefinedAtom> _undefinedAtoms;
+ AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ AtomVector<AbsoluteAtom> _absoluteAtoms;
};
class SimpleReference : public Reference {
@@ -204,9 +206,8 @@ namespace lld {
class SimpleDefinedAtom : public DefinedAtom {
public:
- explicit SimpleDefinedAtom(const File &f) : _file(f) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
+ explicit SimpleDefinedAtom(const File &f)
+ : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {
_references.setAllocator(&f.allocator());
}
@@ -224,7 +225,7 @@ public:
Merge merge() const override { return DefinedAtom::mergeNo; }
- Alignment alignment() const override { return Alignment(0, 0); }
+ Alignment alignment() const override { return 1; }
SectionChoice sectionChoice() const override {
return DefinedAtom::sectionBasedOnContent;
diff --git a/include/lld/Core/SymbolTable.h b/include/lld/Core/SymbolTable.h
index 683ed65e3635..2e4459236d18 100644
--- a/include/lld/Core/SymbolTable.h
+++ b/include/lld/Core/SymbolTable.h
@@ -105,7 +105,7 @@ private:
bool addByName(const Atom &);
bool addByContent(const DefinedAtom &);
- LinkingContext &_context;
+ LinkingContext &_ctx;
AtomToAtom _replacedAtoms;
NameToAtom _nameTable;
NameToAtom _groupTable;
diff --git a/include/lld/Core/TODO.txt b/include/lld/Core/TODO.txt
index 8888c763ef65..8b523045de75 100644
--- a/include/lld/Core/TODO.txt
+++ b/include/lld/Core/TODO.txt
@@ -1,7 +1,7 @@
include/lld/Core
~~~~~~~~~~~~~~~~
-* The native/yaml reader/writer interfaces should be changed to return
+* The yaml reader/writer interfaces should be changed to return
an explanatory string if there is an error. The existing error_code
abstraction only works for returning low level OS errors. It does not
work for describing formatting issues.
diff --git a/include/lld/Core/Writer.h b/include/lld/Core/Writer.h
index 94c75d8d019f..8214ed6203f2 100644
--- a/include/lld/Core/Writer.h
+++ b/include/lld/Core/Writer.h
@@ -15,16 +15,15 @@
#include <vector>
namespace lld {
-class File;
class ELFLinkingContext;
+class File;
+class LinkingContext;
class MachOLinkingContext;
class PECOFFLinkingContext;
-class LinkingContext;
-class TargetHandlerBase;
/// \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,
-/// PECOFF, native, etc) have a concrete subclass of Writer.
+/// PECOFF, etc) have a concrete subclass of Writer.
class Writer {
public:
virtual ~Writer();
@@ -35,17 +34,16 @@ public:
/// \brief 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 bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) {}
protected:
// only concrete subclasses can be instantiated
Writer();
};
-std::unique_ptr<Writer> createWriterELF(TargetHandlerBase *handler);
+std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &);
std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &);
std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &);
-std::unique_ptr<Writer> createWriterNative();
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &);
} // end namespace lld
diff --git a/include/lld/Driver/Driver.h b/include/lld/Driver/Driver.h
index 300d2356d050..4bf0f43f8ce5 100644
--- a/include/lld/Driver/Driver.h
+++ b/include/lld/Driver/Driver.h
@@ -35,7 +35,7 @@ class ELFLinkingContext;
typedef std::vector<std::unique_ptr<File>> FileVector;
FileVector makeErrorFile(StringRef path, std::error_code ec);
-FileVector parseMemberFiles(FileVector &files);
+FileVector parseMemberFiles(std::unique_ptr<File> File);
FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
/// Base class for all Drivers.
@@ -46,6 +46,9 @@ protected:
static bool link(LinkingContext &context,
raw_ostream &diag = llvm::errs());
+ /// Parses the LLVM options from the context.
+ static void parseLLVMOptions(const LinkingContext &context);
+
private:
Driver() = delete;
};
@@ -55,7 +58,7 @@ private:
class UniversalDriver : public Driver {
public:
/// Determine flavor and pass control to Driver for that flavor.
- static bool link(int argc, const char *argv[],
+ static bool link(llvm::MutableArrayRef<const char *> args,
raw_ostream &diag = llvm::errs());
private:
@@ -67,12 +70,12 @@ class GnuLdDriver : public Driver {
public:
/// Parses command line arguments same as gnu/binutils ld and performs link.
/// Returns true iff an error occurred.
- static bool linkELF(int argc, const char *argv[],
+ static bool linkELF(llvm::ArrayRef<const char *> args,
raw_ostream &diag = llvm::errs());
/// 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[],
+ static bool parse(llvm::ArrayRef<const char *> args,
std::unique_ptr<ELFLinkingContext> &context,
raw_ostream &diag = llvm::errs());
@@ -103,12 +106,13 @@ class DarwinLdDriver : public Driver {
public:
/// Parses command line arguments same as darwin's ld and performs link.
/// Returns true iff there was an error.
- static bool linkMachO(int argc, const char *argv[],
+ static bool linkMachO(llvm::ArrayRef<const char *> args,
raw_ostream &diag = llvm::errs());
/// 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[], MachOLinkingContext &info,
+ static bool parse(llvm::ArrayRef<const char *> args,
+ MachOLinkingContext &info,
raw_ostream &diag = llvm::errs());
private:
@@ -116,41 +120,25 @@ private:
};
/// Driver for Windows 'link.exe' command line options
-class WinLinkDriver : public Driver {
-public:
- /// Parses command line arguments same as Windows link.exe and performs link.
- /// Returns true iff there was an error.
- static bool linkPECOFF(int argc, const char *argv[],
- raw_ostream &diag = llvm::errs());
-
- /// 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[], PECOFFLinkingContext &info,
- raw_ostream &diag = llvm::errs(),
- bool isDirective = false);
-
- // Same as parse(), but restricted to the context of directives.
- static bool parseDirectives(int argc, const char *argv[],
- PECOFFLinkingContext &info,
- raw_ostream &diag = llvm::errs()) {
- return parse(argc, argv, info, diag, true);
- }
+namespace coff {
+void link(llvm::ArrayRef<const char *> args);
+}
-private:
- WinLinkDriver() = delete;
-};
+namespace elf2 {
+void link(llvm::ArrayRef<const char *> args);
+}
/// Driver for lld unit tests
class CoreDriver : public Driver {
public:
/// Parses command line arguments same as lld-core and performs link.
/// Returns true iff there was an error.
- static bool link(int argc, const char *argv[],
+ static bool link(llvm::ArrayRef<const char *> args,
raw_ostream &diag = llvm::errs());
/// 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[], CoreLinkingContext &info,
+ static bool parse(llvm::ArrayRef<const char *> args, CoreLinkingContext &info,
raw_ostream &diag = llvm::errs());
private:
diff --git a/include/lld/Driver/WinLinkModuleDef.h b/include/lld/Driver/WinLinkModuleDef.h
deleted file mode 100644
index 68c9a4bfef70..000000000000
--- a/include/lld/Driver/WinLinkModuleDef.h
+++ /dev/null
@@ -1,200 +0,0 @@
-//===- lld/Driver/WinLinkModuleDef.h --------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Windows module definition file parser.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_DRIVER_WIN_LINK_MODULE_DEF_H
-#define LLD_DRIVER_WIN_LINK_MODULE_DEF_H
-
-#include "lld/Core/LLVM.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Allocator.h"
-#include <vector>
-
-namespace lld {
-namespace moduledef {
-
-enum class Kind {
- unknown,
- eof,
- identifier,
- comma,
- equal,
- kw_base,
- kw_data,
- kw_exports,
- kw_heapsize,
- kw_library,
- kw_name,
- kw_noname,
- kw_private,
- kw_stacksize,
- kw_version,
-};
-
-class Token {
-public:
- Token() : _kind(Kind::unknown) {}
- Token(Kind kind, StringRef range) : _kind(kind), _range(range) {}
-
- Kind _kind;
- StringRef _range;
-};
-
-class Lexer {
-public:
- explicit Lexer(std::unique_ptr<MemoryBuffer> mb) : _buffer(mb->getBuffer()) {
- _sourceManager.AddNewSourceBuffer(std::move(mb), llvm::SMLoc());
- }
-
- Token lex();
- const llvm::SourceMgr &getSourceMgr() const { return _sourceManager; }
-
-private:
- StringRef _buffer;
- llvm::SourceMgr _sourceManager;
-};
-
-class Directive {
-public:
- enum class Kind { exports, heapsize, library, name, stacksize, version };
-
- Kind getKind() const { return _kind; }
- virtual ~Directive() {}
-
-protected:
- explicit Directive(Kind k) : _kind(k) {}
-
-private:
- Kind _kind;
-};
-
-class Exports : public Directive {
-public:
- explicit Exports(const std::vector<PECOFFLinkingContext::ExportDesc> &exports)
- : Directive(Kind::exports), _exports(exports) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::exports;
- }
-
- const std::vector<PECOFFLinkingContext::ExportDesc> &getExports() const {
- return _exports;
- }
-
-private:
- const std::vector<PECOFFLinkingContext::ExportDesc> _exports;
-};
-
-template <Directive::Kind kind>
-class MemorySize : public Directive {
-public:
- MemorySize(uint64_t reserve, uint64_t commit)
- : Directive(kind), _reserve(reserve), _commit(commit) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == kind;
- }
-
- uint64_t getReserve() const { return _reserve; }
- uint64_t getCommit() const { return _commit; }
-
-private:
- const uint64_t _reserve;
- const uint64_t _commit;
-};
-
-typedef MemorySize<Directive::Kind::heapsize> Heapsize;
-typedef MemorySize<Directive::Kind::stacksize> Stacksize;
-
-class Name : public Directive {
-public:
- Name(StringRef outputPath, uint64_t baseaddr)
- : Directive(Kind::name), _outputPath(outputPath), _baseaddr(baseaddr) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::name;
- }
-
- StringRef getOutputPath() const { return _outputPath; }
- uint64_t getBaseAddress() const { return _baseaddr; }
-
-private:
- const std::string _outputPath;
- const uint64_t _baseaddr;
-};
-
-class Library : public Directive {
-public:
- Library(StringRef name, uint64_t baseaddr)
- : Directive(Kind::library), _name(name), _baseaddr(baseaddr) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::library;
- }
-
- StringRef getName() const { return _name; }
- uint64_t getBaseAddress() const { return _baseaddr; }
-
-private:
- const std::string _name;
- const uint64_t _baseaddr;
-};
-
-class Version : public Directive {
-public:
- Version(int major, int minor)
- : Directive(Kind::version), _major(major), _minor(minor) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::version;
- }
-
- int getMajorVersion() const { return _major; }
- int getMinorVersion() const { return _minor; }
-
-private:
- const int _major;
- const int _minor;
-};
-
-class Parser {
-public:
- Parser(Lexer &lex, llvm::BumpPtrAllocator &alloc)
- : _lex(lex), _alloc(alloc) {}
-
- bool parse(std::vector<Directive *> &ret);
-
-private:
- void consumeToken();
- bool consumeTokenAsInt(uint64_t &result);
- bool expectAndConsume(Kind kind, Twine msg);
-
- void ungetToken();
- void error(const Token &tok, Twine msg);
-
- bool parseOne(Directive *&dir);
- bool parseExport(PECOFFLinkingContext::ExportDesc &result);
- bool parseMemorySize(uint64_t &reserve, uint64_t &commit);
- bool parseName(std::string &outfile, uint64_t &baseaddr);
- bool parseVersion(int &major, int &minor);
-
- Lexer &_lex;
- llvm::BumpPtrAllocator &_alloc;
- Token _tok;
- std::vector<Token> _tokBuf;
-};
-}
-}
-
-#endif
diff --git a/include/lld/Makefile b/include/lld/Makefile
deleted file mode 100644
index 5bfb8910313e..000000000000
--- a/include/lld/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-LLD_LEVEL := ../..
-DIRS := Config
-
-include $(LLD_LEVEL)/Makefile
-
-install-local::
- $(Echo) Installing lld include files
- $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir)
- $(Verb) if test -d "$(PROJ_SRC_DIR)" ; then \
- cd $(PROJ_SRC_DIR)/.. && \
- for hdr in `find lld -type f \
- '(' -name LICENSE.TXT \
- -o -name '*.def' \
- -o -name '*.h' \
- -o -name '*.inc' \
- ')' -print \
- | grep -v CVS | grep -v .svn | grep -v .dir` ; do \
- instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
- if test \! -d "$$instdir" ; then \
- $(EchoCmd) Making install directory $$instdir ; \
- $(MKDIR) $$instdir ;\
- fi ; \
- $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
- done ; \
- fi
-ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
- $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/lld/include/lld" ; then \
- cd $(PROJ_OBJ_ROOT)/tools/lld/include && \
- for hdr in `find lld -type f \
- '(' -name LICENSE.TXT \
- -o -name '*.def' \
- -o -name '*.h' \
- -o -name '*.inc' \
- ')' -print \
- | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
- instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
- if test \! -d "$$instdir" ; then \
- $(EchoCmd) Making install directory $$instdir ; \
- $(MKDIR) $$instdir ;\
- fi ; \
- $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
- done ; \
- fi
-endif
diff --git a/include/lld/ReaderWriter/ELFLinkingContext.h b/include/lld/ReaderWriter/ELFLinkingContext.h
index d1cd3d9f3d6b..d1a5b28bb61f 100644
--- a/include/lld/ReaderWriter/ELFLinkingContext.h
+++ b/include/lld/ReaderWriter/ELFLinkingContext.h
@@ -26,24 +26,60 @@
#include <memory>
#include <set>
+namespace llvm {
+class FileOutputBuffer;
+}
+
namespace lld {
-class DefinedAtom;
-class Reference;
+struct AtomLayout;
class File;
+class Reference;
namespace elf {
-template <typename ELFT> class TargetHandler;
-}
+using llvm::object::ELF32LE;
+using llvm::object::ELF32BE;
+using llvm::object::ELF64LE;
+using llvm::object::ELF64BE;
+
+class ELFWriter;
+
+std::unique_ptr<ELFLinkingContext> createAArch64LinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createAMDGPULinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createARMLinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createExampleLinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createHexagonLinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createMipsLinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createX86LinkingContext(llvm::Triple);
+std::unique_ptr<ELFLinkingContext> createX86_64LinkingContext(llvm::Triple);
+
+class TargetRelocationHandler {
+public:
+ virtual ~TargetRelocationHandler() {}
+
+ virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+ const lld::AtomLayout &,
+ const Reference &) const = 0;
+};
-class TargetHandlerBase {
+} // namespace elf
+
+/// \brief TargetHandler contains all the information responsible to handle a
+/// a particular target on ELF. A target might wish to override implementation
+/// of creating atoms and how the atoms are written to the output file.
+class TargetHandler {
public:
- virtual ~TargetHandlerBase() {}
- virtual void registerRelocationNames(Registry &) = 0;
+ virtual ~TargetHandler() {}
+ /// Determines how relocations need to be applied.
+ virtual const elf::TargetRelocationHandler &getRelocationHandler() const = 0;
+
+ /// Returns a reader for object files.
virtual std::unique_ptr<Reader> getObjReader() = 0;
+ /// Returns a reader for .so files.
virtual std::unique_ptr<Reader> getDSOReader() = 0;
+ /// Returns a writer to write an ELF file.
virtual std::unique_ptr<Writer> getWriter() = 0;
};
@@ -52,28 +88,32 @@ public:
/// \brief The type of ELF executable that the linker
/// creates.
enum class OutputMagic : uint8_t {
- DEFAULT, // The default mode, no specific magic set
- NMAGIC, // Disallow shared libraries and don't align sections
- // PageAlign Data, Mark Text Segment/Data segment RW
- OMAGIC // Disallow shared libraries and don't align sections,
- // Mark Text Segment/Data segment RW
+ // The default mode, no specific magic set
+ DEFAULT,
+ // Disallow shared libraries and don't align sections
+ // PageAlign Data, Mark Text Segment/Data segment RW
+ NMAGIC,
+ // Disallow shared libraries and don't align sections,
+ // Mark Text Segment/Data segment RW
+ OMAGIC,
+ };
+
+ /// \brief ELF DT_FLAGS.
+ enum DTFlag : uint32_t {
+ DT_NOW = 1 << 1,
+ DT_ORIGIN = 1 << 2,
};
llvm::Triple getTriple() const { return _triple; }
- // Page size.
- virtual uint64_t getPageSize() const {
- if (_maxPageSize)
- return *_maxPageSize;
- return 0x1000;
- }
- virtual void setMaxPageSize(uint64_t pagesize) {
- _maxPageSize = pagesize;
- }
+ uint64_t getPageSize() const { return _maxPageSize; }
+ void setMaxPageSize(uint64_t v) { _maxPageSize = v; }
+
OutputMagic getOutputMagic() const { return _outputMagic; }
uint16_t getOutputELFType() const { return _outputELFType; }
uint16_t getOutputMachine() const;
bool mergeCommonStrings() const { return _mergeCommonStrings; }
+ virtual int getMachineType() const = 0;
virtual uint64_t getBaseAddress() const { return _baseAddress; }
virtual void setBaseAddress(uint64_t address) { _baseAddress = address; }
@@ -85,9 +125,9 @@ public:
/// created for every undefined symbol that are present in the dynamic table
/// in the shared library
bool useShlibUndefines() const { return _useShlibUndefines; }
- /// @}
- /// \brief Does this relocation belong in the dynamic relocation table?
+ /// \brief Returns true if a given relocation should be added to the
+ /// dynamic relocation table.
///
/// This table is evaluated at loadtime by the dynamic loader and is
/// referenced by the DT_RELA{,ENT,SZ} entries in the dynamic table.
@@ -95,20 +135,20 @@ public:
/// table.
virtual bool isDynamicRelocation(const Reference &) const { return false; }
- /// \brief Is this a copy relocation?
+ /// \brief Returns true if a given reference is a copy relocation.
///
/// If this is a copy relocation, its target must be an ObjectAtom. We must
/// include in DT_NEEDED the name of the library where this object came from.
- virtual bool isCopyRelocation(const Reference &) const {
- return false;
- }
+ virtual bool isCopyRelocation(const Reference &) const { return false; }
bool validateImpl(raw_ostream &diagnostics) override;
- /// \brief Does the linker allow dynamic libraries to be linked with?
+ /// \brief Returns true if the linker allows dynamic libraries to be
+ /// linked with.
+ ///
/// This is true when the output mode of the executable is set to be
/// having NMAGIC/OMAGIC
- virtual bool allowLinkWithDynamicLibraries() const {
+ bool allowLinkWithDynamicLibraries() const {
if (_outputMagic == OutputMagic::NMAGIC ||
_outputMagic == OutputMagic::OMAGIC || _noAllowDynamicLibraries)
return false;
@@ -118,7 +158,7 @@ public:
/// \brief Use Elf_Rela format to output relocation tables.
virtual bool isRelaOutputFormat() const { return true; }
- /// \brief Does this relocation belong in the dynamic plt relocation table?
+ /// \brief Returns true if a given relocation should be added to PLT.
///
/// This table holds all of the relocations used for delayed symbol binding.
/// It will be evaluated at load time if LD_BIND_NOW is set. It is referenced
@@ -133,30 +173,28 @@ public:
}
/// \brief The dynamic linker path set by the --dynamic-linker option
- virtual StringRef getInterpreter() const {
- if (_dynamicLinkerArg)
- return _dynamicLinkerPath;
+ StringRef getInterpreter() const {
+ if (_dynamicLinkerPath.hasValue())
+ return _dynamicLinkerPath.getValue();
return getDefaultInterpreter();
}
- /// \brief Does the output have dynamic sections.
- virtual bool isDynamic() const;
+ /// \brief Returns true if the output have dynamic sections.
+ bool isDynamic() const;
- /// \brief Are we creating a shared library?
- virtual bool isDynamicLibrary() const {
- return _outputELFType == llvm::ELF::ET_DYN;
- }
+ /// \brief Returns true if we are creating a shared library.
+ bool isDynamicLibrary() const { return _outputELFType == llvm::ELF::ET_DYN; }
- /// \brief Is the relocation a relative relocation
+ /// \brief Returns true if a given relocation is a relative relocation.
virtual bool isRelativeReloc(const Reference &r) const;
- template <typename ELFT>
- lld::elf::TargetHandler<ELFT> &getTargetHandler() const {
+ TargetHandler &getTargetHandler() const {
assert(_targetHandler && "Got null TargetHandler!");
- return static_cast<lld::elf::TargetHandler<ELFT> &>(*_targetHandler.get());
+ return *_targetHandler;
}
- TargetHandlerBase *targetHandler() const { return _targetHandler.get(); }
+ virtual void registerRelocationNames(Registry &) = 0;
+
void addPasses(PassManager &pm) override;
void setTriple(llvm::Triple trip) { _triple = trip; }
@@ -174,19 +212,16 @@ public:
void finalizeInputFiles() override;
/// \brief Set the dynamic linker path
- void setInterpreter(StringRef dynamicLinker) {
- _dynamicLinkerArg = true;
- _dynamicLinkerPath = dynamicLinker;
- }
+ void setInterpreter(StringRef s) { _dynamicLinkerPath = s; }
/// \brief Set NMAGIC output kind when the linker specifies --nmagic
/// or -n in the command line
/// Set OMAGIC output kind when the linker specifies --omagic
/// or -N in the command line
- virtual void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
+ void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
/// \brief Disallow dynamic libraries during linking
- virtual void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
+ void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
/// Searches directories for a match on the input File
ErrorOr<StringRef> searchLibrary(StringRef libName) const;
@@ -220,34 +255,17 @@ public:
_absoluteSymbols[name] = addr;
}
- void setSharedObjectName(StringRef soname) {
- _soname = soname;
- }
-
StringRef sharedObjectName() const { return _soname; }
+ void setSharedObjectName(StringRef soname) { _soname = soname; }
StringRef getSysroot() const { return _sysrootPath; }
+ void setSysroot(StringRef path) { _sysrootPath = path; }
- /// \brief Set path to the system root
- void setSysroot(StringRef path) {
- _sysrootPath = path;
- }
-
- void addRpath(StringRef path) {
- _rpathList.push_back(path);
- }
-
- range<const StringRef *> getRpathList() const {
- return _rpathList;
- }
-
- void addRpathLink(StringRef path) {
- _rpathLinkList.push_back(path);
- }
+ void addRpath(StringRef path) { _rpathList.push_back(path); }
+ range<const StringRef *> getRpathList() const { return _rpathList; }
- range<const StringRef *> getRpathLinkList() const {
- return _rpathLinkList;
- }
+ void addRpathLink(StringRef path) { _rpathLinkList.push_back(path); }
+ range<const StringRef *> getRpathLinkList() const { return _rpathLinkList; }
const std::map<std::string, uint64_t> &getAbsoluteSymbols() const {
return _absoluteSymbols;
@@ -262,13 +280,10 @@ public:
}
// add search path to list.
- virtual bool addSearchPath(StringRef ref) {
- _inputSearchPaths.push_back(ref);
- return true;
- }
+ void addSearchPath(StringRef ref) { _inputSearchPaths.push_back(ref); }
// Retrieve search path list.
- StringRefVector getSearchPaths() { return _inputSearchPaths; };
+ StringRefVector getSearchPaths() { return _inputSearchPaths; }
// By default, the linker would merge sections that are read only with
// segments that have read and execute permissions. When the user specifies a
@@ -290,6 +305,26 @@ public:
bool alignSegments() const { return _alignSegments; }
void setAlignSegments(bool align) { _alignSegments = align; }
+ /// \brief Enable new dtags.
+ /// If this flag is set lld emits DT_RUNPATH instead of
+ /// DT_RPATH. They are functionally equivalent except for
+ /// the following two differences:
+ /// - DT_RUNPATH is searched after LD_LIBRARY_PATH, while
+ /// DT_RPATH is searched before.
+ /// - DT_RUNPATH is used only to search for direct dependencies
+ /// of the object it's contained in, while DT_RPATH is used
+ /// for indirect dependencies as well.
+ bool getEnableNewDtags() const { return _enableNewDtags; }
+ void setEnableNewDtags(bool e) { _enableNewDtags = e; }
+
+ /// \brief Discard local symbols.
+ bool discardLocals() const { return _discardLocals; }
+ void setDiscardLocals(bool d) { _discardLocals = d; }
+
+ /// \brief Discard temprorary local symbols.
+ bool discardTempLocals() const { return _discardTempLocals; }
+ void setDiscardTempLocals(bool d) { _discardTempLocals = d; }
+
/// \brief Strip symbols.
bool stripSymbols() const { return _stripSymbols; }
void setStripSymbols(bool strip) { _stripSymbols = strip; }
@@ -301,6 +336,10 @@ public:
// --wrap option.
void addWrapForSymbol(StringRef sym) { _wrapCalls.insert(sym); }
+ // \brief Set DT_FLAGS flag.
+ void setDTFlag(DTFlag f) { _dtFlags |= f; }
+ bool getDTFlag(DTFlag f) { return (_dtFlags & f); }
+
const llvm::StringSet<> &wrapCalls() const { return _wrapCalls; }
void setUndefinesResolver(std::unique_ptr<File> resolver);
@@ -308,43 +347,61 @@ public:
script::Sema &linkerScriptSema() { return _linkerScriptSema; }
const script::Sema &linkerScriptSema() const { return _linkerScriptSema; }
-private:
- ELFLinkingContext() = delete;
+ /// Notify the ELFLinkingContext when the new ELF section is read.
+ void notifyInputSectionName(StringRef name);
+ /// Encountered C-ident input section names.
+ const llvm::StringSet<> &cidentSectionNames() const {
+ return _cidentSections;
+ }
+
+ // Set R_ARM_TARGET1 relocation behaviour
+ bool armTarget1Rel() const { return _armTarget1Rel; }
+ void setArmTarget1Rel(bool value) { _armTarget1Rel = value; }
+
+ // Set R_MIPS_EH relocation behaviour.
+ bool mipsPcRelEhRel() const { return _mipsPcRelEhRel; }
+ void setMipsPcRelEhRel(bool value) { _mipsPcRelEhRel = value; }
protected:
- ELFLinkingContext(llvm::Triple, std::unique_ptr<TargetHandlerBase>);
+ ELFLinkingContext(llvm::Triple triple, std::unique_ptr<TargetHandler> handler)
+ : _triple(triple), _targetHandler(std::move(handler)) {}
Writer &writer() const override;
/// Method to create a internal file for an undefined symbol
std::unique_ptr<File> createUndefinedSymbolFile() const override;
- uint16_t _outputELFType; // e.g ET_EXEC
+ uint16_t _outputELFType = llvm::ELF::ET_EXEC;
llvm::Triple _triple;
- std::unique_ptr<TargetHandlerBase> _targetHandler;
- uint64_t _baseAddress;
- bool _isStaticExecutable;
- bool _noInhibitExec;
- bool _exportDynamic;
- bool _mergeCommonStrings;
- bool _useShlibUndefines;
- bool _dynamicLinkerArg;
- bool _noAllowDynamicLibraries;
- bool _mergeRODataToTextSegment;
- bool _demangle;
- bool _stripSymbols;
- bool _alignSegments;
- bool _nostdlib;
- bool _collectStats;
- llvm::Optional<uint64_t> _maxPageSize;
-
- OutputMagic _outputMagic;
+ std::unique_ptr<TargetHandler> _targetHandler;
+ uint64_t _baseAddress = 0;
+ bool _isStaticExecutable = false;
+ bool _noInhibitExec = false;
+ bool _exportDynamic = false;
+ bool _mergeCommonStrings = false;
+ bool _useShlibUndefines = true;
+ bool _dynamicLinkerArg = false;
+ bool _noAllowDynamicLibraries = false;
+ bool _mergeRODataToTextSegment = true;
+ bool _demangle = true;
+ bool _discardTempLocals = false;
+ bool _discardLocals = false;
+ bool _stripSymbols = false;
+ bool _alignSegments = true;
+ bool _enableNewDtags = false;
+ bool _collectStats = false;
+ bool _armTarget1Rel = false;
+ bool _mipsPcRelEhRel = false;
+ uint64_t _maxPageSize = 0x1000;
+ uint32_t _dtFlags = 0;
+
+ OutputMagic _outputMagic = OutputMagic::DEFAULT;
StringRefVector _inputSearchPaths;
std::unique_ptr<Writer> _writer;
- StringRef _dynamicLinkerPath;
- StringRef _initFunction;
- StringRef _finiFunction;
- StringRef _sysrootPath;
+ llvm::Optional<StringRef> _dynamicLinkerPath;
+ StringRef _initFunction = "_init";
+ StringRef _finiFunction = "_fini";
+ StringRef _sysrootPath = "";
StringRef _soname;
StringRefVector _rpathList;
StringRefVector _rpathLinkList;
@@ -352,11 +409,14 @@ protected:
std::map<std::string, uint64_t> _absoluteSymbols;
llvm::StringSet<> _dynamicallyExportedSymbols;
std::unique_ptr<File> _resolver;
+ std::mutex _cidentMutex;
+ llvm::StringSet<> _cidentSections;
// The linker script semantic object, which owns all script ASTs, is stored
// in the current linking context via _linkerScriptSema.
script::Sema _linkerScriptSema;
};
+
} // end namespace lld
#endif
diff --git a/include/lld/ReaderWriter/ELFTargets.h b/include/lld/ReaderWriter/ELFTargets.h
deleted file mode 100644
index 3d00339818e2..000000000000
--- a/include/lld/ReaderWriter/ELFTargets.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- lld/ReaderWriter/ELFTargets.h --------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_TARGETS_H
-#define LLD_READER_WRITER_ELF_TARGETS_H
-
-#include "ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-#define LLVM_TARGET(TargetName) \
- class TargetName##LinkingContext final : public ELFLinkingContext { \
- public: \
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple); \
- };
-
-// FIXME: #include "llvm/Config/Targets.def"
-LLVM_TARGET(AArch64)
-LLVM_TARGET(ARM)
-LLVM_TARGET(Hexagon)
-LLVM_TARGET(Mips)
-LLVM_TARGET(X86)
-LLVM_TARGET(Example)
-LLVM_TARGET(X86_64)
-
-#undef LLVM_TARGET
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/LinkerScript.h b/include/lld/ReaderWriter/LinkerScript.h
index ae8d18d830c6..08ccb89ce8c1 100644
--- a/include/lld/ReaderWriter/LinkerScript.h
+++ b/include/lld/ReaderWriter/LinkerScript.h
@@ -20,6 +20,7 @@
#include "lld/Core/range.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
@@ -78,6 +79,9 @@ public:
kw_entry,
kw_exclude_file,
kw_extern,
+ kw_filehdr,
+ kw_fill,
+ kw_flags,
kw_group,
kw_hidden,
kw_input,
@@ -85,6 +89,7 @@ public:
kw_length,
kw_memory,
kw_origin,
+ kw_phdrs,
kw_provide,
kw_provide_hidden,
kw_only_if_ro,
@@ -160,6 +165,7 @@ public:
enum class Kind {
Entry,
Extern,
+ Fill,
Group,
Input,
InputSectionsCmd,
@@ -170,6 +176,7 @@ public:
OutputFormat,
OutputSectionDescription,
Overlay,
+ PHDRS,
SearchDir,
Sections,
SortedGroup,
@@ -191,6 +198,14 @@ private:
Kind _kind;
};
+template <class T>
+ArrayRef<T> save_array(llvm::BumpPtrAllocator &alloc, ArrayRef<T> array) {
+ size_t num = array.size();
+ T *start = alloc.Allocate<T>(num);
+ std::uninitialized_copy(std::begin(array), std::end(array), start);
+ return llvm::makeArrayRef(start, num);
+}
+
class Output : public Command {
public:
Output(Parser &ctx, StringRef outputFileName)
@@ -212,10 +227,7 @@ class OutputFormat : public Command {
public:
OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
: Command(ctx, Kind::OutputFormat) {
- size_t numFormats = formats.size();
- StringRef *formatsStart = getAllocator().Allocate<StringRef>(numFormats);
- std::copy(std::begin(formats), std::end(formats), formatsStart);
- _formats = llvm::makeArrayRef(formatsStart, numFormats);
+ _formats = save_array<StringRef>(getAllocator(), formats);
}
static bool classof(const Command *c) {
@@ -274,10 +286,7 @@ class PathList : public Command {
public:
PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
: Command(ctx, K), _name(name) {
- size_t numPaths = paths.size();
- Path *pathsStart = getAllocator().template Allocate<Path>(numPaths);
- std::copy(std::begin(paths), std::end(paths), pathsStart);
- _paths = llvm::makeArrayRef(pathsStart, numPaths);
+ _paths = save_array<Path>(getAllocator(), paths);
}
static bool classof(const Command *c) { return c->getKind() == K; }
@@ -382,7 +391,8 @@ public:
Kind getKind() const { return _kind; }
inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
- virtual ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const = 0;
+ virtual ErrorOr<int64_t>
+ evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
virtual ~Expression() {}
protected:
@@ -406,7 +416,7 @@ public:
return c->getKind() == Kind::Constant;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
uint64_t _num;
@@ -422,7 +432,7 @@ public:
return c->getKind() == Kind::Symbol;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -433,11 +443,7 @@ public:
FunctionCall(Parser &ctx, StringRef name,
const SmallVectorImpl<const Expression *> &args)
: Expression(ctx, Kind::FunctionCall), _name(name) {
- size_t numArgs = args.size();
- const Expression **argsStart =
- getAllocator().Allocate<const Expression *>(numArgs);
- std::copy(std::begin(args), std::end(args), argsStart);
- _args = llvm::makeArrayRef(argsStart, numArgs);
+ _args = save_array<const Expression *>(getAllocator(), args);
}
void dump(raw_ostream &os) const override;
@@ -446,7 +452,7 @@ public:
return c->getKind() == Kind::FunctionCall;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -468,7 +474,7 @@ public:
return c->getKind() == Kind::Unary;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -503,7 +509,7 @@ public:
return c->getKind() == Kind::BinOp;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -538,7 +544,7 @@ public:
return c->getKind() == Kind::TernaryConditional;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
const Expression *_conditional;
@@ -647,11 +653,7 @@ public:
InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
const SmallVectorImpl<const InputSection *> &sections)
: InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -691,11 +693,7 @@ public:
: Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
_archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
_archiveSortMode(archiveSortMode) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -720,6 +718,24 @@ private:
llvm::ArrayRef<const InputSection *> _sections;
};
+class FillCmd : public Command {
+public:
+ FillCmd(Parser &ctx, ArrayRef<uint8_t> bytes) : Command(ctx, Kind::Fill) {
+ _bytes = save_array<uint8_t>(getAllocator(), bytes);
+ }
+
+ void dump(raw_ostream &os) const override;
+
+ static bool classof(const Command *c) {
+ return c->getKind() == Kind::Fill;
+ }
+
+ ArrayRef<uint8_t> bytes() { return _bytes; }
+
+private:
+ ArrayRef<uint8_t> _bytes;
+};
+
/// A sections-command to specify which input sections and symbols compose a
/// given output section.
/// Example:
@@ -743,18 +759,16 @@ public:
const Expression *align, const Expression *subAlign, const Expression *at,
const Expression *fillExpr, StringRef fillStream, bool alignWithInput,
bool discard, Constraint constraint,
- const SmallVectorImpl<const Command *> &outputSectionCommands)
+ const SmallVectorImpl<const Command *> &outputSectionCommands,
+ ArrayRef<StringRef> phdrs)
: Command(ctx, Kind::OutputSectionDescription), _sectionName(sectionName),
_address(address), _align(align), _subAlign(subAlign), _at(at),
_fillExpr(fillExpr), _fillStream(fillStream),
_alignWithInput(alignWithInput), _discard(discard),
_constraint(constraint) {
- size_t numCommands = outputSectionCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(outputSectionCommands),
- std::end(outputSectionCommands), commandsStart);
- _outputSectionCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _outputSectionCommands =
+ save_array<const Command *>(getAllocator(), outputSectionCommands);
+ _phdrs = save_array<StringRef>(getAllocator(), phdrs);
}
static bool classof(const Command *c) {
@@ -766,6 +780,8 @@ public:
const_iterator begin() const { return _outputSectionCommands.begin(); }
const_iterator end() const { return _outputSectionCommands.end(); }
StringRef name() const { return _sectionName; }
+ bool isDiscarded() const { return _discard; }
+ ArrayRef<StringRef> PHDRs() const { return _phdrs; }
private:
StringRef _sectionName;
@@ -779,6 +795,7 @@ private:
bool _discard;
Constraint _constraint;
llvm::ArrayRef<const Command *> _outputSectionCommands;
+ ArrayRef<StringRef> _phdrs;
};
/// Represents an Overlay structure as documented in
@@ -794,6 +811,52 @@ public:
void dump(raw_ostream &os) const override { os << "Overlay description\n"; }
};
+class PHDR {
+public:
+ PHDR(StringRef name, uint64_t type, bool includeFileHdr, bool includePHDRs,
+ const Expression *at, uint64_t flags)
+ : _name(name), _type(type), _includeFileHdr(includeFileHdr),
+ _includePHDRs(includePHDRs), _at(at), _flags(flags) {}
+
+ StringRef name() const { return _name; }
+ uint64_t type() const { return _type; }
+ bool hasFileHdr() const { return _includeFileHdr; }
+ bool hasPHDRs() const { return _includePHDRs; }
+ uint64_t flags() const { return _flags; }
+ bool isNone() const;
+
+ void dump(raw_ostream &os) const;
+
+private:
+ StringRef _name;
+ uint64_t _type;
+ bool _includeFileHdr;
+ bool _includePHDRs;
+ const Expression *_at;
+ uint64_t _flags;
+};
+
+class PHDRS : public Command {
+public:
+ typedef ArrayRef<const PHDR *>::const_iterator const_iterator;
+
+ PHDRS(Parser &ctx, const SmallVectorImpl<const PHDR *> &phdrs)
+ : Command(ctx, Kind::PHDRS) {
+ _phdrs = save_array<const PHDR *>(getAllocator(), phdrs);
+ }
+
+ static bool classof(const Command *c) {
+ return c->getKind() == Kind::PHDRS;
+ }
+
+ void dump(raw_ostream &os) const override;
+ const_iterator begin() const { return _phdrs.begin(); }
+ const_iterator end() const { return _phdrs.end(); }
+
+private:
+ ArrayRef<const PHDR *> _phdrs;
+};
+
/// Represents all the contents of the SECTIONS {} construct.
class Sections : public Command {
public:
@@ -802,12 +865,8 @@ public:
Sections(Parser &ctx,
const SmallVectorImpl<const Command *> &sectionsCommands)
: Command(ctx, Kind::Sections) {
- size_t numCommands = sectionsCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(sectionsCommands), std::end(sectionsCommands),
- commandsStart);
- _sectionsCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _sectionsCommands =
+ save_array<const Command *>(getAllocator(), sectionsCommands);
}
static bool classof(const Command *c) {
@@ -844,11 +903,7 @@ public:
Memory(Parser &ctx,
const SmallVectorImpl<const MemoryBlock *> &blocks)
: Command(ctx, Kind::Memory) {
- size_t numBlocks = blocks.size();
- const MemoryBlock **blocksStart =
- getAllocator().Allocate<const MemoryBlock *>(numBlocks);
- std::copy(std::begin(blocks), std::end(blocks), blocksStart);
- _blocks = llvm::makeArrayRef(blocksStart, numBlocks);
+ _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
}
static bool classof(const Command *c) {
@@ -869,11 +924,7 @@ public:
Extern(Parser &ctx,
const SmallVectorImpl<StringRef> &symbols)
: Command(ctx, Kind::Extern) {
- size_t numSymbols = symbols.size();
- StringRef *symbolsStart =
- getAllocator().Allocate<StringRef>(numSymbols);
- std::copy(std::begin(symbols), std::end(symbols), symbolsStart);
- _symbols = llvm::makeArrayRef(symbolsStart, numSymbols);
+ _symbols = save_array<StringRef>(getAllocator(), symbols);
}
static bool classof(const Command *c) {
@@ -1133,6 +1184,8 @@ private:
/// }
const InputSectionsCmd *parseInputSectionsCmd();
+ const FillCmd *parseFillCmd();
+
/// Parse output section description statements.
/// Example:
///
@@ -1145,6 +1198,10 @@ private:
/// Stub for parsing overlay commands. Currently unimplemented.
const Overlay *parseOverlay();
+ const PHDR *parsePHDR();
+
+ PHDRS *parsePHDRS();
+
/// Parse the SECTIONS linker script command.
/// Example:
///
@@ -1231,7 +1288,7 @@ public:
/// Prepare our data structures according to the linker scripts currently in
/// our control (control given via addLinkerScript()). Called once all linker
/// scripts have been parsed.
- void perform();
+ std::error_code perform();
/// Answer if we have layout commands (section mapping rules). If we don't,
/// the output file writer can assume there is no linker script special rule
@@ -1273,6 +1330,15 @@ public:
/// has been performed (by calling evalExpr() for all expressions).
uint64_t getLinkerScriptExprValue(StringRef name) const;
+ /// Check if there are custom headers available.
+ bool hasPHDRs() const;
+
+ /// Retrieve all the headers the given output section is assigned to.
+ std::vector<const PHDR *> getPHDRsForOutputSection(StringRef name) const;
+
+ /// Retrieve program header if available.
+ const PHDR *getProgramPHDR() const;
+
void dump() const;
private:
@@ -1314,6 +1380,14 @@ private:
bool localCompare(int order, const SectionKey &lhs,
const SectionKey &rhs) const;
+ /// Convert the PHDRS command into map of names to headers.
+ /// Determine program header during processing.
+ std::error_code collectPHDRs(const PHDRS *ph,
+ llvm::StringMap<const PHDR *> &phdrs);
+
+ /// Build map that matches output section names to segments they should be
+ /// put into.
+ std::error_code buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs);
/// Our goal with all linearizeAST overloaded functions is to
/// traverse the linker script AST while putting nodes in a vector and
@@ -1370,8 +1444,6 @@ private:
void linearizeAST(const InputSectionsCmd *inputSections);
void linearizeAST(const InputSection *inputSection);
- void perform(const LinkerScript *ls);
-
std::vector<std::unique_ptr<Parser>> _scripts;
std::vector<const Command *> _layoutCommands;
std::unordered_multimap<std::string, int> _memberToLayoutOrder;
@@ -1381,6 +1453,9 @@ private:
llvm::DenseSet<int> _deliveredExprs;
mutable llvm::StringSet<> _definedSymbols;
+ llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
+ const PHDR *_programPHDR;
+
Expression::SymbolTableTy _symbolTable;
};
diff --git a/include/lld/ReaderWriter/MachOLinkingContext.h b/include/lld/ReaderWriter/MachOLinkingContext.h
index 8e253a1235f1..dc44d3f303f8 100644
--- a/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -27,12 +27,13 @@ namespace mach_o {
class ArchHandler;
class MachODylibFile;
class MachOFile;
+class SectCreateFile;
}
class MachOLinkingContext : public LinkingContext {
public:
MachOLinkingContext();
- ~MachOLinkingContext();
+ ~MachOLinkingContext() override;
enum Arch {
arch_unknown,
@@ -63,6 +64,13 @@ public:
noDebugMap // -S option
};
+ enum class UndefinedMode {
+ error,
+ warning,
+ suppress,
+ dynamicLookup
+ };
+
/// Initializes the context to sane default values given the specified output
/// file type, arch, os, and minimum os version. This should be called before
/// other setXXX() methods.
@@ -72,7 +80,7 @@ public:
bool validateImpl(raw_ostream &diagnostics) override;
std::string demangle(StringRef symbolName) const override;
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
@@ -129,6 +137,9 @@ public:
bool PIE() const { return _pie; }
void setPIE(bool pie) { _pie = pie; }
+ uint64_t stackSize() const { return _stackSize; }
+ void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
+
uint64_t baseAddress() const { return _baseAddress; }
void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
@@ -201,6 +212,30 @@ public:
/// when linking a binary that does not use any of its symbols.
bool deadStrippableDylib() const { return _deadStrippableDylib; }
+ /// \brief Whether or not to use flat namespace.
+ ///
+ /// MachO usually uses a two-level namespace, where each external symbol
+ /// referenced by the target is associated with the dylib that will provide
+ /// the symbol's definition at runtime. Using flat namespace overrides this
+ /// behavior: the linker searches all dylibs on the command line and all
+ /// dylibs those original dylibs depend on, but does not record which dylib
+ /// an external symbol came from. At runtime dyld again searches all images
+ /// and uses the first definition it finds. In addition, any undefines in
+ /// loaded flat_namespace dylibs must be resolvable at build time.
+ bool useFlatNamespace() const { return _flatNamespace; }
+
+ /// \brief How to handle undefined symbols.
+ ///
+ /// Options are:
+ /// * error: Report an error and terminate linking.
+ /// * warning: Report a warning, but continue linking.
+ /// * suppress: Ignore and continue linking.
+ /// * dynamic_lookup: For use with -twolevel namespace: Records source dylibs
+ /// for symbols that are defined in a linked dylib at static link time.
+ /// Undefined symbols are handled by searching all loaded images at
+ /// runtime.
+ UndefinedMode undefinedMode() const { return _undefinedMode; }
+
/// \brief The path to the executable that will load the bundle at runtime.
///
/// When building a Mach-O bundle, this executable will be examined if there
@@ -215,6 +250,14 @@ public:
void setDeadStrippableDylib(bool deadStrippable) {
_deadStrippableDylib = deadStrippable;
}
+ void setUseFlatNamespace(bool flatNamespace) {
+ _flatNamespace = flatNamespace;
+ }
+
+ void setUndefinedMode(UndefinedMode undefinedMode) {
+ _undefinedMode = undefinedMode;
+ }
+
void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
void setPrintAtoms(bool value=true) { _printAtoms = value; }
void setTestingFileUsage(bool value = true) {
@@ -228,10 +271,14 @@ public:
const StringRefVector &rpaths() const { return _rpaths; }
/// Add section alignment constraint on final layout.
- void addSectionAlignment(StringRef seg, StringRef sect, uint8_t align2);
+ void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
+
+ /// \brief Add a section based on a command-line sectcreate option.
+ void addSectCreateSection(StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content);
/// Returns true if specified section had alignment constraints.
- bool sectionAligned(StringRef seg, StringRef sect, uint8_t &align2) const;
+ bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
StringRef dyldPath() const { return "/usr/lib/dyld"; }
@@ -241,6 +288,9 @@ public:
// GOT creation Pass should be run.
bool needsGOTPass() const;
+ /// Pass to add TLV sections.
+ bool needsTLVPass() const;
+
/// Pass to transform __compact_unwind into __unwind_info should be run.
bool needsCompactUnwindPass() const;
@@ -271,8 +321,7 @@ public:
/// If the memoryBuffer is a fat file with a slice for the current arch,
/// this method will return the offset and size of that slice.
- bool sliceFromFatFile(const MemoryBuffer &mb, uint32_t &offset,
- uint32_t &size);
+ bool sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset, uint32_t &size);
/// Returns if a command line option specified dylib is an upward link.
bool isUpwardDylib(StringRef installName) const;
@@ -296,6 +345,11 @@ public:
bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
bool &leftBeforeRight) const;
+ /// Return the 'flat namespace' file. This is the file that supplies
+ /// atoms for otherwise undefined symbols when the -flat_namespace or
+ /// -undefined dynamic_lookup options are used.
+ File* flatNamespaceFile() const { return _flatNamespaceFile; }
+
private:
Writer &writer() const override;
mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
@@ -312,7 +366,7 @@ private:
struct SectionAlign {
StringRef segmentName;
StringRef sectionName;
- uint8_t align2;
+ uint16_t align;
};
struct OrderFileNode {
@@ -339,10 +393,13 @@ private:
uint64_t _pageZeroSize;
uint64_t _pageSize;
uint64_t _baseAddress;
+ uint64_t _stackSize;
uint32_t _compatibilityVersion;
uint32_t _currentVersion;
StringRef _installName;
StringRefVector _rpaths;
+ bool _flatNamespace;
+ UndefinedMode _undefinedMode;
bool _deadStrippableDylib;
bool _printAtoms;
bool _testingFileUsage;
@@ -356,14 +413,17 @@ private:
mutable std::set<mach_o::MachODylibFile*> _allDylibs;
mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
+ mutable std::mutex _dylibsMutex;
ExportMode _exportMode;
llvm::StringSet<> _exportedSymbols;
DebugInfoMode _debugInfoMode;
std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
unsigned _orderFileEntries;
+ File *_flatNamespaceFile;
+ mach_o::SectCreateFile *_sectCreateFile = nullptr;
};
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
diff --git a/include/lld/ReaderWriter/PECOFFLinkingContext.h b/include/lld/ReaderWriter/PECOFFLinkingContext.h
deleted file mode 100644
index cccb8ac03b6e..000000000000
--- a/include/lld/ReaderWriter/PECOFFLinkingContext.h
+++ /dev/null
@@ -1,463 +0,0 @@
-//===- lld/ReaderWriter/PECOFFLinkingContext.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_PECOFF_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileUtilities.h"
-#include <map>
-#include <mutex>
-#include <set>
-#include <vector>
-
-using llvm::COFF::MachineTypes;
-using llvm::COFF::WindowsSubsystem;
-
-static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
-
-namespace lld {
-
-class PECOFFLinkingContext : public LinkingContext {
-public:
- PECOFFLinkingContext()
- : _mutex(), _allocMutex(), _hasEntry(true),
- _baseAddress(invalidBaseAddress), _stackReserve(1024 * 1024),
- _stackCommit(4096), _heapReserve(1024 * 1024), _heapCommit(4096),
- _noDefaultLibAll(false), _sectionDefaultAlignment(4096),
- _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
- _machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386), _imageVersion(0, 0),
- _minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
- _allowBind(true), _allowIsolation(true), _swapRunFromCD(false),
- _swapRunFromNet(false), _baseRelocationEnabled(true),
- _terminalServerAware(true), _dynamicBaseEnabled(true),
- _createManifest(true), _embedManifest(false), _manifestId(1),
- _manifestUAC(true), _manifestLevel("'asInvoker'"),
- _manifestUiAccess("'false'"), _isDll(false), _highEntropyVA(true),
- _requireSEH(false), _noSEH(false), _implib(""), _debug(false),
- _pdbFilePath(""), _dosStub(llvm::makeArrayRef(DEFAULT_DOS_STUB)),
- _parseDirectives(nullptr) {
- setDeadStripping(true);
- }
-
- struct Version {
- Version(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
- int majorVersion;
- int minorVersion;
- };
-
- struct ExportDesc {
- ExportDesc()
- : ordinal(-1), noname(false), isData(false), isPrivate(false) {}
-
- bool operator<(const ExportDesc &other) const {
- return getExternalName().compare(other.getExternalName()) < 0;
- }
-
- StringRef getRealName() const {
- return mangledName.empty() ? name : mangledName;
- }
-
- StringRef getExternalName() const {
- return externalName.empty() ? name : externalName;
- }
-
- std::string name;
- std::string externalName;
- std::string mangledName;
- int ordinal;
- bool noname;
- bool isData;
- bool isPrivate;
- };
-
- typedef bool (*ParseDirectives)(int, const char **, PECOFFLinkingContext &,
- raw_ostream &);
-
- /// \brief Casting support
- static bool classof(const LinkingContext *info) { return true; }
-
- Writer &writer() const override;
- bool validateImpl(raw_ostream &diagnostics) override;
-
- void addPasses(PassManager &pm) override;
-
- bool createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) override;
-
- bool is64Bit() const {
- return _machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
- }
-
- // Returns a set of all defined symbols in input files.
- const std::set<std::string> &definedSymbols();
-
- /// Page size of x86 processor. Some data needs to be aligned at page boundary
- /// when loaded into memory.
- uint64_t getPageSize() const {
- return 0x1000;
- }
-
- void appendInputSearchPath(StringRef dirPath) {
- _inputSearchPaths.push_back(dirPath);
- }
-
- const std::vector<StringRef> getInputSearchPaths() {
- return _inputSearchPaths;
- }
-
- void registerTemporaryFile(StringRef path) {
- std::unique_ptr<llvm::FileRemover> fileRemover(
- new llvm::FileRemover(Twine(allocate(path))));
- _tempFiles.push_back(std::move(fileRemover));
- }
-
- StringRef searchLibraryFile(StringRef path) const;
-
- StringRef decorateSymbol(StringRef name) const;
- StringRef undecorateSymbol(StringRef name) const;
-
- void setEntrySymbolName(StringRef name) { _entry = name; }
- StringRef getEntrySymbolName() const { return _entry; }
-
- void setHasEntry(bool val) { _hasEntry = val; }
- bool hasEntry() const { return _hasEntry; }
-
- void setBaseAddress(uint64_t addr) { _baseAddress = addr; }
- uint64_t getBaseAddress() const;
-
- void setStackReserve(uint64_t size) { _stackReserve = size; }
- void setStackCommit(uint64_t size) { _stackCommit = size; }
- uint64_t getStackReserve() const { return _stackReserve; }
- uint64_t getStackCommit() const { return _stackCommit; }
-
- void setHeapReserve(uint64_t size) { _heapReserve = size; }
- void setHeapCommit(uint64_t size) { _heapCommit = size; }
- uint64_t getHeapReserve() const { return _heapReserve; }
- uint64_t getHeapCommit() const { return _heapCommit; }
-
- void setSectionDefaultAlignment(uint32_t val) {
- _sectionDefaultAlignment = val;
- }
- uint32_t getSectionDefaultAlignment() const {
- return _sectionDefaultAlignment;
- }
-
- void setSubsystem(WindowsSubsystem ss) { _subsystem = ss; }
- WindowsSubsystem getSubsystem() const { return _subsystem; }
-
- void setMachineType(MachineTypes type) { _machineType = type; }
- MachineTypes getMachineType() const { return _machineType; }
-
- void setImageVersion(const Version &version) { _imageVersion = version; }
- Version getImageVersion() const { return _imageVersion; }
-
- void setMinOSVersion(const Version &version) { _minOSVersion = version; }
- Version getMinOSVersion() const { return _minOSVersion; }
-
- void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
- bool isNxCompat() const { return _nxCompat; }
-
- void setLargeAddressAware(bool val) { _largeAddressAware = val; }
- bool getLargeAddressAware() const { return _largeAddressAware; }
-
- void setAllowBind(bool val) { _allowBind = val; }
- bool getAllowBind() const { return _allowBind; }
-
- void setAllowIsolation(bool val) { _allowIsolation = val; }
- bool getAllowIsolation() const { return _allowIsolation; }
-
- void setSwapRunFromCD(bool val) { _swapRunFromCD = val; }
- bool getSwapRunFromCD() const { return _swapRunFromCD; }
-
- void setSwapRunFromNet(bool val) { _swapRunFromNet = val; }
- bool getSwapRunFromNet() const { return _swapRunFromNet; }
-
- void setBaseRelocationEnabled(bool val) { _baseRelocationEnabled = val; }
- bool getBaseRelocationEnabled() const { return _baseRelocationEnabled; }
-
- void setTerminalServerAware(bool val) { _terminalServerAware = val; }
- bool isTerminalServerAware() const { return _terminalServerAware; }
-
- void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
- bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
-
- void setCreateManifest(bool val) { _createManifest = val; }
- bool getCreateManifest() const { return _createManifest; }
-
- void setManifestOutputPath(std::string val) { _manifestOutputPath = val; }
- const std::string &getManifestOutputPath() const {
- return _manifestOutputPath;
- }
-
- void setEmbedManifest(bool val) { _embedManifest = val; }
- bool getEmbedManifest() const { return _embedManifest; }
-
- void setManifestId(int val) { _manifestId = val; }
- int getManifestId() const { return _manifestId; }
-
- void setManifestUAC(bool val) { _manifestUAC = val; }
- bool getManifestUAC() const { return _manifestUAC; }
-
- void setManifestLevel(std::string val) { _manifestLevel = std::move(val); }
- const std::string &getManifestLevel() const { return _manifestLevel; }
-
- void setManifestUiAccess(std::string val) { _manifestUiAccess = val; }
- const std::string &getManifestUiAccess() const { return _manifestUiAccess; }
-
- void setManifestDependency(std::string val) { _manifestDependency = val; }
- const std::string &getManifestDependency() const {
- return _manifestDependency;
- }
-
- void setIsDll(bool val) { _isDll = val; }
- bool isDll() const { return _isDll; }
-
- void setSafeSEH(bool val) {
- if (val)
- _requireSEH = true;
- else
- _noSEH = true;
- }
- bool requireSEH() const { return _requireSEH; }
- bool noSEH() const { return _noSEH; }
-
- void setHighEntropyVA(bool val) { _highEntropyVA = val; }
- bool getHighEntropyVA() const { return _highEntropyVA; }
-
- void setOutputImportLibraryPath(const std::string &val) { _implib = val; }
- std::string getOutputImportLibraryPath() const;
-
- void setDebug(bool val) { _debug = val; }
- bool getDebug() { return _debug; }
-
- void setPDBFilePath(StringRef str) { _pdbFilePath = str; }
- std::string getPDBFilePath() const;
-
- void addDelayLoadDLL(StringRef dll) {
- _delayLoadDLLs.insert(dll.lower());
- }
- bool isDelayLoadDLL(StringRef dll) const {
- return _delayLoadDLLs.count(dll.lower()) == 1;
- }
-
- StringRef getOutputSectionName(StringRef sectionName) const;
- bool addSectionRenaming(raw_ostream &diagnostics,
- StringRef from, StringRef to);
-
- const std::set<std::string> &getAlternateNames(StringRef name) {
- return _alternateNames[name];
- }
-
- void addAlternateName(StringRef weak, StringRef def) {
- _alternateNames[def].insert(weak);
- }
-
- void addNoDefaultLib(StringRef path) {
- if (path.endswith_lower(".lib"))
- _noDefaultLibs.insert(path.drop_back(4).lower());
- else
- _noDefaultLibs.insert(path.lower());
- }
-
- bool hasNoDefaultLib(StringRef path) const {
- if (path.endswith_lower(".lib"))
- return _noDefaultLibs.count(path.drop_back(4).lower()) > 0;
- return _noDefaultLibs.count(path.lower()) > 0;
- }
-
- void setNoDefaultLibAll(bool val) { _noDefaultLibAll = val; }
- bool getNoDefaultLibAll() const { return _noDefaultLibAll; }
-
- void setSectionSetMask(StringRef sectionName, uint32_t flags);
- void setSectionClearMask(StringRef sectionName, uint32_t flags);
- uint32_t getSectionAttributes(StringRef sectionName, uint32_t flags) const;
-
- void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
- ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
-
- void addDllExport(ExportDesc &desc);
- std::vector<ExportDesc> &getDllExports() { return _dllExports; }
- const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
-
- StringRef getDelayLoadHelperName() const {
- return is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2@8";
- }
-
- StringRef allocate(StringRef ref) const {
- _allocMutex.lock();
- char *x = _allocator.Allocate<char>(ref.size() + 1);
- _allocMutex.unlock();
- memcpy(x, ref.data(), ref.size());
- x[ref.size()] = '\0';
- return x;
- }
-
- ArrayRef<uint8_t> allocate(ArrayRef<uint8_t> array) const {
- size_t size = array.size();
- _allocMutex.lock();
- uint8_t *p = _allocator.Allocate<uint8_t>(size);
- _allocMutex.unlock();
- memcpy(p, array.data(), size);
- return ArrayRef<uint8_t>(p, p + array.size());
- }
-
- template <typename T> T &allocateCopy(const T &x) const {
- _allocMutex.lock();
- T *r = new (_allocator) T(x);
- _allocMutex.unlock();
- return *r;
- }
-
- void addLibraryFile(std::unique_ptr<FileNode> file);
-
- void setModuleDefinitionFile(const std::string val) {
- _moduleDefinitionFile = val;
- }
- std::string getModuleDefinitionFile() const {
- return _moduleDefinitionFile;
- }
-
- std::recursive_mutex &getMutex() { return _mutex; }
-
- void setParseDirectives(ParseDirectives parseDirectives) {
- _parseDirectives = parseDirectives;
- }
-
- ParseDirectives getParseDirectives() {
- return _parseDirectives;
- }
-
-protected:
- /// Method to create a internal file for the entry symbol
- std::unique_ptr<File> createEntrySymbolFile() const override;
-
- /// Method to create a internal file for an undefined symbol
- std::unique_ptr<File> createUndefinedSymbolFile() const override;
-
-private:
- enum : uint64_t {
- invalidBaseAddress = UINT64_MAX,
- pe32DefaultBaseAddress = 0x400000U,
- pe32PlusDefaultBaseAddress = 0x140000000U
- };
-
- std::recursive_mutex _mutex;
- mutable std::mutex _allocMutex;
-
- std::string _entry;
-
- // False if /noentry option is given.
- bool _hasEntry;
-
- // The start address for the program. The default value for the executable is
- // 0x400000, but can be altered using /base command line option.
- uint64_t _baseAddress;
-
- uint64_t _stackReserve;
- uint64_t _stackCommit;
- uint64_t _heapReserve;
- uint64_t _heapCommit;
- bool _noDefaultLibAll;
- uint32_t _sectionDefaultAlignment;
- WindowsSubsystem _subsystem;
- MachineTypes _machineType;
- Version _imageVersion;
- Version _minOSVersion;
- bool _nxCompat;
- bool _largeAddressAware;
- bool _allowBind;
- bool _allowIsolation;
- bool _swapRunFromCD;
- bool _swapRunFromNet;
- bool _baseRelocationEnabled;
- bool _terminalServerAware;
- bool _dynamicBaseEnabled;
- bool _createManifest;
- std::string _manifestOutputPath;
- bool _embedManifest;
- int _manifestId;
- bool _manifestUAC;
- std::string _manifestLevel;
- std::string _manifestUiAccess;
- std::string _manifestDependency;
- bool _isDll;
- bool _highEntropyVA;
-
- // True if /SAFESEH option is specified. Valid only for x86. If true, LLD will
- // produce an image with SEH table. If any modules were not compatible with
- // SEH, LLD will exit with an error.
- bool _requireSEH;
-
- // True if /SAFESEH:no option is specified. Valid only for x86. If true, LLD
- // will not produce an image with SEH table even if all input object files are
- // compatible with SEH.
- bool _noSEH;
-
- // /IMPLIB command line option.
- std::string _implib;
-
- // True if /DEBUG is given.
- bool _debug;
-
- // PDB file output path. NB: this is dummy -- LLD just creates the empty file.
- std::string _pdbFilePath;
-
- // /DELAYLOAD option.
- std::set<std::string> _delayLoadDLLs;
-
- // The set to store /nodefaultlib arguments.
- std::set<std::string> _noDefaultLibs;
-
- std::vector<StringRef> _inputSearchPaths;
- std::unique_ptr<Writer> _writer;
-
- // A map for weak aliases.
- std::map<std::string, std::set<std::string>> _alternateNames;
-
- // A map for section renaming. For example, if there is an entry in the map
- // whose value is .rdata -> .text, the section contens of .rdata will be
- // merged to .text in the resulting executable.
- std::map<std::string, std::string> _renamedSections;
-
- // Section attributes specified by /section option.
- std::map<std::string, uint32_t> _sectionSetMask;
- std::map<std::string, uint32_t> _sectionClearMask;
-
- // DLLExport'ed symbols.
- std::vector<ExportDesc> _dllExports;
-
- // List of files that will be removed on destruction.
- std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
-
- // DOS Stub. DOS stub is data located at the beginning of PE/COFF file.
- // Windows loader do not really care about DOS stub contents, but it's usually
- // a small DOS program that prints out a message "This program requires
- // Microsoft Windows." This feature was somewhat useful before Windows 95.
- ArrayRef<uint8_t> _dosStub;
-
- // Name of the temporary file for lib.exe subcommand. For debugging
- // only.
- std::string _moduleDefinitionFile;
-
- std::set<std::string> _definedSyms;
- std::set<Node *> _seen;
-
- ParseDirectives _parseDirectives;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/RelocationHelperFunctions.h b/include/lld/ReaderWriter/RelocationHelperFunctions.h
deleted file mode 100644
index 8738e91ebabc..000000000000
--- a/include/lld/ReaderWriter/RelocationHelperFunctions.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- lld/ReaderWriter/RelocationHelperFunctions.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_RELOCATION_HELPER_FUNCTIONS_H
-#define LLD_READER_WRITER_RELOCATION_HELPER_FUNCTIONS_H
-
-namespace lld {
-
-/// Gather val's bits as specified by the mask. Example:
-///
-/// Val: 0bABCDEFGHIJKLMN
-/// Mask: 0b10111100001011
-/// Output: 0b000000ACDEFKMN
-template <typename T> T gatherBits(T val, T mask) {
- T result = 0;
- size_t off = 0;
-
- for (size_t bit = 0; bit < sizeof(T) * 8; ++bit) {
- bool maskBit = (mask >> bit) & 1;
- if (maskBit) {
- bool valBit = (val >> bit) & 1;
- result |= static_cast<T>(valBit) << off;
- ++off;
- }
- }
- return result;
-}
-
-/// Scatter val's bits as specified by the mask. Example:
-///
-/// Val: 0bABCDEFG
-/// Mask: 0b10111100001011
-/// Output: 0b00ABCD0000E0FG
-template <typename T> T scatterBits(T val, T mask) {
- T result = 0;
- size_t off = 0;
-
- for (size_t bit = 0; bit < sizeof(T) * 8; ++bit) {
- bool maskBit = (mask >> bit) & 1;
- if (maskBit) {
- bool valBit = (val >> off) & 1;
- result |= static_cast<T>(valBit) << bit;
- ++off;
- }
- }
- return result;
-}
-
-} // namespace lld
-
-#endif // LLD_READER_WRITER_RELOCATION_HELPER_FUNCTIONS_H
diff --git a/include/lld/ReaderWriter/YamlContext.h b/include/lld/ReaderWriter/YamlContext.h
index a15a398ec636..b26161a15431 100644
--- a/include/lld/ReaderWriter/YamlContext.h
+++ b/include/lld/ReaderWriter/YamlContext.h
@@ -30,14 +30,10 @@ using lld::mach_o::normalized::NormalizedFile;
/// object. We need to support hetergenous yaml documents which each require
/// different context info. This struct supports all clients.
struct YamlContext {
- YamlContext()
- : _linkingContext(nullptr), _registry(nullptr), _file(nullptr),
- _normalizeMachOFile(nullptr) {}
-
- const LinkingContext *_linkingContext;
- const Registry *_registry;
- File *_file;
- NormalizedFile *_normalizeMachOFile;
+ const LinkingContext *_ctx = nullptr;
+ const Registry *_registry = nullptr;
+ File *_file = nullptr;
+ NormalizedFile *_normalizeMachOFile = nullptr;
StringRef _path;
};