aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
commit1c98619801a5705c688e683be3ef9d70169a0686 (patch)
tree8422105cd1a94c368315f2db16b9ac746cf7c000 /include
parentf4f3ce4613680903220815690ad79fc7ba0a2e26 (diff)
downloadsrc-1c98619801a5705c688e683be3ef9d70169a0686.tar.gz
src-1c98619801a5705c688e683be3ef9d70169a0686.zip
Vendor import of lld release_39 branch r276489:vendor/lld/lld-release_39-r276489
Notes
Notes: svn path=/vendor/lld/dist/; revision=303239 svn path=/vendor/lld/lld-release_39-r276489/; revision=303240; tag=vendor/lld/lld-release_39-r276489
Diffstat (limited to 'include')
-rw-r--r--include/lld/Core/Alias.h100
-rw-r--r--include/lld/Core/ArchiveLibraryFile.h15
-rw-r--r--include/lld/Core/Atom.h53
-rw-r--r--include/lld/Core/DefinedAtom.h50
-rw-r--r--include/lld/Core/Error.h42
-rw-r--r--include/lld/Core/File.h120
-rw-r--r--include/lld/Core/LLVM.h6
-rw-r--r--include/lld/Core/LinkingContext.h150
-rw-r--r--include/lld/Core/Node.h6
-rw-r--r--include/lld/Core/Parallel.h36
-rw-r--r--include/lld/Core/Pass.h4
-rw-r--r--include/lld/Core/PassManager.h7
-rw-r--r--include/lld/Core/Reader.h9
-rw-r--r--include/lld/Core/Reference.h18
-rw-r--r--include/lld/Core/Resolver.h41
-rw-r--r--include/lld/Core/STDExtras.h29
-rw-r--r--include/lld/Core/SharedLibraryAtom.h4
-rw-r--r--include/lld/Core/SharedLibraryFile.h21
-rw-r--r--include/lld/Core/Simple.h150
-rw-r--r--include/lld/Core/SymbolTable.h11
-rw-r--r--include/lld/Core/UndefinedAtom.h10
-rw-r--r--include/lld/Core/Writer.h11
-rw-r--r--include/lld/Core/range.h738
-rw-r--r--include/lld/Driver/Driver.h138
-rw-r--r--include/lld/ReaderWriter/AtomLayout.h39
-rw-r--r--include/lld/ReaderWriter/CoreLinkingContext.h47
-rw-r--r--include/lld/ReaderWriter/ELFLinkingContext.h422
-rw-r--r--include/lld/ReaderWriter/LinkerScript.h1471
-rw-r--r--include/lld/ReaderWriter/MachOLinkingContext.h133
29 files changed, 449 insertions, 3432 deletions
diff --git a/include/lld/Core/Alias.h b/include/lld/Core/Alias.h
deleted file mode 100644
index fa999292fbd3..000000000000
--- a/include/lld/Core/Alias.h
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- lld/Core/Alias.h - Alias atoms -------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Provide alias atoms.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ALIAS_H
-#define LLD_CORE_ALIAS_H
-
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/Optional.h"
-#include <string>
-
-namespace lld {
-
-// An AliasAtom is a zero-size atom representing an alias for other atom. It has
-// a LayoutAfter reference to the target atom, so that this atom and the target
-// atom will be laid out at the same location in the final result. Initially
-// the target atom is an undefined atom. Resolver will replace it with a defined
-// one.
-//
-// It does not have attributes itself. Most member function calls are forwarded
-// to the target atom.
-class AliasAtom : public SimpleDefinedAtom {
-public:
- AliasAtom(const File &file, StringRef name)
- : SimpleDefinedAtom(file), _name(name) {}
-
- StringRef name() const override { return _name; }
- uint64_t size() const override { return 0; }
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- Scope scope() const override {
- getTarget();
- return _target ? _target->scope() : scopeLinkageUnit;
- }
-
- Merge merge() const override {
- if (_merge.hasValue())
- return _merge.getValue();
- getTarget();
- return _target ? _target->merge() : mergeNo;
- }
-
- void setMerge(Merge val) { _merge = val; }
-
- ContentType contentType() const override {
- getTarget();
- return _target ? _target->contentType() : typeUnknown;
- }
-
- Interposable interposable() const override {
- getTarget();
- return _target ? _target->interposable() : interposeNo;
- }
-
- SectionChoice sectionChoice() const override {
- getTarget();
- return _target ? _target->sectionChoice() : sectionBasedOnContent;
- }
-
- StringRef customSectionName() const override {
- getTarget();
- return _target ? _target->customSectionName() : StringRef("");
- }
-
- DeadStripKind deadStrip() const override { return _deadStrip; }
- void setDeadStrip(DeadStripKind val) { _deadStrip = val; }
-
-private:
- void getTarget() const {
- if (_target)
- return;
- for (const Reference *r : *this) {
- if (r->kindNamespace() == lld::Reference::KindNamespace::all &&
- r->kindValue() == lld::Reference::kindLayoutAfter) {
- _target = dyn_cast<DefinedAtom>(r->target());
- return;
- }
- }
- }
-
- std::string _name;
- mutable const DefinedAtom *_target = nullptr;
- llvm::Optional<Merge> _merge = DefinedAtom::mergeNo;
- DeadStripKind _deadStrip = DefinedAtom::deadStripNormal;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Core/ArchiveLibraryFile.h b/include/lld/Core/ArchiveLibraryFile.h
index ff379d4f3ecf..2c736e7d6c61 100644
--- a/include/lld/Core/ArchiveLibraryFile.h
+++ b/include/lld/Core/ArchiveLibraryFile.h
@@ -11,7 +11,6 @@
#define LLD_CORE_ARCHIVE_LIBRARY_FILE_H
#include "lld/Core/File.h"
-#include "lld/Core/Parallel.h"
#include <set>
namespace lld {
@@ -33,23 +32,11 @@ public:
/// Check if any member of the archive contains an Atom with the
/// specified name and return the File object for that member, or nullptr.
- virtual File *find(StringRef name, bool dataSymbolOnly) = 0;
+ virtual File *find(StringRef name) = 0;
virtual std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) = 0;
- // Parses a member file containing a given symbol, so that when you
- // need the file find() can return that immediately. Calling this function
- // has no side effect other than pre-instantiating a file. Calling this
- // function doesn't affect correctness.
- virtual void preload(TaskGroup &group, StringRef symbolName) {}
-
- /// Returns a set of all defined symbols in the archive, i.e. all
- /// resolvable symbol using this file.
- virtual std::set<StringRef> getDefinedSymbols() {
- return std::set<StringRef>();
- }
-
protected:
/// only subclasses of ArchiveLibraryFile can be instantiated
ArchiveLibraryFile(StringRef path) : File(path, kindArchiveLibrary) {}
diff --git a/include/lld/Core/Atom.h b/include/lld/Core/Atom.h
index 27fdde022ba7..42ca2bb8af8c 100644
--- a/include/lld/Core/Atom.h
+++ b/include/lld/Core/Atom.h
@@ -16,6 +16,9 @@ namespace lld {
class File;
+template<typename T>
+class OwningAtomPtr;
+
///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms. Each Atom is a node
@@ -24,6 +27,7 @@ class File;
/// undefined symbol (extern declaration).
///
class Atom {
+ template<typename T> friend class OwningAtomPtr;
public:
/// Whether this atom is defined or a proxy for an undefined symbol
enum Definition {
@@ -71,6 +75,55 @@ private:
Definition _definition;
};
+/// Class which owns an atom pointer and runs the atom destructor when the
+/// owning pointer goes out of scope.
+template<typename T>
+class OwningAtomPtr {
+private:
+ OwningAtomPtr(const OwningAtomPtr &) = delete;
+ void operator=(const OwningAtomPtr&) = delete;
+public:
+ OwningAtomPtr() : atom(nullptr) { }
+ OwningAtomPtr(T *atom) : atom(atom) { }
+
+ ~OwningAtomPtr() {
+ if (atom)
+ runDestructor(atom);
+ }
+
+ void runDestructor(Atom *atom) {
+ atom->~Atom();
+ }
+
+ OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
+ ptr.atom = nullptr;
+ }
+
+ void operator=(OwningAtomPtr&& ptr) {
+ if (atom)
+ runDestructor(atom);
+ atom = ptr.atom;
+ ptr.atom = nullptr;
+ }
+
+ T *const &get() const {
+ return atom;
+ }
+
+ T *&get() {
+ return atom;
+ }
+
+ T *release() {
+ auto *v = atom;
+ atom = nullptr;
+ return v;
+ }
+
+private:
+ T *atom;
+};
+
} // namespace lld
#endif // LLD_CORE_ATOM_H
diff --git a/include/lld/Core/DefinedAtom.h b/include/lld/Core/DefinedAtom.h
index e4d4488ccdca..e3193f8aaf2e 100644
--- a/include/lld/Core/DefinedAtom.h
+++ b/include/lld/Core/DefinedAtom.h
@@ -11,11 +11,12 @@
#define LLD_CORE_DEFINED_ATOM_H
#include "lld/Core/Atom.h"
+#include "lld/Core/Reference.h"
#include "lld/Core/LLVM.h"
+#include "llvm/Support/ErrorHandling.h"
namespace lld {
class File;
-class Reference;
/// \brief The fundamental unit of linking.
///
@@ -105,6 +106,7 @@ public:
enum ContentType {
typeUnknown, // for use with definitionUndefined
+ typeMachHeader, // atom representing mach_header [Darwin]
typeCode, // executable code
typeResolver, // function which returns address of target
typeBranchIsland, // linker created for large binaries
@@ -127,6 +129,7 @@ public:
typeObjC1Class, // ObjC1 class [Darwin]
typeLazyPointer, // pointer through which a stub jumps
typeLazyDylibPointer, // pointer through which a stub jumps [Darwin]
+ typeNonLazyPointer, // pointer to external symbol
typeCFString, // NS/CFString object [Darwin]
typeGOT, // pointer to external symbol
typeInitializerPtr, // pointer to initializer function
@@ -134,6 +137,8 @@ public:
typeCStringPtr, // pointer to UTF8 C string [Darwin]
typeObjCClassPtr, // pointer to ObjC class [Darwin]
typeObjC2CategoryList, // pointers to ObjC category [Darwin]
+ typeObjCImageInfo, // pointer to ObjC class [Darwin]
+ typeObjCMethodList, // pointer to ObjC method list [Darwin]
typeDTraceDOF, // runtime data for Dtrace [Darwin]
typeInterposingTuples, // tuples of interposing info for dyld [Darwin]
typeTempLTO, // temporary atom for bitcode reader
@@ -143,14 +148,7 @@ public:
typeTLVInitialData, // initial data for a TLV [Darwin]
typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
typeTLVInitializerPtr, // pointer to thread local initializer [Darwin]
- typeMachHeader, // atom representing mach_header [Darwin]
- typeThreadZeroFill, // Uninitialized thread local data(TBSS) [ELF]
- typeThreadData, // Initialized thread local data(TDATA) [ELF]
- typeRONote, // Identifies readonly note sections [ELF]
- typeRWNote, // Identifies readwrite note sections [ELF]
- typeNoAlloc, // Identifies non allocatable sections [ELF]
- typeGroupComdat, // Identifies a section group [ELF, COFF]
- typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
+ typeDSOHandle, // atom representing DSO handle [Darwin]
typeSectCreate, // Created via the -sectcreate option [Darwin]
};
@@ -218,11 +216,6 @@ public:
///
/// This is used by the linker to order the layout of Atoms so that the
/// resulting image is stable and reproducible.
- ///
- /// Note that this should not be confused with ordinals of exported symbols in
- /// Windows DLLs. In Windows terminology, ordinals are symbols' export table
- /// indices (small integers) which can be used instead of symbol names to
- /// refer items in a DLL.
virtual uint64_t ordinal() const = 0;
/// \brief the number of bytes of space this atom's content will occupy in the
@@ -307,8 +300,12 @@ public:
return _atom.derefIterator(_it);
}
+ bool operator==(const reference_iterator &other) const {
+ return _it == other._it;
+ }
+
bool operator!=(const reference_iterator &other) const {
- return _it != other._it;
+ return !(*this == other);
}
reference_iterator &operator++() {
@@ -326,6 +323,14 @@ public:
/// \brief Returns an iterator to the end of this Atom's References.
virtual reference_iterator end() const = 0;
+ /// Adds a reference to this atom.
+ virtual void addReference(Reference::KindNamespace ns,
+ Reference::KindArch arch,
+ Reference::KindValue kindValue, uint64_t off,
+ const Atom *target, Reference::Addend a) {
+ llvm_unreachable("Subclass does not permit adding references");
+ }
+
static bool classof(const Atom *a) {
return a->definition() == definitionRegular;
}
@@ -338,16 +343,15 @@ public:
ContentType atomContentType = contentType();
return !(atomContentType == DefinedAtom::typeZeroFill ||
atomContentType == DefinedAtom::typeZeroFillFast ||
- atomContentType == DefinedAtom::typeTLVInitialZeroFill ||
- atomContentType == DefinedAtom::typeThreadZeroFill);
+ atomContentType == DefinedAtom::typeTLVInitialZeroFill);
}
- /// Utility function to check if the atom belongs to a group section
- /// that represents section groups or .gnu.linkonce sections.
- bool isGroupParent() const {
+ /// Utility function to check if relocations in this atom to other defined
+ /// atoms can be implicitly generated, and so we don't need to explicitly
+ /// emit those relocations.
+ bool relocsToDefinedCanBeImplicit() const {
ContentType atomContentType = contentType();
- return (atomContentType == DefinedAtom::typeGroupComdat ||
- atomContentType == DefinedAtom::typeGnuLinkOnce);
+ return atomContentType == typeCFI;
}
// Returns true if lhs should be placed before rhs in the final output.
@@ -359,6 +363,8 @@ protected:
// constructor.
DefinedAtom() : Atom(definitionRegular) { }
+ ~DefinedAtom() override = default;
+
/// \brief Returns a pointer to the Reference object that the abstract
/// iterator "points" to.
virtual const Reference *derefIterator(const void *iter) const = 0;
diff --git a/include/lld/Core/Error.h b/include/lld/Core/Error.h
index a7e61f91d8e9..b0bf73b1cb7b 100644
--- a/include/lld/Core/Error.h
+++ b/include/lld/Core/Error.h
@@ -15,6 +15,8 @@
#define LLD_CORE_ERROR_H
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include <system_error>
namespace lld {
@@ -30,39 +32,37 @@ inline std::error_code make_error_code(YamlReaderError e) {
return std::error_code(static_cast<int>(e), YamlReaderCategory());
}
-const std::error_category &LinkerScriptReaderCategory();
-
-enum class LinkerScriptReaderError {
- success = 0,
- parse_error,
- unknown_symbol_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) {
- return std::error_code(static_cast<int>(e), LinkerScriptReaderCategory());
-}
-
/// Creates an error_code object that has associated with it an arbitrary
/// error messsage. The value() of the error_code will always be non-zero
/// but its value is meaningless. The messsage() will be (a copy of) the
/// 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);
+
+/// Generic error.
+///
+/// For errors that don't require their own specific sub-error (most errors)
+/// this class can be used to describe the error via a string message.
+class GenericError : public llvm::ErrorInfo<GenericError> {
+public:
+ static char ID;
+ GenericError(Twine Msg);
+ const std::string &getMessage() const { return Msg; }
+ void log(llvm::raw_ostream &OS) const override;
+
+ std::error_code convertToErrorCode() const override {
+ return make_dynamic_error_code(getMessage());
+ }
+
+private:
+ std::string Msg;
+};
} // end namespace lld
namespace std {
template <> struct is_error_code_enum<lld::YamlReaderError> : std::true_type {};
-template <>
-struct is_error_code_enum<lld::LinkerScriptReaderError> : std::true_type {};
}
#endif
diff --git a/include/lld/Core/File.h b/include/lld/Core/File.h
index 494e50065340..20418688dfa0 100644
--- a/include/lld/Core/File.h
+++ b/include/lld/Core/File.h
@@ -14,8 +14,8 @@
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/range.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <functional>
@@ -45,9 +45,18 @@ public:
/// \brief Kinds of files that are supported.
enum Kind {
- kindObject, ///< object file (.o)
- kindSharedLibrary, ///< shared library (.so)
- kindArchiveLibrary ///< archive (.a)
+ kindErrorObject, ///< a error object file (.o)
+ kindNormalizedObject, ///< a normalized file (.o)
+ kindMachObject, ///< a MachO object file (.o)
+ kindCEntryObject, ///< a file for CEntries
+ kindHeaderObject, ///< a file for file headers
+ kindEntryObject, ///< a file for the entry
+ kindUndefinedSymsObject, ///< a file for undefined symbols
+ kindStubHelperObject, ///< a file for stub helpers
+ kindResolverMergedObject, ///< the resolver merged file.
+ kindSectCreateObject, ///< a sect create object file (.o)
+ kindSharedLibrary, ///< shared library (.so)
+ kindArchiveLibrary ///< archive (.a)
};
/// \brief Returns file kind. Need for dyn_cast<> on File objects.
@@ -97,17 +106,69 @@ public:
}
/// The type of atom mutable container.
- template <typename T> using AtomVector = std::vector<const T *>;
+ template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
- /// 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.
+ /// The range type for the atoms.
template <typename T> class AtomRange {
public:
- 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(); }
+ AtomRange(AtomVector<T> &v) : _v(v) {}
+ AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
+
+ typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
+ const T*> ConstDerefFn;
+
+ typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
+
+ typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
+ ConstDerefFn> ConstItTy;
+ typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
+ DerefFn> ItTy;
+
+ static const T* DerefConst(const OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ static T* Deref(OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ ConstItTy begin() const {
+ return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
+ }
+ ConstItTy end() const {
+ return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
+ }
+
+ ItTy begin() {
+ return ItTy(_v.begin(), DerefFn(Deref));
+ }
+ ItTy end() {
+ return ItTy(_v.end(), DerefFn(Deref));
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ bool empty() const {
+ return _v.empty();
+ }
+
+ size_t size() const {
+ return _v.size();
+ }
+
+ const OwningAtomPtr<T> &operator[](size_t idx) const {
+ return _v[idx];
+ }
+
+ OwningAtomPtr<T> &operator[](size_t idx) {
+ return _v[idx];
+ }
private:
AtomVector<T> &_v;
@@ -115,19 +176,25 @@ public:
/// \brief Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
- virtual const AtomVector<DefinedAtom> &defined() const = 0;
+ virtual const AtomRange<DefinedAtom> defined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
- virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
+ virtual const AtomRange<UndefinedAtom> undefined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
- virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
+ virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
- virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
+ virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
+
+ /// Drop all of the atoms owned by this file. This will result in all of
+ /// the atoms running their destructors.
+ /// This is required because atoms may be allocated on a BumpPtrAllocator
+ /// of a different file. We need to destruct all atoms before any files.
+ virtual void clearAtoms() = 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
@@ -137,14 +204,6 @@ public:
std::error_code parse();
- // This function is called just before the core linker tries to use
- // a file. Currently the PECOFF reader uses this to trigger the
- // driver to parse .drectve section (which contains command line options).
- // If you want to do something having side effects, don't do that in
- // doParse() because a file could be pre-loaded speculatively.
- // Use this hook instead.
- virtual void beforeLink() {}
-
// Usually each file owns a std::unique_ptr<MemoryBuffer>.
// However, there's one special case. If a file is an archive file,
// the archive file and its children all shares the same memory buffer.
@@ -190,23 +249,26 @@ private:
class ErrorFile : public File {
public:
ErrorFile(StringRef path, std::error_code ec)
- : File(path, kindObject), _ec(ec) {}
+ : File(path, kindErrorObject), _ec(ec) {}
std::error_code doParse() override { return _ec; }
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
llvm_unreachable("internal error");
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
llvm_unreachable("internal error");
}
+ void clearAtoms() override {
+ }
+
private:
std::error_code _ec;
};
diff --git a/include/lld/Core/LLVM.h b/include/lld/Core/LLVM.h
index d532c17fbfdf..ccf08859f4ae 100644
--- a/include/lld/Core/LLVM.h
+++ b/include/lld/Core/LLVM.h
@@ -23,6 +23,7 @@
namespace llvm {
// ADT's.
+ class Error;
class StringRef;
class Twine;
class MemoryBuffer;
@@ -38,6 +39,9 @@ namespace llvm {
template<typename T>
class ErrorOr;
+ template<typename T>
+ class Expected;
+
class raw_ostream;
// TODO: DenseMap, ...
}
@@ -51,6 +55,7 @@ namespace lld {
using llvm::cast_or_null;
// ADT's.
+ using llvm::Error;
using llvm::StringRef;
using llvm::Twine;
using llvm::MemoryBuffer;
@@ -61,6 +66,7 @@ namespace lld {
using llvm::SmallVectorImpl;
using llvm::SaveAndRestore;
using llvm::ErrorOr;
+ using llvm::Expected;
using llvm::raw_ostream;
} // end namespace lld.
diff --git a/include/lld/Core/LinkingContext.h b/include/lld/Core/LinkingContext.h
index a723854b3c91..7e4edaf22cf3 100644
--- a/include/lld/Core/LinkingContext.h
+++ b/include/lld/Core/LinkingContext.h
@@ -13,9 +13,7 @@
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Node.h"
-#include "lld/Core/Parallel.h"
#include "lld/Core/Reference.h"
-#include "lld/Core/range.h"
#include "lld/Core/Reader.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
@@ -33,16 +31,9 @@ class SharedLibraryFile;
///
/// The base class LinkingContext contains the options needed by core linking.
/// Subclasses of LinkingContext have additional options needed by specific
-/// Writers. For example, ELFLinkingContext has methods that supplies
-/// options to the ELF Writer and ELF Passes.
+/// Writers.
class LinkingContext {
public:
- /// \brief The types of output file that the linker creates.
- enum class OutputFileType : uint8_t {
- Default, // The default output type for this target
- YAML, // The output type is set to YAML
- };
-
virtual ~LinkingContext();
/// \name Methods needed by core linking
@@ -78,28 +69,6 @@ public:
_deadStripRoots.push_back(symbolName);
}
- /// Archive files (aka static libraries) are normally lazily loaded. That is,
- /// object files within an archive are only loaded and linked in, if the
- /// object file contains a DefinedAtom which will replace an existing
- /// UndefinedAtom. If this method returns true, core linking will also look
- /// for archive members to replace existing tentative definitions in addition
- /// to replacing undefines. Note: a "tentative definition" (also called a
- /// "common" symbols) is a C (but not C++) concept. They are modeled in lld
- /// as a DefinedAtom with merge() of mergeAsTentative.
- bool searchArchivesToOverrideTentativeDefinitions() const {
- return _searchArchivesToOverrideTentativeDefinitions;
- }
-
- /// Normally core linking will turn a tentative definition into a real
- /// definition if not replaced by a real DefinedAtom from some object file.
- /// If this method returns true, core linking will search all supplied
- /// dynamic shared libraries for symbol names that match remaining tentative
- /// definitions. If any are found, the corresponding tentative definition
- /// atom is replaced with SharedLibraryAtom.
- bool searchSharedLibrariesToOverrideTentativeDefinitions() const {
- return _searchSharedLibrariesToOverrideTentativeDefinitions;
- }
-
/// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
/// SharedLibraryAtom for the link to be successful. This method controls
/// whether core linking prints out a list of remaining UndefinedAtoms.
@@ -114,35 +83,6 @@ public:
/// whether core linking considers remaining undefines to be an error.
bool allowRemainingUndefines() const { return _allowRemainingUndefines; }
- /// In the lld model, a SharedLibraryAtom is a proxy atom for something
- /// that will be found in a dynamic shared library when the program runs.
- /// A SharedLibraryAtom optionally contains the name of the shared library
- /// in which to find the symbol name at runtime. Core linking may merge
- /// two SharedLibraryAtom with the same name. If this method returns true,
- /// when merging core linking will also verify that they both have the same
- /// loadName() and if not print a warning.
- ///
- /// \todo This should be a method core linking calls so that drivers can
- /// format the warning as needed.
- bool warnIfCoalesableAtomsHaveDifferentLoadName() const {
- return _warnIfCoalesableAtomsHaveDifferentLoadName;
- }
-
- /// In C/C++ you can mark a function's prototype with
- /// __attribute__((weak_import)) or __attribute__((weak)) to say the function
- /// may not be available at runtime and/or build time and in which case its
- /// address will evaluate to NULL. In lld this is modeled using the
- /// UndefinedAtom::canBeNull() method. During core linking, UndefinedAtom
- /// with the same name are automatically merged. If this method returns
- /// true, core link also verfies that the canBeNull() value for merged
- /// UndefinedAtoms are the same and warns if not.
- ///
- /// \todo This should be a method core linking calls so that drivers can
- /// format the warning as needed.
- bool warnIfCoalesableAtomsHaveDifferentCanBeNull() const {
- return _warnIfCoalesableAtomsHaveDifferentCanBeNull;
- }
-
/// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
/// SharedLibraryAtom for the link to be successful. This method controls
/// whether core linking considers remaining undefines from the shared library
@@ -176,20 +116,7 @@ public:
}
void setDeadStripping(bool enable) { _deadStrip = enable; }
- void setAllowDuplicates(bool enable) { _allowDuplicates = enable; }
void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; }
- void setSearchArchivesToOverrideTentativeDefinitions(bool search) {
- _searchArchivesToOverrideTentativeDefinitions = search;
- }
- void setSearchSharedLibrariesToOverrideTentativeDefinitions(bool search) {
- _searchSharedLibrariesToOverrideTentativeDefinitions = search;
- }
- void setWarnIfCoalesableAtomsHaveDifferentCanBeNull(bool warn) {
- _warnIfCoalesableAtomsHaveDifferentCanBeNull = warn;
- }
- void setWarnIfCoalesableAtomsHaveDifferentLoadName(bool warn) {
- _warnIfCoalesableAtomsHaveDifferentLoadName = warn;
- }
void setPrintRemainingUndefines(bool print) {
_printRemainingUndefines = print;
}
@@ -199,27 +126,11 @@ public:
void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; }
void setLogInputFiles(bool log) { _logInputFiles = log; }
- // Returns true if multiple definitions should not be treated as a
- // fatal error.
- bool getAllowDuplicates() const { return _allowDuplicates; }
-
void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); }
- void addAlias(StringRef from, StringRef to) { _aliasSymbols[from] = to; }
- const std::map<std::string, std::string> &getAliases() const {
- return _aliasSymbols;
- }
-
std::vector<std::unique_ptr<Node>> &getNodes() { return _nodes; }
const std::vector<std::unique_ptr<Node>> &getNodes() const { return _nodes; }
- /// Notify the LinkingContext when the symbol table found a name collision.
- /// The useNew parameter specifies which the symbol table plans to keep,
- /// but that can be changed by the LinkingContext. This is also an
- /// opportunity for flavor specific processing.
- virtual void notifySymbolTableCoalesce(const Atom *existingAtom,
- const Atom *newAtom, bool &useNew) {}
-
/// This method adds undefined symbols specified by the -u option to the to
/// the list of undefined symbols known to the linker. This option essentially
/// forces an undefined symbol to be created. You may also need to call
@@ -242,7 +153,7 @@ public:
/// Return the list of undefined symbols that are specified in the
/// linker command line, using the -u option.
- range<const StringRef *> initialUndefinedSymbols() const {
+ ArrayRef<StringRef> initialUndefinedSymbols() const {
return _initialUndefinedSymbols;
}
@@ -255,9 +166,7 @@ public:
bool validate(raw_ostream &diagnostics);
/// Formats symbol name for use in error messages.
- virtual std::string demangle(StringRef symbolName) const {
- return symbolName;
- }
+ virtual std::string demangle(StringRef symbolName) const = 0;
/// @}
/// \name Methods used by Driver::link()
@@ -269,19 +178,6 @@ public:
/// the linker to write to an in-memory buffer.
StringRef outputPath() const { return _outputPath; }
- /// Set the various output file types that the linker would
- /// create
- bool setOutputFileType(StringRef outputFileType) {
- if (outputFileType.equals_lower("yaml")) {
- _outputFileType = OutputFileType::YAML;
- return true;
- }
- return false;
- }
-
- /// Returns the output file type that that the linker needs to create.
- OutputFileType outputFileType() const { return _outputFileType; }
-
/// Accessor for Register object embedded in LinkingContext.
const Registry &registry() const { return _registry; }
Registry &registry() { return _registry; }
@@ -289,25 +185,30 @@ 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 void createImplicitFiles(std::vector<std::unique_ptr<File>> &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) = 0;
/// 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.
- virtual void addPasses(PassManager &pm);
+ virtual void addPasses(PassManager &pm) = 0;
/// Calls through to the writeFile() method on the specified Writer.
///
/// \param linkedFile This is the merged/linked graph of all input file Atoms.
- virtual std::error_code writeFile(const File &linkedFile) const;
+ virtual llvm::Error writeFile(const File &linkedFile) const;
/// Return the next ordinal and Increment it.
virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; }
// This function is called just before the Resolver kicks in.
// Derived classes may use it to change the list of input files.
- virtual void finalizeInputFiles() {}
+ virtual void finalizeInputFiles() = 0;
- TaskGroup &getTaskGroup() { return _taskGroup; }
+ /// Callback invoked for each file the Resolver decides we are going to load.
+ /// This can be used to update context state based on the file, and emit
+ /// errors for any differences between the context state and a loaded file.
+ /// For example, we can error if we try to load a file which is a different
+ /// arch from that being linked.
+ virtual llvm::Error handleLoadedFile(File &file) = 0;
/// @}
protected:
@@ -324,36 +225,25 @@ protected:
virtual std::unique_ptr<File> createUndefinedSymbolFile() const;
std::unique_ptr<File> createUndefinedSymbolFile(StringRef filename) const;
- /// Method to create an internal file for alias symbols
- std::unique_ptr<File> createAliasSymbolFile() const;
-
StringRef _outputPath;
StringRef _entrySymbolName;
- bool _deadStrip;
- bool _allowDuplicates;
- bool _globalsAreDeadStripRoots;
- bool _searchArchivesToOverrideTentativeDefinitions;
- bool _searchSharedLibrariesToOverrideTentativeDefinitions;
- bool _warnIfCoalesableAtomsHaveDifferentCanBeNull;
- bool _warnIfCoalesableAtomsHaveDifferentLoadName;
- bool _printRemainingUndefines;
- bool _allowRemainingUndefines;
- bool _logInputFiles;
- bool _allowShlibUndefines;
- OutputFileType _outputFileType;
+ bool _deadStrip = false;
+ bool _globalsAreDeadStripRoots = false;
+ bool _printRemainingUndefines = true;
+ bool _allowRemainingUndefines = false;
+ bool _logInputFiles = false;
+ bool _allowShlibUndefines = false;
std::vector<StringRef> _deadStripRoots;
- std::map<std::string, std::string> _aliasSymbols;
std::vector<const char *> _llvmOptions;
StringRefVector _initialUndefinedSymbols;
std::vector<std::unique_ptr<Node>> _nodes;
mutable llvm::BumpPtrAllocator _allocator;
- mutable uint64_t _nextOrdinal;
+ mutable uint64_t _nextOrdinal = 0;
Registry _registry;
private:
/// Validate the subclass bits. Only called by validate.
virtual bool validateImpl(raw_ostream &diagnostics) = 0;
- TaskGroup _taskGroup;
};
} // end namespace lld
diff --git a/include/lld/Core/Node.h b/include/lld/Core/Node.h
index cd38fbd4a482..8de0ecdbba6a 100644
--- a/include/lld/Core/Node.h
+++ b/include/lld/Core/Node.h
@@ -57,7 +57,7 @@ private:
class FileNode : public Node {
public:
explicit FileNode(std::unique_ptr<File> f)
- : Node(Node::Kind::File), _file(std::move(f)), _asNeeded(false) {}
+ : Node(Node::Kind::File), _file(std::move(f)) {}
static bool classof(const Node *a) {
return a->kind() == Node::Kind::File;
@@ -65,12 +65,8 @@ public:
File *getFile() { return _file.get(); }
- void setAsNeeded(bool val) { _asNeeded = val; }
- bool asNeeded() const { return _asNeeded; }
-
protected:
std::unique_ptr<File> _file;
- bool _asNeeded;
};
} // namespace lld
diff --git a/include/lld/Core/Parallel.h b/include/lld/Core/Parallel.h
index e2c38308b768..2dde97d9e3f0 100644
--- a/include/lld/Core/Parallel.h
+++ b/include/lld/Core/Parallel.h
@@ -12,7 +12,6 @@
#include "lld/Core/Instrumentation.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/range.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/thread.h"
@@ -63,41 +62,6 @@ public:
}
};
-/// \brief An implementation of future. std::future and std::promise in
-/// old libstdc++ have a threading bug; there is a small chance that a
-/// call of future::get throws an exception in the normal use case.
-/// We want to use our own future implementation until we drop support
-/// of old versions of libstdc++.
-/// https://gcc.gnu.org/ml/gcc-patches/2014-05/msg01389.html
-template<typename T> class Future {
-public:
- Future() : _hasValue(false) {}
-
- void set(T &&val) {
- assert(!_hasValue);
- {
- std::unique_lock<std::mutex> lock(_mutex);
- _val = val;
- _hasValue = true;
- }
- _cond.notify_all();
- }
-
- T &get() {
- std::unique_lock<std::mutex> lock(_mutex);
- if (_hasValue)
- return _val;
- _cond.wait(lock, [&] { return _hasValue; });
- return _val;
- }
-
-private:
- T _val;
- bool _hasValue;
- std::mutex _mutex;
- std::condition_variable _cond;
-};
-
// Classes in this namespace are implementation details of this header.
namespace internal {
diff --git a/include/lld/Core/Pass.h b/include/lld/Core/Pass.h
index 2e49cd1b8eee..0527f02cd362 100644
--- a/include/lld/Core/Pass.h
+++ b/include/lld/Core/Pass.h
@@ -13,7 +13,7 @@
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
-#include "lld/Core/range.h"
+#include "llvm/Support/Error.h"
#include <vector>
namespace lld {
@@ -34,7 +34,7 @@ public:
virtual ~Pass() { }
/// Do the actual work of the Pass.
- virtual std::error_code perform(SimpleFile &mergedFile) = 0;
+ virtual llvm::Error 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 62aa119f8f76..71a25cc7f3cd 100644
--- a/include/lld/Core/PassManager.h
+++ b/include/lld/Core/PassManager.h
@@ -12,6 +12,7 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
@@ -31,11 +32,11 @@ public:
_passes.push_back(std::move(pass));
}
- std::error_code runOnFile(SimpleFile &file) {
+ llvm::Error runOnFile(SimpleFile &file) {
for (std::unique_ptr<Pass> &pass : _passes)
- if (std::error_code EC = pass->perform(file))
+ if (llvm::Error EC = pass->perform(file))
return EC;
- return std::error_code();
+ return llvm::Error();
}
private:
diff --git a/include/lld/Core/Reader.h b/include/lld/Core/Reader.h
index 9324da475e3d..66df4380dc76 100644
--- a/include/lld/Core/Reader.h
+++ b/include/lld/Core/Reader.h
@@ -27,17 +27,14 @@ class IO;
}
namespace lld {
-class ELFLinkingContext;
class File;
class LinkingContext;
-class PECOFFLinkingContext;
class MachOLinkingContext;
/// \brief An abstract class for reading object files, library files, and
/// executable files.
///
-/// Each file format (e.g. ELF, mach-o, PECOFF, etc) have a concrete
-/// subclass of Reader.
+/// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader.
class Reader {
public:
virtual ~Reader() {}
@@ -114,11 +111,7 @@ public:
// as parameters to the addSupport*() method.
void addSupportArchives(bool logLoading);
void addSupportYamlFiles();
- void addSupportCOFFObjects(PECOFFLinkingContext &);
- void addSupportCOFFImportLibraries(PECOFFLinkingContext &);
void addSupportMachOObjects(MachOLinkingContext &);
- void addSupportELFObjects(ELFLinkingContext &);
- void addSupportELFDynamicSharedObjects(ELFLinkingContext &);
/// To convert between kind values and names, the registry walks the list
/// of registered kind tables. Each table is a zero terminated array of
diff --git a/include/lld/Core/Reference.h b/include/lld/Core/Reference.h
index 971721eb7d54..86de4f6a4236 100644
--- a/include/lld/Core/Reference.h
+++ b/include/lld/Core/Reference.h
@@ -25,15 +25,13 @@ class Atom;
/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
/// kind=callsite, target=malloc, addend=0.
///
-/// Besides supporting traditional "relocations", References are also used
-/// grouping atoms (group comdat), forcing layout (one atom must follow
-/// another), marking data-in-code (jump tables or ARM constants), etc.
+/// Besides supporting traditional "relocations", references are also used
+/// forcing layout (one atom must follow another), marking data-in-code
+/// (jump tables or ARM constants), etc.
///
/// The "kind" of a reference is a tuple of <namespace, arch, value>. This
/// enable us to re-use existing relocation types definded for various
-/// file formats and architectures. For instance, in ELF the relocation type 10
-/// means R_X86_64_32 for x86_64, and R_386_GOTPC for i386. For PE/COFF
-/// relocation 10 means IMAGE_REL_AMD64_SECTION.
+/// file formats and architectures.
///
/// References and atoms form a directed graph. The dead-stripping pass
/// traverses them starting from dead-strip root atoms to garbage collect
@@ -47,16 +45,14 @@ public:
enum class KindNamespace {
all = 0,
testing = 1,
- ELF = 2,
- COFF = 3,
- mach_o = 4,
+ mach_o = 2,
};
KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
// Which architecture the kind value is for.
- enum class KindArch { all, AArch64, AMDGPU, ARM, Hexagon, Mips, x86, x86_64 };
+ enum class KindArch { all, AArch64, ARM, x86, x86_64};
KindArch kindArch() const { return (KindArch)_kindArch; }
void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
@@ -76,8 +72,6 @@ public:
// kindLayoutAfter is treated as a bidirected edge by the dead-stripping
// pass.
kindLayoutAfter = 1,
- // kindGroupChild is treated as a bidirected edge too.
- kindGroupChild,
kindAssociate,
};
diff --git a/include/lld/Core/Resolver.h b/include/lld/Core/Resolver.h
index 05af7d9573ea..fb62a779c0a5 100644
--- a/include/lld/Core/Resolver.h
+++ b/include/lld/Core/Resolver.h
@@ -17,6 +17,7 @@
#include "lld/Core/SymbolTable.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/ErrorOr.h"
#include <set>
#include <unordered_map>
#include <unordered_set>
@@ -31,25 +32,23 @@ class LinkingContext;
/// and producing a merged graph.
class Resolver {
public:
- Resolver(LinkingContext &ctx)
- : _ctx(ctx), _symbolTable(ctx), _result(new MergedFile()),
- _fileIndex(0) {}
+ Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
// InputFiles::Handler methods
- void doDefinedAtom(const DefinedAtom&);
- bool doUndefinedAtom(const UndefinedAtom &);
- void doSharedLibraryAtom(const SharedLibraryAtom &);
- void doAbsoluteAtom(const AbsoluteAtom &);
+ void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
+ bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
+ void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
+ void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
// Handle files, this adds atoms from the current file thats
// being processed by the resolver
- bool handleFile(File &);
+ llvm::Expected<bool> handleFile(File &);
// Handle an archive library file.
- bool handleArchiveFile(File &);
+ llvm::Expected<bool> handleArchiveFile(File &);
// Handle a shared library file.
- void handleSharedLibrary(File &);
+ llvm::Error handleSharedLibrary(File &);
/// @brief do work of merging and resolving and return list
bool resolve();
@@ -57,37 +56,30 @@ public:
std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
private:
- typedef std::function<void(StringRef, bool)> UndefCallback;
+ typedef std::function<llvm::Expected<bool>(StringRef)> UndefCallback;
bool undefinesAdded(int begin, int end);
File *getFile(int &index);
- /// \brief Add section group/.gnu.linkonce if it does not exist previously.
- void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);
-
/// \brief The main function that iterates over the files to resolve
- void updatePreloadArchiveMap();
bool resolveUndefines();
void updateReferences();
void deadStripOptimize();
bool checkUndefines();
void removeCoalescedAwayAtoms();
- void checkDylibSymbolCollisions();
- void forEachUndefines(File &file, bool searchForOverrides, UndefCallback callback);
+ llvm::Expected<bool> forEachUndefines(File &file, UndefCallback callback);
void markLive(const Atom *atom);
- void addAtoms(const std::vector<const DefinedAtom *>&);
- void maybePreloadArchiveMember(StringRef sym);
class MergedFile : public SimpleFile {
public:
- MergedFile() : SimpleFile("<linker-internal>") {}
- void addAtoms(std::vector<const Atom*>& atoms);
+ MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
+ void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
};
LinkingContext &_ctx;
SymbolTable _symbolTable;
- std::vector<const Atom *> _atoms;
+ std::vector<OwningAtomPtr<Atom>> _atoms;
std::set<const Atom *> _deadStripRoots;
llvm::DenseSet<const Atom *> _liveAtoms;
llvm::DenseSet<const Atom *> _deadAtoms;
@@ -97,11 +89,6 @@ private:
// --start-group and --end-group
std::vector<File *> _files;
std::map<File *, bool> _newUndefinesAdded;
- size_t _fileIndex;
-
- // Preloading
- llvm::StringMap<ArchiveLibraryFile *> _archiveMap;
- llvm::DenseSet<ArchiveLibraryFile *> _archiveSeen;
// List of undefined symbols.
std::vector<StringRef> _undefines;
diff --git a/include/lld/Core/STDExtras.h b/include/lld/Core/STDExtras.h
deleted file mode 100644
index 4a6183891844..000000000000
--- a/include/lld/Core/STDExtras.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- lld/Core/STDExtra.h - Helpers for the stdlib -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_STD_EXTRA_H
-#define LLD_CORE_STD_EXTRA_H
-
-namespace lld {
-/// \brief Deleter for smart pointers that only calls the destructor. Memory is
-/// managed elsewhere. A common use of this is for things allocated with a
-/// BumpPtrAllocator.
-template <class T>
-struct destruct_delete {
- void operator ()(T *ptr) {
- ptr->~T();
- }
-};
-
-template <class T>
-using unique_bump_ptr = std::unique_ptr<T, destruct_delete<T>>;
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Core/SharedLibraryAtom.h b/include/lld/Core/SharedLibraryAtom.h
index 1b0c37c41138..7fec7a3e3d29 100644
--- a/include/lld/Core/SharedLibraryAtom.h
+++ b/include/lld/Core/SharedLibraryAtom.h
@@ -25,9 +25,7 @@ public:
};
/// Returns shared library name used to load it at runtime.
- /// On linux that is the DT_NEEDED name.
/// On Darwin it is the LC_DYLIB_LOAD dylib name.
- /// On Windows it is the DLL name that to be referred from .idata section.
virtual StringRef loadName() const = 0;
/// Returns if shared library symbol can be missing at runtime and if
@@ -46,6 +44,8 @@ public:
protected:
SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
+
+ ~SharedLibraryAtom() override = default;
};
} // namespace lld
diff --git a/include/lld/Core/SharedLibraryFile.h b/include/lld/Core/SharedLibraryFile.h
index a2907287862d..53bf967b0236 100644
--- a/include/lld/Core/SharedLibraryFile.h
+++ b/include/lld/Core/SharedLibraryFile.h
@@ -27,29 +27,34 @@ public:
/// Check if the shared library exports a symbol with the specified name.
/// If so, return a SharedLibraryAtom which represents that exported
/// symbol. Otherwise return nullptr.
- virtual const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const = 0;
+ virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const = 0;
- // Returns DSO name. It's the soname (ELF), the install name (MachO) or
- // the import name (Windows).
+ // Returns the install name.
virtual StringRef getDSOName() const = 0;
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _definedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _undefinedAtoms.clear();
+ _sharedLibraryAtoms.clear();
+ _absoluteAtoms.clear();
+ }
+
protected:
/// only subclasses of SharedLibraryFile can be instantiated
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
diff --git a/include/lld/Core/Simple.h b/include/lld/Core/Simple.h
index 3c204f8ba284..f75b40327db4 100644
--- a/include/lld/Core/Simple.h
+++ b/include/lld/Core/Simple.h
@@ -15,36 +15,60 @@
#ifndef LLD_CORE_SIMPLE_H
#define LLD_CORE_SIMPLE_H
+#include "lld/Core/AbsoluteAtom.h"
+#include "lld/Core/Atom.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-#include <atomic>
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <functional>
namespace lld {
class SimpleFile : public File {
public:
- SimpleFile(StringRef path) : File(path, kindObject) {}
+ SimpleFile(StringRef path, File::Kind kind)
+ : File(path, kind) {}
+
+ ~SimpleFile() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
- 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(DefinedAtom &a) {
+ _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
+ }
+ void addAtom(UndefinedAtom &a) {
+ _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
+ }
+ void addAtom(SharedLibraryAtom &a) {
+ _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
+ }
+ void addAtom(AbsoluteAtom &a) {
+ _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
+ }
void addAtom(const Atom &atom) {
if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
- _defined.push_back(p);
+ addAtom(const_cast<DefinedAtom &>(*p));
} else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
- _undefined.push_back(p);
+ addAtom(const_cast<UndefinedAtom &>(*p));
} else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
- _shared.push_back(p);
+ addAtom(const_cast<SharedLibraryAtom &>(*p));
} else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
- _absolute.push_back(p);
+ addAtom(const_cast<AbsoluteAtom &>(*p));
} else {
llvm_unreachable("atom has unknown definition kind");
}
@@ -52,26 +76,33 @@ public:
void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
auto &atoms = _defined;
- auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
+ auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
+ [&pred](OwningAtomPtr<DefinedAtom> &p) {
+ return pred(p.get());
+ });
atoms.erase(newEnd, atoms.end());
}
- const AtomVector<DefinedAtom> &defined() const override { return _defined; }
+ const AtomRange<DefinedAtom> defined() const override { return _defined; }
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefined;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _shared;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absolute;
}
- typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
- DefinedAtomRange definedAtoms() { return make_range(_defined); }
+ void clearAtoms() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
private:
AtomVector<DefinedAtom> _defined;
@@ -80,48 +111,6 @@ private:
AtomVector<AbsoluteAtom> _absolute;
};
-/// \brief Archive library file that may be used as a virtual container
-/// for symbols that should be added dynamically in response to
-/// call to find() method.
-class SimpleArchiveLibraryFile : public ArchiveLibraryFile {
-public:
- SimpleArchiveLibraryFile(StringRef filename)
- : ArchiveLibraryFile(filename) {}
-
- const AtomVector<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
-
- const AtomVector<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
-
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const AtomVector<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- // For descendants:
- // do some checks here and return dynamically generated files with atoms.
- return nullptr;
- }
-
- std::error_code
- parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
- return std::error_code();
- }
-
-private:
- AtomVector<DefinedAtom> _definedAtoms;
- AtomVector<UndefinedAtom> _undefinedAtoms;
- AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
- AtomVector<AbsoluteAtom> _absoluteAtoms;
-};
-
class SimpleReference : public Reference {
public:
SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
@@ -159,12 +148,13 @@ private:
SimpleReference *_prev;
};
-}
+} // end namespace lld
// ilist will lazily create a sentinal (so end() can return a node past the
// end of the list). We need this trait so that the sentinal is allocated
// via the BumpPtrAllocator.
namespace llvm {
+
template<>
struct ilist_sentinel_traits<lld::SimpleReference> {
@@ -200,7 +190,8 @@ struct ilist_sentinel_traits<lld::SimpleReference> {
private:
mutable llvm::BumpPtrAllocator *_allocator;
};
-}
+
+} // end namespace llvm
namespace lld {
@@ -211,6 +202,10 @@ public:
_references.setAllocator(&f.allocator());
}
+ ~SimpleDefinedAtom() override {
+ _references.clearAndLeakNodesUnsafely();
+ }
+
const File &file() const override { return _file; }
StringRef name() const override { return StringRef(); }
@@ -256,9 +251,10 @@ public:
it = reinterpret_cast<const void*>(next);
}
- void addReference(Reference::KindNamespace ns, Reference::KindArch arch,
+ void addReference(Reference::KindNamespace ns,
+ Reference::KindArch arch,
Reference::KindValue kindValue, uint64_t off,
- const Atom *target, Reference::Addend a) {
+ const Atom *target, Reference::Addend a) override {
assert(target && "trying to create reference to nothing");
auto node = new (_file.allocator())
SimpleReference(ns, arch, kindValue, off, target, a);
@@ -290,6 +286,7 @@ public:
_references.push_back(node);
}
}
+
void setOrdinal(uint64_t ord) { _ordinal = ord; }
private:
@@ -306,6 +303,8 @@ public:
assert(!name.empty() && "UndefinedAtoms must have a name");
}
+ ~SimpleUndefinedAtom() override = default;
+
/// file - returns the File that produced/owns this Atom
const File &file() const override { return _file; }
@@ -320,23 +319,6 @@ private:
StringRef _name;
};
-class SimpleAbsoluteAtom : public AbsoluteAtom {
-public:
- SimpleAbsoluteAtom(const File &f, StringRef name, Scope s, uint64_t value)
- : _file(f), _name(name), _scope(s), _value(value) {}
-
- const File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- uint64_t value() const override { return _value; }
- Scope scope() const override { return _scope; }
-
-private:
- const File &_file;
- StringRef _name;
- Scope _scope;
- uint64_t _value;
-};
-
} // end namespace lld
-#endif
+#endif // LLD_CORE_SIMPLE_H
diff --git a/include/lld/Core/SymbolTable.h b/include/lld/Core/SymbolTable.h
index 2e4459236d18..db610ad14066 100644
--- a/include/lld/Core/SymbolTable.h
+++ b/include/lld/Core/SymbolTable.h
@@ -34,8 +34,6 @@ class UndefinedAtom;
/// if an atom has been coalesced away.
class SymbolTable {
public:
- explicit SymbolTable(LinkingContext &);
-
/// @brief add atom to symbol table
bool add(const DefinedAtom &);
@@ -70,13 +68,6 @@ public:
/// @brief if atom has been coalesced away, return true
bool isCoalescedAway(const Atom *);
- /// @brief Find a group atom.
- const Atom *findGroup(StringRef name);
-
- /// @brief Add a group atom and returns true/false depending on whether the
- /// previously existed.
- bool addGroup(const DefinedAtom &da);
-
private:
typedef llvm::DenseMap<const Atom *, const Atom *> AtomToAtom;
@@ -105,10 +96,8 @@ private:
bool addByName(const Atom &);
bool addByContent(const DefinedAtom &);
- LinkingContext &_ctx;
AtomToAtom _replacedAtoms;
NameToAtom _nameTable;
- NameToAtom _groupTable;
AtomContentSet _contentTable;
};
diff --git a/include/lld/Core/UndefinedAtom.h b/include/lld/Core/UndefinedAtom.h
index 7a835a4ebaa8..f45d6ecda6b0 100644
--- a/include/lld/Core/UndefinedAtom.h
+++ b/include/lld/Core/UndefinedAtom.h
@@ -57,16 +57,10 @@ public:
static bool classof(const UndefinedAtom *) { return true; }
- /// Returns an undefined atom if this undefined symbol has a synonym. This is
- /// mainly used in COFF. In COFF, an unresolved external symbol can have up to
- /// one optional name (sym2) in addition to its regular name (sym1). If a
- /// definition of sym1 exists, sym1 is resolved normally. Otherwise, all
- /// references to sym1 refer to sym2 instead. In that case sym2 must be
- /// resolved, or link will fail.
- virtual const UndefinedAtom *fallback() const { return nullptr; }
-
protected:
UndefinedAtom() : Atom(definitionUndefined) {}
+
+ ~UndefinedAtom() override = default;
};
} // namespace lld
diff --git a/include/lld/Core/Writer.h b/include/lld/Core/Writer.h
index 8214ed6203f2..216f934916bc 100644
--- a/include/lld/Core/Writer.h
+++ b/include/lld/Core/Writer.h
@@ -11,25 +11,24 @@
#define LLD_CORE_WRITER_H
#include "lld/Core/LLVM.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <vector>
namespace lld {
-class ELFLinkingContext;
class File;
class LinkingContext;
class MachOLinkingContext;
-class PECOFFLinkingContext;
/// \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, etc) have a concrete subclass of Writer.
+/// library files, and executable files. Each file format (e.g. mach-o, etc)
+/// has a concrete subclass of Writer.
class Writer {
public:
virtual ~Writer();
/// \brief Write a file from the supplied File object
- virtual std::error_code writeFile(const File &linkedFile, StringRef path) = 0;
+ virtual llvm::Error writeFile(const File &linkedFile, StringRef path) = 0;
/// \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
@@ -41,9 +40,7 @@ protected:
Writer();
};
-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> createWriterYAML(const LinkingContext &);
} // end namespace lld
diff --git a/include/lld/Core/range.h b/include/lld/Core/range.h
deleted file mode 100644
index 614c9672955c..000000000000
--- a/include/lld/Core/range.h
+++ /dev/null
@@ -1,738 +0,0 @@
-//===-- lld/Core/range.h - Iterator ranges ----------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Iterator range type based on c++1y range proposal.
-///
-/// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_RANGE_H
-#define LLD_CORE_RANGE_H
-
-#include "llvm/Support/Compiler.h"
-#include <array>
-#include <cassert>
-#include <iterator>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-namespace lld {
-// Nothing in this namespace is part of the exported interface.
-namespace detail {
-using std::begin;
-using std::end;
-/// Used as the result type of undefined functions.
-struct undefined {};
-
-template <typename R> class begin_result {
- template <typename T> static auto check(T &&t) -> decltype(begin(t));
- static undefined check(...);
-public:
- typedef decltype(check(std::declval<R>())) type;
-};
-
-template <typename R> class end_result {
- template <typename T> static auto check(T &&t) -> decltype(end(t));
- static undefined check(...);
-public:
- typedef decltype(check(std::declval<R>())) type;
-};
-
-// Things that begin and end work on, in compatible ways, are
-// ranges. [stmt.ranged]
-template <typename R>
-struct is_range : std::is_same<typename detail::begin_result<R>::type,
- typename detail::end_result<R>::type> {};
-
-// This currently requires specialization and doesn't work for
-// detecting \c range<>s or iterators. We should add
-// \c contiguous_iterator_tag to fix that.
-template <typename R> struct is_contiguous_range : std::false_type {};
-template <typename R>
-struct is_contiguous_range<R &> : is_contiguous_range<R> {};
-template <typename R>
-struct is_contiguous_range <R &&> : is_contiguous_range<R> {};
-template <typename R>
-struct is_contiguous_range<const R> : is_contiguous_range<R> {};
-
-template <typename T, size_t N>
-struct is_contiguous_range<T[N]> : std::true_type {};
-template <typename T, size_t N>
-struct is_contiguous_range<const T[N]> : std::true_type {};
-template <typename T, size_t N>
-struct is_contiguous_range<std::array<T, N> > : std::true_type {};
-template <typename charT, typename traits, typename Allocator>
-struct is_contiguous_range<
- std::basic_string<charT, traits, Allocator> > : std::true_type {};
-template <typename T, typename Allocator>
-struct is_contiguous_range<std::vector<T, Allocator> > : std::true_type {};
-
-// Removes cv qualifiers from all levels of a multi-level pointer
-// type, not just the type level.
-template <typename T> struct remove_all_cv_ptr {
- typedef T type;
-};
-template <typename T> struct remove_all_cv_ptr<T *> {
- typedef typename remove_all_cv_ptr<T>::type *type;
-};
-template <typename T> struct remove_all_cv_ptr<const T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-template <typename T> struct remove_all_cv_ptr<volatile T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-template <typename T> struct remove_all_cv_ptr<const volatile T> {
- typedef typename remove_all_cv_ptr<T>::type type;
-};
-
-template <typename From, typename To>
-struct conversion_preserves_array_indexing : std::false_type {};
-
-template <typename FromVal, typename ToVal>
-struct conversion_preserves_array_indexing<FromVal *,
- ToVal *> : std::integral_constant<
- bool, std::is_convertible<FromVal *, ToVal *>::value &&
- std::is_same<typename remove_all_cv_ptr<FromVal>::type,
- typename remove_all_cv_ptr<ToVal>::type>::value> {};
-
-template <typename T>
-LLVM_CONSTEXPR auto adl_begin(T &&t) -> decltype(begin(t)) {
- return begin(std::forward<T>(t));
-}
-
-template <typename T> LLVM_CONSTEXPR auto adl_end(T &&t) -> decltype(end(t)) {
- return end(std::forward<T>(t));
-}
-} // end namespace detail
-
-/// A \c std::range<Iterator> represents a half-open iterator range
-/// built from two iterators, \c 'begin', and \c 'end'. If \c end is
-/// not reachable from \c begin, the behavior is undefined.
-///
-/// The mutability of elements of the range is controlled by the
-/// Iterator argument. Instantiate
-/// <code>range<<var>Foo</var>::iterator></code> or
-/// <code>range<<var>T</var>*></code>, or call
-/// <code>make_range(<var>non_const_container</var>)</code>, and you
-/// get a mutable range. Instantiate
-/// <code>range<<var>Foo</var>::const_iterator></code> or
-/// <code>range<const <var>T</var>*></code>, or call
-/// <code>make_range(<var>const_container</var>)</code>, and you get a
-/// constant range.
-///
-/// \todo Inherit from std::pair<Iterator, Iterator>?
-///
-/// \todo This interface contains some functions that could be
-/// provided as free algorithms rather than member functions, and all
-/// of the <code>pop_*()</code> functions could be replaced by \c
-/// slice() at the cost of some extra iterator copies. This makes
-/// them more awkward to use, but makes it easier for users to write
-/// their own types that follow the same interface. On the other hand,
-/// a \c range_facade could be provided to help users write new
-/// ranges, and it could provide the members. Such functions are
-/// marked with a note in their documentation. (Of course, all of
-/// these member functions could be provided as free functions using
-/// the iterator access methods, but one goal here is to allow people
-/// to program without touching iterators at all.)
-template <typename Iterator> class range {
- Iterator begin_, end_;
-public:
- /// \name types
- /// @{
-
- /// The iterator category of \c Iterator.
- /// \todo Consider defining range categories. If they don't add
- /// anything over the corresponding iterator categories, then
- /// they're probably not worth defining.
- typedef typename std::iterator_traits<
- Iterator>::iterator_category iterator_category;
- /// The type of elements of the range. Not cv-qualified.
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
- /// The type of the size of the range and offsets within the range.
- typedef typename std::iterator_traits<
- Iterator>::difference_type difference_type;
- /// The return type of element access methods: \c front(), \c back(), etc.
- typedef typename std::iterator_traits<Iterator>::reference reference;
- typedef typename std::iterator_traits<Iterator>::pointer pointer;
- /// @}
-
- /// \name constructors
- /// @{
-
- /// Creates a range of default-constructed (<em>not</em>
- /// value-initialized) iterators. For most \c Iterator types, this
- /// will be an invalid range.
- range() : begin_(), end_() {}
-
- /// \pre \c end is reachable from \c begin.
- /// \post <code>this->begin() == begin && this->end() == end</code>
- LLVM_CONSTEXPR range(Iterator begin, Iterator end)
- : begin_(begin), end_(end) {}
-
- /// \par Participates in overload resolution if:
- /// - \c Iterator is not a pointer type,
- /// - \c begin(r) and \c end(r) return the same type, and
- /// - that type is convertible to \c Iterator.
- ///
- /// \todo std::begin and std::end are overloaded between T& and
- /// const T&, which means that if a container has only a non-const
- /// begin or end method, then it's ill-formed to pass an rvalue to
- /// the free function. To avoid that problem, we don't use
- /// std::forward<> here, so begin() and end() are always called with
- /// an lvalue. Another option would be to insist that rvalue
- /// arguments to range() must have const begin() and end() methods.
- template <typename R> LLVM_CONSTEXPR range(
- R &&r,
- typename std::enable_if<
- !std::is_pointer<Iterator>::value &&
- detail::is_range<R>::value &&
- std::is_convertible<typename detail::begin_result<R>::type,
- Iterator>::value>::type* = 0)
- : begin_(detail::adl_begin(r)), end_(detail::adl_end(r)) {}
-
- /// This constructor creates a \c range<T*> from any range with
- /// contiguous iterators. Because dereferencing a past-the-end
- /// iterator can be undefined behavior, empty ranges get initialized
- /// with \c nullptr rather than \c &*begin().
- ///
- /// \par Participates in overload resolution if:
- /// - \c Iterator is a pointer type \c T*,
- /// - \c begin(r) and \c end(r) return the same type,
- /// - elements \c i of that type satisfy the invariant
- /// <code>&*(i + N) == (&*i) + N</code>, and
- /// - The result of <code>&*begin()</code> is convertible to \c T*
- /// using only qualification conversions [conv.qual] (since
- /// pointer conversions stop the pointer from pointing to an
- /// array element).
- ///
- /// \todo The <code>&*(i + N) == (&*i) + N</code> invariant is
- /// currently impossible to check for user-defined types. We need a
- /// \c contiguous_iterator_tag to let users assert it.
- template <typename R> LLVM_CONSTEXPR range(
- R &&r,
- typename std::enable_if<
- std::is_pointer<Iterator>::value &&
- detail::is_contiguous_range<R>::value
- // MSVC returns false for this in this context, but not if we lift it out of the
- // constructor.
-#ifndef _MSC_VER
- && detail::conversion_preserves_array_indexing<
- decltype(&*detail::adl_begin(r)), Iterator>::value
-#endif
- >::type* = 0)
- : begin_((detail::adl_begin(r) == detail::adl_end(r) &&
- !std::is_pointer<decltype(detail::adl_begin(r))>::value)
- // For non-pointers, &*begin(r) is only defined behavior
- // if there's an element there. Otherwise, use nullptr
- // since the user can't dereference it anyway. This _is_
- // detectable.
- ? nullptr : &*detail::adl_begin(r)),
- end_(begin_ + (detail::adl_end(r) - detail::adl_begin(r))) {}
-
- /// @}
-
- /// \name iterator access
- /// @{
- LLVM_CONSTEXPR Iterator begin() const { return begin_; }
- LLVM_CONSTEXPR Iterator end() const { return end_; }
- /// @}
-
- /// \name element access
- /// @{
-
- /// \par Complexity:
- /// O(1)
- /// \pre \c !empty()
- /// \returns a reference to the element at the front of the range.
- LLVM_CONSTEXPR reference front() const { return *begin(); }
-
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(2) (Involves copying and decrementing an iterator, so not
- /// quite as cheap as \c front())
- ///
- /// \pre \c !empty()
- /// \returns a reference to the element at the front of the range.
- LLVM_CONSTEXPR reference back() const {
- static_assert(
- std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only retrieve the last element of a bidirectional range.");
- using std::prev;
- return *prev(end());
- }
-
- /// This method is drawn from scripting language indexing. It
- /// indexes std::forward from the beginning of the range if the argument
- /// is positive, or backwards from the end of the array if the
- /// argument is negative.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1)
- ///
- /// \pre <code>abs(index) < size() || index == -size()</code>
- ///
- /// \returns if <code>index >= 0</code>, a reference to the
- /// <code>index</code>'th element in the range. Otherwise, a
- /// reference to the <code>size()+index</code>'th element.
- LLVM_CONSTEXPR reference operator[](difference_type index) const {
- static_assert(std::is_convertible<iterator_category,
- std::random_access_iterator_tag>::value,
- "Can only index into a random-access range.");
- // Less readable construction for constexpr support.
- return index < 0 ? end()[index]
- : begin()[index];
- }
- /// @}
-
- /// \name size
- /// @{
-
- /// \par Complexity:
- /// O(1)
- /// \returns \c true if the range contains no elements.
- LLVM_CONSTEXPR bool empty() const { return begin() == end(); }
-
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag. O(<code>size()</code>)
- /// otherwise.
- ///
- /// \returns the number of times \c pop_front() can be called before
- /// \c empty() becomes true.
- LLVM_CONSTEXPR difference_type size() const {
- static_assert(std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling size on an input range would destroy the range.");
- return dispatch_size(iterator_category());
- }
- /// @}
-
- /// \name traversal from the beginning of the range
- /// @{
-
- /// Advances the beginning of the range by one element.
- /// \pre \c !empty()
- void pop_front() { ++begin_; }
-
- /// Advances the beginning of the range by \c n elements.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>n</code>) otherwise.
- ///
- /// \pre <code>n >= 0</code>, and there must be at least \c n
- /// elements in the range.
- void pop_front(difference_type n) { advance(begin_, n); }
-
- /// Advances the beginning of the range by at most \c n elements,
- /// stopping if the range becomes empty. A negative argument causes
- /// no change.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>min(n,
- /// <var>#-elements-in-range</var>)</code>) otherwise.
- ///
- /// \note Could be provided as a free function with little-to-no
- /// loss in efficiency.
- void pop_front_upto(difference_type n) {
- advance_upto(begin_, std::max<difference_type>(0, n), end_,
- iterator_category());
- }
-
- /// @}
-
- /// \name traversal from the end of the range
- /// @{
-
- /// Moves the end of the range earlier by one element.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1)
- ///
- /// \pre \c !empty()
- void pop_back() {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- --end_;
- }
-
- /// Moves the end of the range earlier by \c n elements.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>n</code>) otherwise.
- ///
- /// \pre <code>n >= 0</code>, and there must be at least \c n
- /// elements in the range.
- void pop_back(difference_type n) {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- advance(end_, -n);
- }
-
- /// Moves the end of the range earlier by <code>min(n,
- /// size())</code> elements. A negative argument causes no change.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::bidirectional_iterator_tag.
- ///
- /// \par Complexity:
- /// O(1) if \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag, O(<code>min(n,
- /// <var>#-elements-in-range</var>)</code>) otherwise.
- ///
- /// \note Could be provided as a free function with little-to-no
- /// loss in efficiency.
- void pop_back_upto(difference_type n) {
- static_assert(std::is_convertible<iterator_category,
- std::bidirectional_iterator_tag>::value,
- "Can only access the end of a bidirectional range.");
- advance_upto(end_, -std::max<difference_type>(0, n), begin_,
- iterator_category());
- }
-
- /// @}
-
- /// \name creating derived ranges
- /// @{
-
- /// Divides the range into two pieces at \c index, where a positive
- /// \c index represents an offset from the beginning of the range
- /// and a negative \c index represents an offset from the end.
- /// <code>range[index]</code> is the first element in the second
- /// piece. If <code>index >= size()</code>, the second piece
- /// will be empty. If <code>index < -size()</code>, the first
- /// piece will be empty.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// - If \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag: O(1)
- /// - Otherwise, if \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag, \c abs(index) iterator increments
- /// or decrements
- /// - Otherwise, if <code>index >= 0</code>, \c index iterator
- /// increments
- /// - Otherwise, <code>size() + (size() + index)</code>
- /// iterator increments.
- ///
- /// \returns a pair of adjacent ranges.
- ///
- /// \post
- /// - <code>result.first.size() == min(index, this->size())</code>
- /// - <code>result.first.end() == result.second.begin()</code>
- /// - <code>result.first.size() + result.second.size()</code> <code>==
- /// this->size()</code>
- ///
- /// \todo split() could take an arbitrary number of indices and
- /// return an <code>N+1</code>-element \c tuple<>. This is tricky to
- /// implement with negative indices in the optimal number of
- /// increments or decrements for a bidirectional iterator, but it
- /// should be possible. Do we want it?
- std::pair<range, range> split(difference_type index) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling split on a non-std::forward range would return a useless "
- "first result.");
- if (index >= 0) {
- range second = *this;
- second.pop_front_upto(index);
- return make_pair(range(begin(), second.begin()), second);
- } else {
- return dispatch_split_neg(index, iterator_category());
- }
- }
-
- /// \returns A sub-range from \c start to \c stop (not including \c
- /// stop, as usual). \c start and \c stop are interpreted as for
- /// <code>operator[]</code>, with negative values offsetting from
- /// the end of the range. Omitting the \c stop argument makes the
- /// sub-range continue to the end of the original range. Positive
- /// arguments saturate to the end of the range, and negative
- /// arguments saturate to the beginning. If \c stop is before \c
- /// start, returns an empty range beginning and ending at \c start.
- ///
- /// \par Ill-formed unless:
- /// \c iterator_category is convertible to
- /// \c std::forward_iterator_tag.
- ///
- /// \par Complexity:
- /// - If \c iterator_category is convertible to \c
- /// std::random_access_iterator_tag: O(1)
- /// - Otherwise, if \c iterator_category is convertible to \c
- /// std::bidirectional_iterator_tag, at most <code>min(abs(start),
- /// size()) + min(abs(stop), size())</code> iterator
- /// increments or decrements
- /// - Otherwise, if <code>start >= 0 && stop >= 0</code>,
- /// <code>max(start, stop)</code> iterator increments
- /// - Otherwise, <code>size() + max(start', stop')</code>
- /// iterator increments, where \c start' and \c stop' are the
- /// offsets of the elements \c start and \c stop refer to.
- ///
- /// \note \c slice(start) should be implemented with a different
- /// overload, rather than defaulting \c stop to
- /// <code>numeric_limits<difference_type>::max()</code>, because
- /// using a default would force non-random-access ranges to use an
- /// O(<code>size()</code>) algorithm to compute the end rather
- /// than the O(1) they're capable of.
- range slice(difference_type start, difference_type stop) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling slice on a non-std::forward range would destroy the original "
- "range.");
- return dispatch_slice(start, stop, iterator_category());
- }
-
- range slice(difference_type start) const {
- static_assert(
- std::is_convertible<iterator_category,
- std::forward_iterator_tag>::value,
- "Calling slice on a non-std::forward range would destroy the original "
- "range.");
- return split(start).second;
- }
-
- /// @}
-
-private:
- // advance_upto: should be added to <algorithm>, but I'll use it as
- // a helper function here.
- //
- // These return the number of increments that weren't applied
- // because we ran into 'limit' (or 0 if we didn't run into limit).
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit, std::input_iterator_tag) {
- if (n < 0)
- return 0;
- while (it != limit && n > 0) {
- ++it;
- --n;
- }
- return n;
- }
-
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit,
- std::bidirectional_iterator_tag) {
- if (n < 0) {
- while (it != limit && n < 0) {
- --it;
- ++n;
- }
- } else {
- while (it != limit && n > 0) {
- ++it;
- --n;
- }
- }
- return n;
- }
-
- static difference_type advance_upto(Iterator &it, difference_type n,
- Iterator limit,
- std::random_access_iterator_tag) {
- difference_type distance = limit - it;
- if (distance < 0)
- assert(n <= 0);
- else if (distance > 0)
- assert(n >= 0);
-
- if (abs(distance) > abs(n)) {
- it += n;
- return 0;
- } else {
- it = limit;
- return n - distance;
- }
- }
-
- // Dispatch functions.
- difference_type dispatch_size(std::forward_iterator_tag) const {
- return std::distance(begin(), end());
- }
-
- LLVM_CONSTEXPR difference_type dispatch_size(
- std::random_access_iterator_tag) const {
- return end() - begin();
- }
-
- std::pair<range, range> dispatch_split_neg(difference_type index,
- std::forward_iterator_tag) const {
- assert(index < 0);
- difference_type size = this->size();
- return split(std::max<difference_type>(0, size + index));
- }
-
- std::pair<range, range> dispatch_split_neg(
- difference_type index, std::bidirectional_iterator_tag) const {
- assert(index < 0);
- range first = *this;
- first.pop_back_upto(-index);
- return make_pair(first, range(first.end(), end()));
- }
-
- range dispatch_slice(difference_type start, difference_type stop,
- std::forward_iterator_tag) const {
- if (start < 0 || stop < 0) {
- difference_type size = this->size();
- if (start < 0)
- start = std::max<difference_type>(0, size + start);
- if (stop < 0)
- stop = size + stop; // Possibly negative; will be fixed in 2 lines.
- }
- stop = std::max<difference_type>(start, stop);
-
- Iterator first = begin();
- advance_upto(first, start, end(), iterator_category());
- Iterator last = first;
- advance_upto(last, stop - start, end(), iterator_category());
- return range(first, last);
- }
-
- range dispatch_slice(const difference_type start, const difference_type stop,
- std::bidirectional_iterator_tag) const {
- Iterator first;
- if (start < 0) {
- first = end();
- advance_upto(first, start, begin(), iterator_category());
- } else {
- first = begin();
- advance_upto(first, start, end(), iterator_category());
- }
- Iterator last;
- if (stop < 0) {
- last = end();
- advance_upto(last, stop, first, iterator_category());
- } else {
- if (start >= 0) {
- last = first;
- if (stop > start)
- advance_upto(last, stop - start, end(), iterator_category());
- } else {
- // Complicated: 'start' walked from the end of the sequence,
- // but 'stop' needs to walk from the beginning.
- Iterator dummy = begin();
- // Walk up to 'stop' increments from begin(), stopping when we
- // get to 'first', and capturing the remaining number of
- // increments.
- difference_type increments_past_start =
- advance_upto(dummy, stop, first, iterator_category());
- if (increments_past_start == 0) {
- // If this is 0, then stop was before start.
- last = first;
- } else {
- // Otherwise, count that many spaces beyond first.
- last = first;
- advance_upto(last, increments_past_start, end(), iterator_category());
- }
- }
- }
- return range(first, last);
- }
-
- range dispatch_slice(difference_type start, difference_type stop,
- std::random_access_iterator_tag) const {
- const difference_type size = this->size();
- if (start < 0)
- start = size + start;
- if (start < 0)
- start = 0;
- if (start > size)
- start = size;
-
- if (stop < 0)
- stop = size + stop;
- if (stop < start)
- stop = start;
- if (stop > size)
- stop = size;
-
- return range(begin() + start, begin() + stop);
- }
-};
-
-/// \name deducing constructor wrappers
-/// \relates std::range
-/// \xmlonly <nonmember/> \endxmlonly
-///
-/// These functions do the same thing as the constructor with the same
-/// signature. They just allow users to avoid writing the iterator
-/// type.
-/// @{
-
-/// \todo I'd like to define a \c make_range taking a single iterator
-/// argument representing the beginning of a range that ends with a
-/// default-constructed \c Iterator. This would help with using
-/// iterators like \c istream_iterator. However, using just \c
-/// make_range() could be confusing and lead to people writing
-/// incorrect ranges of more common iterators. Is there a better name?
-template <typename Iterator>
-LLVM_CONSTEXPR range<Iterator> make_range(Iterator begin, Iterator end) {
- return range<Iterator>(begin, end);
-}
-
-/// \par Participates in overload resolution if:
-/// \c begin(r) and \c end(r) return the same type.
-template <typename Range> LLVM_CONSTEXPR auto make_range(
- Range &&r,
- typename std::enable_if<detail::is_range<Range>::value>::type* = 0)
- -> range<decltype(detail::adl_begin(r))> {
- return range<decltype(detail::adl_begin(r))>(r);
-}
-
-/// \par Participates in overload resolution if:
-/// - \c begin(r) and \c end(r) return the same type,
-/// - that type satisfies the invariant that <code>&*(i + N) ==
-/// (&*i) + N</code>, and
-/// - \c &*begin(r) has a pointer type.
-template <typename Range> LLVM_CONSTEXPR auto make_ptr_range(
- Range &&r,
- typename std::enable_if<
- detail::is_contiguous_range<Range>::value &&
- std::is_pointer<decltype(&*detail::adl_begin(r))>::value>::type* = 0)
- -> range<decltype(&*detail::adl_begin(r))> {
- return range<decltype(&*detail::adl_begin(r))>(r);
-}
-/// @}
-} // end namespace lld
-
-#endif
diff --git a/include/lld/Driver/Driver.h b/include/lld/Driver/Driver.h
index 4bf0f43f8ce5..312f4f812b77 100644
--- a/include/lld/Driver/Driver.h
+++ b/include/lld/Driver/Driver.h
@@ -6,145 +6,27 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Interface for Drivers which convert command line arguments into
-/// LinkingContext objects, then perform the link.
-///
-//===----------------------------------------------------------------------===//
#ifndef LLD_DRIVER_DRIVER_H
#define LLD_DRIVER_DRIVER_H
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Node.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <set>
-#include <vector>
namespace lld {
-class LinkingContext;
-class CoreLinkingContext;
-class MachOLinkingContext;
-class PECOFFLinkingContext;
-class ELFLinkingContext;
-
-typedef std::vector<std::unique_ptr<File>> FileVector;
-
-FileVector makeErrorFile(StringRef path, std::error_code ec);
-FileVector parseMemberFiles(std::unique_ptr<File> File);
-FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
-
-/// Base class for all Drivers.
-class Driver {
-protected:
-
- /// Performs link using specified options
- 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;
-};
-
-/// Driver for "universal" lld tool which can mimic any linker command line
-/// parsing once it figures out which command line flavor to use.
-class UniversalDriver : public Driver {
-public:
- /// Determine flavor and pass control to Driver for that flavor.
- static bool link(llvm::MutableArrayRef<const char *> args,
- raw_ostream &diag = llvm::errs());
-
-private:
- UniversalDriver() = delete;
-};
-
-/// Driver for gnu/binutil 'ld' command line options.
-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(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(llvm::ArrayRef<const char *> args,
- std::unique_ptr<ELFLinkingContext> &context,
- raw_ostream &diag = llvm::errs());
-
- /// Parses a given memory buffer as a linker script and evaluate that.
- /// Public function for testing.
- static std::error_code evalLinkerScript(ELFLinkingContext &ctx,
- std::unique_ptr<MemoryBuffer> mb,
- raw_ostream &diag, bool nostdlib);
-
- /// A factory method to create an instance of ELFLinkingContext.
- static std::unique_ptr<ELFLinkingContext>
- createELFLinkingContext(llvm::Triple triple);
-
-private:
- static llvm::Triple getDefaultTarget(const char *progName);
- static bool applyEmulation(llvm::Triple &triple,
- llvm::opt::InputArgList &args,
- raw_ostream &diag);
- static void addPlatformSearchDirs(ELFLinkingContext &ctx,
- llvm::Triple &triple,
- llvm::Triple &baseTriple);
-
- GnuLdDriver() = delete;
-};
-
-/// Driver for darwin/ld64 'ld' command line options.
-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(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(llvm::ArrayRef<const char *> args,
- MachOLinkingContext &info,
- raw_ostream &diag = llvm::errs());
-
-private:
- DarwinLdDriver() = delete;
-};
-
-/// Driver for Windows 'link.exe' command line options
namespace coff {
-void link(llvm::ArrayRef<const char *> args);
+bool link(llvm::ArrayRef<const char *> Args);
}
-namespace elf2 {
-void link(llvm::ArrayRef<const char *> args);
+namespace elf {
+bool link(llvm::ArrayRef<const char *> Args,
+ llvm::raw_ostream &Diag = llvm::errs());
}
-/// 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(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(llvm::ArrayRef<const char *> args, CoreLinkingContext &info,
- raw_ostream &diag = llvm::errs());
-
-private:
- CoreDriver() = delete;
-};
-
-} // end namespace lld
+namespace mach_o {
+bool link(llvm::ArrayRef<const char *> Args,
+ llvm::raw_ostream &Diag = llvm::errs());
+}
+}
#endif
diff --git a/include/lld/ReaderWriter/AtomLayout.h b/include/lld/ReaderWriter/AtomLayout.h
deleted file mode 100644
index ad4cd0607b88..000000000000
--- a/include/lld/ReaderWriter/AtomLayout.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- include/lld/ReaderWriter/AtomLayout.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_ATOM_LAYOUT_H
-#define LLD_READER_WRITER_ATOM_LAYOUT_H
-
-namespace lld {
-class Atom;
-
-/// AtomLayouts are used by a writer to manage physical positions of atoms.
-/// AtomLayout has two positions; one is file offset, and the other is the
-/// address when loaded into memory.
-///
-/// Construction of AtomLayouts is usually a multi-pass process. When an atom
-/// is appended to a section, we don't know the starting address of the
-/// section. Thus, we have no choice but to store the offset from the
-/// beginning of the section as AtomLayout values. After all sections starting
-/// address are fixed, AtomLayout is revisited to get the offsets updated by
-/// adding the starting addresses of the section.
-struct AtomLayout {
- AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
- : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {}
-
- AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
-
- const Atom *_atom;
- uint64_t _fileOffset;
- uint64_t _virtualAddr;
-};
-
-}
-
-#endif
diff --git a/include/lld/ReaderWriter/CoreLinkingContext.h b/include/lld/ReaderWriter/CoreLinkingContext.h
deleted file mode 100644
index d597ca46ddc7..000000000000
--- a/include/lld/ReaderWriter/CoreLinkingContext.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- lld/ReaderWriter/CoreLinkingContext.h ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_CORE_LINKER_CONTEXT_H
-#define LLD_READER_WRITER_CORE_LINKER_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-
-class CoreLinkingContext : public LinkingContext {
-public:
- CoreLinkingContext();
-
- enum {
- TEST_RELOC_CALL32 = 1,
- TEST_RELOC_PCREL32 = 2,
- TEST_RELOC_GOT_LOAD32 = 3,
- TEST_RELOC_GOT_USE32 = 4,
- TEST_RELOC_LEA32_WAS_GOT = 5,
- };
-
- bool validateImpl(raw_ostream &diagnostics) override;
- void addPasses(PassManager &pm) override;
-
- void addPassNamed(StringRef name) { _passNames.push_back(name); }
-
-protected:
- Writer &writer() const override;
-
-private:
- std::unique_ptr<Writer> _writer;
- std::vector<StringRef> _passNames;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/ELFLinkingContext.h b/include/lld/ReaderWriter/ELFLinkingContext.h
deleted file mode 100644
index d1a5b28bb61f..000000000000
--- a/include/lld/ReaderWriter/ELFLinkingContext.h
+++ /dev/null
@@ -1,422 +0,0 @@
-//===- lld/ReaderWriter/ELFLinkingContext.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_LINKER_CONTEXT_H
-#define LLD_READER_WRITER_ELF_LINKER_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/STDExtras.h"
-#include "lld/Core/range.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/LinkerScript.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-#include <map>
-#include <memory>
-#include <set>
-
-namespace llvm {
-class FileOutputBuffer;
-}
-
-namespace lld {
-struct AtomLayout;
-class File;
-class Reference;
-
-namespace elf {
-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;
-};
-
-} // 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 ~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;
-};
-
-class ELFLinkingContext : public LinkingContext {
-public:
- /// \brief The type of ELF executable that the linker
- /// creates.
- enum class OutputMagic : uint8_t {
- // 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; }
-
- 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; }
-
- void notifySymbolTableCoalesce(const Atom *existingAtom, const Atom *newAtom,
- bool &useNew) override;
-
- /// This controls if undefined atoms need to be created for undefines that are
- /// present in a SharedLibrary. If this option is set, undefined atoms are
- /// created for every undefined symbol that are present in the dynamic table
- /// in the shared library
- bool useShlibUndefines() const { return _useShlibUndefines; }
-
- /// \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.
- /// Relocations that return true will be added to the dynamic relocation
- /// table.
- virtual bool isDynamicRelocation(const Reference &) const { return false; }
-
- /// \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; }
-
- bool validateImpl(raw_ostream &diagnostics) override;
-
- /// \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
- bool allowLinkWithDynamicLibraries() const {
- if (_outputMagic == OutputMagic::NMAGIC ||
- _outputMagic == OutputMagic::OMAGIC || _noAllowDynamicLibraries)
- return false;
- return true;
- }
-
- /// \brief Use Elf_Rela format to output relocation tables.
- virtual bool isRelaOutputFormat() const { return true; }
-
- /// \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
- /// by the DT_{JMPREL,PLTRELSZ} entries in the dynamic table.
- /// Relocations that return true will be added to the dynamic plt relocation
- /// table.
- virtual bool isPLTRelocation(const Reference &) const { return false; }
-
- /// \brief The path to the dynamic interpreter
- virtual StringRef getDefaultInterpreter() const {
- return "/lib64/ld-linux-x86-64.so.2";
- }
-
- /// \brief The dynamic linker path set by the --dynamic-linker option
- StringRef getInterpreter() const {
- if (_dynamicLinkerPath.hasValue())
- return _dynamicLinkerPath.getValue();
- return getDefaultInterpreter();
- }
-
- /// \brief Returns true if the output have dynamic sections.
- bool isDynamic() const;
-
- /// \brief Returns true if we are creating a shared library.
- bool isDynamicLibrary() const { return _outputELFType == llvm::ELF::ET_DYN; }
-
- /// \brief Returns true if a given relocation is a relative relocation.
- virtual bool isRelativeReloc(const Reference &r) const;
-
- TargetHandler &getTargetHandler() const {
- assert(_targetHandler && "Got null TargetHandler!");
- return *_targetHandler;
- }
-
- virtual void registerRelocationNames(Registry &) = 0;
-
- void addPasses(PassManager &pm) override;
-
- void setTriple(llvm::Triple trip) { _triple = trip; }
- void setNoInhibitExec(bool v) { _noInhibitExec = v; }
- void setExportDynamic(bool v) { _exportDynamic = v; }
- void setIsStaticExecutable(bool v) { _isStaticExecutable = v; }
- void setMergeCommonStrings(bool v) { _mergeCommonStrings = v; }
- void setUseShlibUndefines(bool use) { _useShlibUndefines = use; }
- void setOutputELFType(uint32_t type) { _outputELFType = type; }
-
- bool shouldExportDynamic() const { return _exportDynamic; }
-
- void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override;
-
- void finalizeInputFiles() override;
-
- /// \brief Set the dynamic linker path
- 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
- void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
-
- /// \brief Disallow dynamic libraries during linking
- void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
-
- /// Searches directories for a match on the input File
- ErrorOr<StringRef> searchLibrary(StringRef libName) const;
-
- /// \brief Searches directories for a match on the input file.
- /// If \p fileName is an absolute path and \p isSysRooted is true, check
- /// the file under sysroot directory. If \p fileName is a relative path
- /// and is not in the current directory, search the file through library
- /// search directories.
- ErrorOr<StringRef> searchFile(StringRef fileName, bool isSysRooted) const;
-
- /// Get the entry symbol name
- StringRef entrySymbolName() const override;
-
- /// \brief Set new initializer function
- void setInitFunction(StringRef name) { _initFunction = name; }
-
- /// \brief Return an initializer function name.
- /// Either default "_init" or configured by the -init command line option.
- StringRef initFunction() const { return _initFunction; }
-
- /// \brief Set new finalizer function
- void setFiniFunction(StringRef name) { _finiFunction = name; }
-
- /// \brief Return a finalizer function name.
- /// Either default "_fini" or configured by the -fini command line option.
- StringRef finiFunction() const { return _finiFunction; }
-
- /// Add an absolute symbol. Used for --defsym.
- void addInitialAbsoluteSymbol(StringRef name, uint64_t addr) {
- _absoluteSymbols[name] = addr;
- }
-
- StringRef sharedObjectName() const { return _soname; }
- void setSharedObjectName(StringRef soname) { _soname = soname; }
-
- StringRef getSysroot() const { return _sysrootPath; }
- 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); }
- range<const StringRef *> getRpathLinkList() const { return _rpathLinkList; }
-
- const std::map<std::string, uint64_t> &getAbsoluteSymbols() const {
- return _absoluteSymbols;
- }
-
- /// \brief Helper function to allocate strings.
- StringRef allocateString(StringRef ref) const {
- char *x = _allocator.Allocate<char>(ref.size() + 1);
- memcpy(x, ref.data(), ref.size());
- x[ref.size()] = '\0';
- return x;
- }
-
- // add search path to list.
- void addSearchPath(StringRef ref) { _inputSearchPaths.push_back(ref); }
-
- // Retrieve search path list.
- 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
- // flag --rosegment, a separate segment needs to be created.
- bool mergeRODataToTextSegment() const { return _mergeRODataToTextSegment; }
-
- void setCreateSeparateROSegment() { _mergeRODataToTextSegment = false; }
-
- bool isDynamicallyExportedSymbol(StringRef name) const {
- return _dynamicallyExportedSymbols.count(name) != 0;
- }
-
- /// \brief Demangle symbols.
- std::string demangle(StringRef symbolName) const override;
- bool demangleSymbols() const { return _demangle; }
- void setDemangleSymbols(bool d) { _demangle = d; }
-
- /// \brief Align segments.
- 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; }
-
- /// \brief Collect statistics.
- bool collectStats() const { return _collectStats; }
- void setCollectStats(bool s) { _collectStats = s; }
-
- // --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);
-
- script::Sema &linkerScriptSema() { return _linkerScriptSema; }
- const script::Sema &linkerScriptSema() const { return _linkerScriptSema; }
-
- /// 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 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 = llvm::ELF::ET_EXEC;
- llvm::Triple _triple;
- 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;
- llvm::Optional<StringRef> _dynamicLinkerPath;
- StringRef _initFunction = "_init";
- StringRef _finiFunction = "_fini";
- StringRef _sysrootPath = "";
- StringRef _soname;
- StringRefVector _rpathList;
- StringRefVector _rpathLinkList;
- llvm::StringSet<> _wrapCalls;
- 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/LinkerScript.h b/include/lld/ReaderWriter/LinkerScript.h
deleted file mode 100644
index 08ccb89ce8c1..000000000000
--- a/include/lld/ReaderWriter/LinkerScript.h
+++ /dev/null
@@ -1,1471 +0,0 @@
-//===- ReaderWriter/LinkerScript.h ----------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Linker script parser.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_LINKER_SCRIPT_H
-#define LLD_READER_WRITER_LINKER_SCRIPT_H
-
-#include "lld/Core/Error.h"
-#include "lld/Core/LLVM.h"
-#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"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <system_error>
-#include <unordered_map>
-#include <vector>
-
-namespace lld {
-namespace script {
-class Token {
-public:
- enum Kind {
- unknown,
- eof,
- exclaim,
- exclaimequal,
- amp,
- ampequal,
- l_paren,
- r_paren,
- star,
- starequal,
- plus,
- plusequal,
- comma,
- minus,
- minusequal,
- slash,
- slashequal,
- number,
- colon,
- semicolon,
- less,
- lessequal,
- lessless,
- lesslessequal,
- equal,
- equalequal,
- greater,
- greaterequal,
- greatergreater,
- greatergreaterequal,
- question,
- identifier,
- libname,
- kw_align,
- kw_align_with_input,
- kw_as_needed,
- kw_at,
- kw_discard,
- kw_entry,
- kw_exclude_file,
- kw_extern,
- kw_filehdr,
- kw_fill,
- kw_flags,
- kw_group,
- kw_hidden,
- kw_input,
- kw_keep,
- kw_length,
- kw_memory,
- kw_origin,
- kw_phdrs,
- kw_provide,
- kw_provide_hidden,
- kw_only_if_ro,
- kw_only_if_rw,
- kw_output,
- kw_output_arch,
- kw_output_format,
- kw_overlay,
- kw_search_dir,
- kw_sections,
- kw_sort_by_alignment,
- kw_sort_by_init_priority,
- kw_sort_by_name,
- kw_sort_none,
- kw_subalign,
- l_brace,
- pipe,
- pipeequal,
- r_brace,
- tilde
- };
-
- Token() : _kind(unknown) {}
- Token(StringRef range, Kind kind) : _range(range), _kind(kind) {}
-
- void dump(raw_ostream &os) const;
-
- StringRef _range;
- Kind _kind;
-};
-
-class Lexer {
-public:
- explicit Lexer(std::unique_ptr<MemoryBuffer> mb) : _buffer(mb->getBuffer()) {
- _sourceManager.AddNewSourceBuffer(std::move(mb), llvm::SMLoc());
- }
-
- void lex(Token &tok);
-
- const llvm::SourceMgr &getSourceMgr() const { return _sourceManager; }
-
-private:
- bool canStartNumber(char c) const;
- bool canContinueNumber(char c) const;
- bool canStartName(char c) const;
- bool canContinueName(char c) const;
- void skipWhitespace();
-
- Token _current;
- /// \brief The current buffer state.
- StringRef _buffer;
- // Lexer owns the input files.
- llvm::SourceMgr _sourceManager;
-};
-
-/// All linker scripts commands derive from this class. High-level, sections and
-/// output section commands are all subclasses of this class.
-/// Examples:
-///
-/// OUTPUT_FORMAT("elf64-x86-64") /* A linker script command */
-/// OUTPUT_ARCH(i386:x86-64) /* Another command */
-/// ENTRY(_start) /* Another command */
-///
-/// SECTIONS /* Another command */
-/// {
-/// .interp : { /* A sections-command */
-/// *(.interp) /* An output-section-command */
-/// }
-/// }
-///
-class Command {
-public:
- enum class Kind {
- Entry,
- Extern,
- Fill,
- Group,
- Input,
- InputSectionsCmd,
- InputSectionName,
- Memory,
- Output,
- OutputArch,
- OutputFormat,
- OutputSectionDescription,
- Overlay,
- PHDRS,
- SearchDir,
- Sections,
- SortedGroup,
- SymbolAssignment,
- };
-
- Kind getKind() const { return _kind; }
- inline llvm::BumpPtrAllocator &getAllocator() const;
-
- virtual void dump(raw_ostream &os) const = 0;
-
- virtual ~Command() {}
-
-protected:
- Command(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
-
-private:
- Parser &_ctx;
- 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)
- : Command(ctx, Kind::Output), _outputFileName(outputFileName) {}
-
- static bool classof(const Command *c) { return c->getKind() == Kind::Output; }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT(" << _outputFileName << ")\n";
- }
-
- StringRef getOutputFileName() const { return _outputFileName; }
-
-private:
- StringRef _outputFileName;
-};
-
-class OutputFormat : public Command {
-public:
- OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
- : Command(ctx, Kind::OutputFormat) {
- _formats = save_array<StringRef>(getAllocator(), formats);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputFormat;
- }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT_FORMAT(";
- bool first = true;
- for (StringRef format : _formats) {
- if (!first)
- os << ",";
- first = false;
- os << "\"" << format << "\"";
- }
- os << ")\n";
- }
-
- llvm::ArrayRef<StringRef> getFormats() { return _formats; }
-
-private:
- llvm::ArrayRef<StringRef> _formats;
-};
-
-class OutputArch : public Command {
-public:
- OutputArch(Parser &ctx, StringRef arch)
- : Command(ctx, Kind::OutputArch), _arch(arch) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputArch;
- }
-
- void dump(raw_ostream &os) const override {
- os << "OUTPUT_ARCH(" << getArch() << ")\n";
- }
-
- StringRef getArch() const { return _arch; }
-
-private:
- StringRef _arch;
-};
-
-struct Path {
- StringRef _path;
- bool _asNeeded;
- bool _isDashlPrefix;
-
- Path() : _asNeeded(false), _isDashlPrefix(false) {}
- Path(StringRef path, bool asNeeded = false, bool isLib = false)
- : _path(path), _asNeeded(asNeeded), _isDashlPrefix(isLib) {}
-};
-
-template<Command::Kind K>
-class PathList : public Command {
-public:
- PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
- : Command(ctx, K), _name(name) {
- _paths = save_array<Path>(getAllocator(), paths);
- }
-
- static bool classof(const Command *c) { return c->getKind() == K; }
-
- void dump(raw_ostream &os) const override {
- os << _name << "(";
- bool first = true;
- for (const Path &path : getPaths()) {
- if (!first)
- os << " ";
- first = false;
- if (path._asNeeded)
- os << "AS_NEEDED(";
- if (path._isDashlPrefix)
- os << "-l";
- os << path._path;
- if (path._asNeeded)
- os << ")";
- }
- os << ")\n";
- }
-
- llvm::ArrayRef<Path> getPaths() const { return _paths; }
-
-private:
- StringRef _name;
- llvm::ArrayRef<Path> _paths;
-};
-
-class Group : public PathList<Command::Kind::Group> {
-public:
- template <class RangeT>
- Group(Parser &ctx, RangeT range)
- : PathList(ctx, "GROUP", std::move(range)) {}
-};
-
-class Input : public PathList<Command::Kind::Input> {
-public:
- template <class RangeT>
- Input(Parser &ctx, RangeT range)
- : PathList(ctx, "INPUT", std::move(range)) {}
-};
-
-class Entry : public Command {
-public:
- Entry(Parser &ctx, StringRef entryName)
- : Command(ctx, Kind::Entry), _entryName(entryName) {}
-
- static bool classof(const Command *c) { return c->getKind() == Kind::Entry; }
-
- void dump(raw_ostream &os) const override {
- os << "ENTRY(" << _entryName << ")\n";
- }
-
- StringRef getEntryName() const { return _entryName; }
-
-private:
- StringRef _entryName;
-};
-
-class SearchDir : public Command {
-public:
- SearchDir(Parser &ctx, StringRef searchPath)
- : Command(ctx, Kind::SearchDir), _searchPath(searchPath) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SearchDir;
- }
-
- void dump(raw_ostream &os) const override {
- os << "SEARCH_DIR(\"" << _searchPath << "\")\n";
- }
-
- StringRef getSearchPath() const { return _searchPath; }
-
-private:
- StringRef _searchPath;
-};
-
-/// Superclass for expression nodes. Linker scripts accept C-like expressions in
-/// many places, such as when defining the value of a symbol or the address of
-/// an output section.
-/// Example:
-///
-/// SECTIONS {
-/// my_symbol = 1 + 1 * 2;
-/// | | ^~~~> Constant : Expression
-/// | | ^~~~> Constant : Expression
-/// | | ^~~~> BinOp : Expression
-/// ^~~~> Constant : Expression
-/// ^~~~> BinOp : Expression (the top-level Expression node)
-/// }
-///
-class Expression {
-public:
- // The symbol table does not need to own its string keys and the use of StringMap
- // here is an overkill.
- typedef llvm::StringMap<int64_t, llvm::BumpPtrAllocator> SymbolTableTy;
-
- enum class Kind { Constant, Symbol, FunctionCall, Unary, BinOp,
- TernaryConditional };
- Kind getKind() const { return _kind; }
- inline llvm::BumpPtrAllocator &getAllocator() const;
- virtual void dump(raw_ostream &os) const = 0;
- virtual ErrorOr<int64_t>
- evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
- virtual ~Expression() {}
-
-protected:
- Expression(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
-
-private:
- Parser &_ctx;
- Kind _kind;
-};
-
-/// A constant value is stored as unsigned because it represents absolute
-/// values. We represent negative numbers by composing the unary '-' operator
-/// with a constant.
-class Constant : public Expression {
-public:
- Constant(Parser &ctx, uint64_t num)
- : Expression(ctx, Kind::Constant), _num(num) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Constant;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- uint64_t _num;
-};
-
-class Symbol : public Expression {
-public:
- Symbol(Parser &ctx, StringRef name)
- : Expression(ctx, Kind::Symbol), _name(name) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Symbol;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- StringRef _name;
-};
-
-class FunctionCall : public Expression {
-public:
- FunctionCall(Parser &ctx, StringRef name,
- const SmallVectorImpl<const Expression *> &args)
- : Expression(ctx, Kind::FunctionCall), _name(name) {
- _args = save_array<const Expression *>(getAllocator(), args);
- }
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::FunctionCall;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- StringRef _name;
- llvm::ArrayRef<const Expression *> _args;
-};
-
-class Unary : public Expression {
-public:
- enum Operation {
- Minus,
- Not
- };
-
- Unary(Parser &ctx, Operation op, const Expression *child)
- : Expression(ctx, Kind::Unary), _op(op), _child(child) {}
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::Unary;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- Operation _op;
- const Expression *_child;
-};
-
-class BinOp : public Expression {
-public:
- enum Operation {
- And,
- CompareDifferent,
- CompareEqual,
- CompareGreater,
- CompareGreaterEqual,
- CompareLess,
- CompareLessEqual,
- Div,
- Mul,
- Or,
- Shl,
- Shr,
- Sub,
- Sum
- };
-
- BinOp(Parser &ctx, const Expression *lhs, Operation op, const Expression *rhs)
- : Expression(ctx, Kind::BinOp), _op(op), _lhs(lhs), _rhs(rhs) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::BinOp;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- Operation _op;
- const Expression *_lhs;
- const Expression *_rhs;
-};
-
-/// Operands of the ternary operator can be any expression, similar to the other
-/// operations, including another ternary operator. To disambiguate the parse
-/// tree, note that ternary conditionals have precedence 13 and, different from
-/// other operators, associates right-to-left. For example:
-///
-/// i = i > 3 ? i < 5 ? 1 : 2 : 0;
-///
-/// will have the following parse tree:
-///
-/// i = ((i > 3) ? ((i < 5) ? 1 : 2) : 0);
-///
-/// The '>' binds tigher because it has precedence 6. When faced with two "?"
-/// ternary operators back-to-back, the parser prioritized the rightmost one.
-///
-class TernaryConditional : public Expression {
-public:
- TernaryConditional(Parser &ctx, const Expression *conditional,
- const Expression *trueExpr, const Expression *falseExpr)
- : Expression(ctx, Kind::TernaryConditional), _conditional(conditional),
- _trueExpr(trueExpr), _falseExpr(falseExpr) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Expression *c) {
- return c->getKind() == Kind::TernaryConditional;
- }
-
- ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
-
-private:
- const Expression *_conditional;
- const Expression *_trueExpr;
- const Expression *_falseExpr;
-};
-
-/// Symbol assignments of the form "symbolname = <expression>" may occur either
-/// as sections-commands or as output-section-commands.
-/// Example:
-///
-/// SECTIONS {
-/// mysymbol = . /* SymbolAssignment as a sections-command */
-/// .data : {
-/// othersymbol = . /* SymbolAssignment as an output-section-command */
-/// }
-///}
-///
-class SymbolAssignment : public Command {
-public:
- enum AssignmentKind { Simple, Sum, Sub, Mul, Div, Shl, Shr, And, Or };
- enum AssignmentVisibility { Default, Hidden, Provide, ProvideHidden };
-
- SymbolAssignment(Parser &ctx, StringRef name, const Expression *expr,
- AssignmentKind kind, AssignmentVisibility visibility)
- : Command(ctx, Kind::SymbolAssignment), _expression(expr), _symbol(name),
- _assignmentKind(Simple), _assignmentVisibility(visibility) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SymbolAssignment;
- }
-
- void dump(raw_ostream &os) const override;
- const Expression *expr() const { return _expression; }
- StringRef symbol() const { return _symbol; }
- AssignmentKind assignmentKind() const { return _assignmentKind; }
- AssignmentVisibility assignmentVisibility() const {
- return _assignmentVisibility;
- }
-
-private:
- const Expression *_expression;
- StringRef _symbol;
- AssignmentKind _assignmentKind;
- AssignmentVisibility _assignmentVisibility;
-};
-
-/// Encodes how to sort file names or section names that are expanded from
-/// wildcard operators. This typically occurs in constructs such as
-/// SECTIONS { .data : SORT_BY_NAME(*)(*) }}, where the order of the expanded
-/// names is important to determine which sections go first.
-enum class WildcardSortMode {
- NA,
- ByAlignment,
- ByAlignmentAndName,
- ByInitPriority,
- ByName,
- ByNameAndAlignment,
- None
-};
-
-/// Represents either a single input section name or a group of sorted input
-/// section names. They specify which sections to map to a given output section.
-/// Example:
-///
-/// SECTIONS {
-/// .x: { *(.text) }
-/// /* ^~~~^ InputSectionName : InputSection */
-/// .y: { *(SORT(.text*)) }
-/// /* ^~~~~~~~~~~^ InputSectionSortedGroup : InputSection */
-/// }
-class InputSection : public Command {
-public:
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionName ||
- c->getKind() == Kind::SortedGroup;
- }
-
-protected:
- InputSection(Parser &ctx, Kind k) : Command(ctx, k) {}
-};
-
-class InputSectionName : public InputSection {
-public:
- InputSectionName(Parser &ctx, StringRef name, bool excludeFile)
- : InputSection(ctx, Kind::InputSectionName), _name(name),
- _excludeFile(excludeFile) {}
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionName;
- }
- bool hasExcludeFile() const { return _excludeFile; }
- StringRef name() const { return _name; }
-
-private:
- StringRef _name;
- bool _excludeFile;
-};
-
-class InputSectionSortedGroup : public InputSection {
-public:
- typedef llvm::ArrayRef<const InputSection *>::const_iterator const_iterator;
-
- InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
- const SmallVectorImpl<const InputSection *> &sections)
- : InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
- _sections = save_array<const InputSection *>(getAllocator(), sections);
- }
-
- void dump(raw_ostream &os) const override;
- WildcardSortMode sortMode() const { return _sortMode; }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::SortedGroup;
- }
-
- const_iterator begin() const { return _sections.begin(); }
- const_iterator end() const { return _sections.end(); }
-
-private:
- WildcardSortMode _sortMode;
- llvm::ArrayRef<const InputSection *> _sections;
-};
-
-/// An output-section-command that maps a series of sections inside a given
-/// file-archive pair to an output section.
-/// Example:
-///
-/// SECTIONS {
-/// .x: { *(.text) }
-/// /* ^~~~~~~^ InputSectionsCmd */
-/// .y: { w:z(SORT(.text*)) }
-/// /* ^~~~~~~~~~~~~~~~^ InputSectionsCmd */
-/// }
-class InputSectionsCmd : public Command {
-public:
- typedef llvm::ArrayRef<const InputSection *>::const_iterator const_iterator;
- typedef std::vector<const InputSection *> VectorTy;
-
- InputSectionsCmd(Parser &ctx, StringRef memberName, StringRef archiveName,
- bool keep, WildcardSortMode fileSortMode,
- WildcardSortMode archiveSortMode,
- const SmallVectorImpl<const InputSection *> &sections)
- : Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
- _archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
- _archiveSortMode(archiveSortMode) {
- _sections = save_array<const InputSection *>(getAllocator(), sections);
- }
-
- void dump(raw_ostream &os) const override;
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::InputSectionsCmd;
- }
-
- StringRef memberName() const { return _memberName; }
- StringRef archiveName() const { return _archiveName; }
- const_iterator begin() const { return _sections.begin(); }
- const_iterator end() const { return _sections.end(); }
- WildcardSortMode archiveSortMode() const { return _archiveSortMode; }
- WildcardSortMode fileSortMode() const { return _fileSortMode; }
-
-private:
- StringRef _memberName;
- StringRef _archiveName;
- bool _keep;
- WildcardSortMode _fileSortMode;
- WildcardSortMode _archiveSortMode;
- 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:
-///
-/// SECTIONS {
-/// .x: { *(.text) ; symbol = .; }
-/// /*^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ OutputSectionDescription */
-/// .y: { w:z(SORT(.text*)) }
-/// /*^~~~~~~~~~~~~~~~~~~~~~~~^ OutputSectionDescription */
-/// .a 0x10000 : ONLY_IF_RW { *(.data*) ; *:libc.a(SORT(*)); }
-/// /*^~~~~~~~~~~~~ OutputSectionDescription ~~~~~~~~~~~~~~~~~^ */
-/// }
-class OutputSectionDescription : public Command {
-public:
- enum Constraint { C_None, C_OnlyIfRO, C_OnlyIfRW };
-
- typedef llvm::ArrayRef<const Command *>::const_iterator const_iterator;
-
- OutputSectionDescription(
- Parser &ctx, StringRef sectionName, const Expression *address,
- 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,
- 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) {
- _outputSectionCommands =
- save_array<const Command *>(getAllocator(), outputSectionCommands);
- _phdrs = save_array<StringRef>(getAllocator(), phdrs);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::OutputSectionDescription;
- }
-
- void dump(raw_ostream &os) const override;
-
- 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;
- const Expression *_address;
- const Expression *_align;
- const Expression *_subAlign;
- const Expression *_at;
- const Expression *_fillExpr;
- StringRef _fillStream;
- bool _alignWithInput;
- bool _discard;
- Constraint _constraint;
- llvm::ArrayRef<const Command *> _outputSectionCommands;
- ArrayRef<StringRef> _phdrs;
-};
-
-/// Represents an Overlay structure as documented in
-/// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
-class Overlay : public Command {
-public:
- Overlay(Parser &ctx) : Command(ctx, Kind::Overlay) {}
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Overlay;
- }
-
- 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:
- typedef llvm::ArrayRef<const Command *>::const_iterator const_iterator;
-
- Sections(Parser &ctx,
- const SmallVectorImpl<const Command *> &sectionsCommands)
- : Command(ctx, Kind::Sections) {
- _sectionsCommands =
- save_array<const Command *>(getAllocator(), sectionsCommands);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Sections;
- }
-
- void dump(raw_ostream &os) const override;
- const_iterator begin() const { return _sectionsCommands.begin(); }
- const_iterator end() const { return _sectionsCommands.end(); }
-
-private:
- llvm::ArrayRef<const Command *> _sectionsCommands;
-};
-
-/// Represents a single memory block definition in a MEMORY {} command.
-class MemoryBlock {
-public:
- MemoryBlock(StringRef name, StringRef attr,
- const Expression *origin, const Expression *length)
- : _name(name), _attr(attr), _origin(origin), _length(length) {}
-
- void dump(raw_ostream &os) const;
-
-private:
- StringRef _name;
- StringRef _attr;
- const Expression *_origin;
- const Expression *_length;
-};
-
-/// Represents all the contents of the MEMORY {} command.
-class Memory : public Command {
-public:
- Memory(Parser &ctx,
- const SmallVectorImpl<const MemoryBlock *> &blocks)
- : Command(ctx, Kind::Memory) {
- _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Memory;
- }
-
- void dump(raw_ostream &os) const override;
-
-private:
- llvm::ArrayRef<const MemoryBlock *> _blocks;
-};
-
-/// Represents an extern command.
-class Extern : public Command {
-public:
- typedef llvm::ArrayRef<StringRef>::const_iterator const_iterator;
-
- Extern(Parser &ctx,
- const SmallVectorImpl<StringRef> &symbols)
- : Command(ctx, Kind::Extern) {
- _symbols = save_array<StringRef>(getAllocator(), symbols);
- }
-
- static bool classof(const Command *c) {
- return c->getKind() == Kind::Extern;
- }
-
- void dump(raw_ostream &os) const override;
- const_iterator begin() const { return _symbols.begin(); }
- const_iterator end() const { return _symbols.end(); }
-
-private:
- llvm::ArrayRef<StringRef> _symbols;
-};
-
-/// Stores the parse tree of a linker script.
-class LinkerScript {
-public:
- void dump(raw_ostream &os) const {
- for (const Command *c : _commands) {
- c->dump(os);
- if (isa<SymbolAssignment>(c))
- os << "\n";
- }
- }
-
- std::vector<const Command *> _commands;
-};
-
-/// Recognizes syntactic constructs of a linker script using a predictive
-/// parser/recursive descent implementation.
-///
-/// Based on the linker script documentation available at
-/// https://sourceware.org/binutils/docs/ld/Scripts.html
-class Parser {
-public:
- explicit Parser(std::unique_ptr<MemoryBuffer> mb)
- : _lex(std::move(mb)), _peekAvailable(false) {}
-
- /// Let's not allow copying of Parser class because it would be expensive
- /// to update all the AST pointers to a new buffer.
- Parser(const Parser &instance) = delete;
-
- /// Lex and parse the current memory buffer to create a linker script AST.
- std::error_code parse();
-
- /// Returns a reference to the top level node of the linker script AST.
- LinkerScript *get() { return &_script; }
-
- /// Returns a reference to the underlying allocator.
- llvm::BumpPtrAllocator &getAllocator() { return _alloc; }
-
-private:
- /// Advances to the next token, either asking the Lexer to lex the next token
- /// or obtaining it from the look ahead buffer.
- void consumeToken() {
- // First check if the look ahead buffer cached the next token
- if (_peekAvailable) {
- _tok = _bufferedToken;
- _peekAvailable = false;
- return;
- }
- _lex.lex(_tok);
- }
-
- /// Returns the token that succeeds the current one without consuming the
- /// current token. This operation will lex an additional token and store it in
- /// a private buffer.
- const Token &peek() {
- if (_peekAvailable)
- return _bufferedToken;
-
- _lex.lex(_bufferedToken);
- _peekAvailable = true;
- return _bufferedToken;
- }
-
- void error(const Token &tok, Twine msg) {
- _lex.getSourceMgr().PrintMessage(
- llvm::SMLoc::getFromPointer(tok._range.data()),
- llvm::SourceMgr::DK_Error, msg);
- }
-
- bool expectAndConsume(Token::Kind kind, Twine msg) {
- if (_tok._kind != kind) {
- error(_tok, msg);
- return false;
- }
- consumeToken();
- return true;
- }
-
- bool isNextToken(Token::Kind kind) { return (_tok._kind == kind); }
-
- // Recursive descent parsing member functions
- // All of these functions consumes tokens and return an AST object,
- // represented by the Command superclass. However, note that not all AST
- // objects derive from Command. For nodes of C-like expressions, used in
- // linker scripts, the superclass is Expression. For nodes that represent
- // input sections that map to an output section, the superclass is
- // InputSection.
- //
- // Example mapping common constructs to AST nodes:
- //
- // SECTIONS { /* Parsed to Sections class */
- // my_symbol = 1 + 1; /* Parsed to SymbolAssignment class */
- // /* ^~~> Parsed to Expression class */
- // .data : { *(.data) } /* Parsed to OutputSectionDescription class */
- // /* ^~~> Parsed to InputSectionName class */
- // /* ^~~~~> Parsed to InputSectionsCmd class */
- // }
-
- // ==== Expression parsing member functions ====
-
- /// Parse "identifier(param [, param]...)"
- ///
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 0x1000 | ALIGN(other_symbol);
- /// /* ^~~~> parseFunctionCall()
- /// }
- const Expression *parseFunctionCall();
-
- /// Ensures that the current token is an expression operand. If it is not,
- /// issues an error to the user and returns false.
- bool expectExprOperand();
-
- /// Parse operands of an expression, such as function calls, identifiers,
- /// literal numbers or unary operators.
- ///
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 0x1000 | ALIGN(other_symbol);
- /// ^~~~> parseExprTerminal()
- /// }
- const Expression *parseExprOperand();
-
- // As a reference to the precedence of C operators, consult
- // http://en.cppreference.com/w/c/language/operator_precedence
-
- /// Parse either a single expression operand and returns or parse an entire
- /// expression if its top-level node has a lower or equal precedence than the
- /// indicated.
- const Expression *parseExpression(unsigned precedence = 13);
-
- /// Parse an operator and its rhs operand, assuming that the lhs was already
- /// consumed. Keep parsing subsequent operator-operand pairs that do not
- /// exceed highestPrecedence.
- /// * lhs points to the left-hand-side operand of this operator
- /// * maxPrecedence has the maximum operator precedence level that this parse
- /// function is allowed to consume.
- const Expression *parseOperatorOperandLoop(const Expression *lhs,
- unsigned maxPrecedence);
-
- /// Parse ternary conditionals such as "(condition)? true: false;". This
- /// operator has precedence level 13 and associates right-to-left.
- const Expression *parseTernaryCondOp(const Expression *lhs);
-
- // ==== High-level commands parsing ====
-
- /// Parse the OUTPUT linker script command.
- /// Example:
- /// OUTPUT(/path/to/file)
- /// ^~~~> parseOutput()
- ///
- Output *parseOutput();
-
- /// Parse the OUTPUT_FORMAT linker script command.
- /// Example:
- ///
- /// OUTPUT_FORMAT(elf64-x86-64,elf64-x86-64,elf64-x86-64)
- /// ^~~~> parseOutputFormat()
- ///
- OutputFormat *parseOutputFormat();
-
- /// Parse the OUTPUT_ARCH linker script command.
- /// Example:
- ///
- /// OUTPUT_ARCH(i386:x86-64)
- /// ^~~~> parseOutputArch()
- ///
- OutputArch *parseOutputArch();
-
- /// Parse the INPUT or GROUP linker script command.
- /// Example:
- ///
- /// GROUP ( /lib/x86_64-linux-gnu/libc.so.6
- /// /usr/lib/x86_64-linux-gnu/libc_nonshared.a
- /// AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 )
- /// -lm -l:libgcc.a )
- ///
- template<class T> T *parsePathList();
- bool parseAsNeeded(SmallVectorImpl<Path> &paths);
-
- /// Parse the ENTRY linker script command.
- /// Example:
- ///
- /// ENTRY(init)
- /// ^~~~> parseEntry()
- ///
- Entry *parseEntry();
-
- /// Parse the SEARCH_DIR linker script command.
- /// Example:
- ///
- /// SEARCH_DIR("/usr/x86_64-linux-gnu/lib64");
- /// ^~~~> parseSearchDir()
- ///
- SearchDir *parseSearchDir();
-
- /// Parse "symbol = expression" commands that live inside the
- /// SECTIONS directive.
- /// Example:
- ///
- /// SECTIONS {
- /// my_symbol = 1 + 1;
- /// ^~~~> parseExpression()
- /// ^~~~ parseSymbolAssignment()
- /// }
- ///
- const SymbolAssignment *parseSymbolAssignment();
-
- /// Parse "EXCLUDE_FILE" used inside the listing of input section names.
- /// Example:
- ///
- /// SECTIONS {
- /// .data : { *(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors) }
- /// ^~~~> parseExcludeFile()
- /// }
- ///
- ErrorOr<InputSectionsCmd::VectorTy> parseExcludeFile();
-
- /// Helper to parse SORT_BY_NAME(, SORT_BY_ALIGNMENT( and SORT_NONE(,
- /// possibly nested. Returns the number of Token::r_paren tokens that need
- /// to be consumed, while sortMode is updated with the parsed sort
- /// criteria.
- /// Example:
- ///
- /// SORT_BY_NAME(SORT_BY_ALIGNMENT(*))
- /// ^~~~ parseSortDirectives() ~~^
- /// Returns 2, finishes with sortMode = WildcardSortMode::ByNameAndAlignment
- ///
- int parseSortDirectives(WildcardSortMode &sortMode);
-
- /// Parse a group of input section names that are sorted via SORT* directives.
- /// Example:
- /// SORT_BY_NAME(SORT_BY_ALIGNMENT(*data *bss))
- const InputSection *parseSortedInputSections();
-
- /// Parse input section description statements.
- /// Example:
- ///
- /// SECTIONS {
- /// .mysection : crt.o(.data* .bss SORT_BY_NAME(name*))
- /// ^~~~ parseInputSectionsCmd()
- /// }
- const InputSectionsCmd *parseInputSectionsCmd();
-
- const FillCmd *parseFillCmd();
-
- /// Parse output section description statements.
- /// Example:
- ///
- /// SECTIONS {
- /// .data : { crt.o(.data* .bss SORT_BY_NAME(name*)) }
- /// ^~~~ parseOutputSectionDescription()
- /// }
- const OutputSectionDescription *parseOutputSectionDescription();
-
- /// Stub for parsing overlay commands. Currently unimplemented.
- const Overlay *parseOverlay();
-
- const PHDR *parsePHDR();
-
- PHDRS *parsePHDRS();
-
- /// Parse the SECTIONS linker script command.
- /// Example:
- ///
- /// SECTIONS {
- /// ^~~~ parseSections()
- /// . = 0x100000;
- /// .data : { *(.data) }
- /// }
- ///
- Sections *parseSections();
-
- /// Parse the MEMORY linker script command.
- /// Example:
- ///
- /// MEMORY {
- /// ^~~~ parseMemory()
- /// ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
- /// rom (rx) : ORIGIN = 0x0, LENGTH = 256K
- /// }
- ///
- Memory *parseMemory();
-
- /// Parse the EXTERN linker script command.
- /// Example:
- ///
- /// EXTERN(symbol symbol ...)
- /// ^~~~> parseExtern()
- ///
- Extern *parseExtern();
-
-private:
- // Owns the entire linker script AST nodes
- llvm::BumpPtrAllocator _alloc;
-
- // The top-level/entry-point linker script AST node
- LinkerScript _script;
-
- Lexer _lex;
-
- // Current token being analyzed
- Token _tok;
-
- // Annotate whether we buffered the next token to allow peeking
- bool _peekAvailable;
- Token _bufferedToken;
-};
-
-/// script::Sema traverses all parsed linker script structures and populate
-/// internal data structures to be able to answer the following questions:
-///
-/// * According to the linker script, which input section goes first in the
-/// output file layout, input section A or input section B?
-///
-/// * What is the name of the output section that input section A should be
-/// mapped to?
-///
-/// * Which linker script expressions should be calculated before emitting
-/// a given section?
-///
-/// * How to evaluate a given linker script expression?
-///
-class Sema {
-public:
- /// From the linker script point of view, this class represents the minimum
- /// set of information to uniquely identify an input section.
- struct SectionKey {
- StringRef archivePath;
- StringRef memberPath;
- StringRef sectionName;
- };
-
- Sema();
-
- /// We can parse several linker scripts via command line whose ASTs are stored
- /// here via addLinkerScript().
- void addLinkerScript(std::unique_ptr<Parser> script) {
- _scripts.push_back(std::move(script));
- }
-
- const std::vector<std::unique_ptr<Parser>> &getLinkerScripts() {
- return _scripts;
- }
-
- /// 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.
- 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
- /// to handle.
- bool hasLayoutCommands() const { return _layoutCommands.size() > 0; }
-
- /// Return true if this section has a mapping rule in the linker script
- bool hasMapping(const SectionKey &key) const {
- return getLayoutOrder(key, true) >= 0;
- }
-
- /// Order function - used to sort input sections in the output file according
- /// to linker script custom mappings. Return true if lhs should appear before
- /// rhs.
- bool less(const SectionKey &lhs, const SectionKey &rhs) const;
-
- /// Retrieve the name of the output section that this input section is mapped
- /// to, according to custom linker script mappings.
- StringRef getOutputSection(const SectionKey &key) const;
-
- /// Retrieve all the linker script expressions that need to be evaluated
- /// before the given section is emitted. This is *not* const because the
- /// first section to retrieve a given set of expression is the only one to
- /// receive it. This set is marked as "delivered" and no other sections can
- /// retrieve this set again. If we don't do this, multiple sections may map
- /// to the same set of expressions because of wildcards rules.
- std::vector<const SymbolAssignment *> getExprs(const SectionKey &key);
-
- /// Evaluate a single linker script expression according to our current
- /// context (symbol table). This function is *not* constant because it can
- /// update our symbol table with new symbols calculated in this expression.
- std::error_code evalExpr(const SymbolAssignment *assgn, uint64_t &curPos);
-
- /// Retrieve the set of symbols defined in linker script expressions.
- const llvm::StringSet<> &getScriptDefinedSymbols() const;
-
- /// Queries the linker script symbol table for the value of a given symbol.
- /// This function must be called after linker script expressions evaluation
- /// 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:
- /// A custom hash operator to teach the STL how to handle our custom keys.
- /// This will be used in our hash table mapping Sections to a Layout Order
- /// number (caching results).
- struct SectionKeyHash {
- int64_t operator()(const SectionKey &k) const {
- return llvm::hash_combine(k.archivePath, k.memberPath, k.sectionName);
- }
- };
-
- /// Teach the STL when two section keys are the same. This will be used in
- /// our hash table mapping Sections to a Layout Order number (caching results)
- struct SectionKeyEq {
- bool operator()(const SectionKey &lhs, const SectionKey &rhs) const {
- return ((lhs.archivePath == rhs.archivePath) &&
- (lhs.memberPath == rhs.memberPath) &&
- (lhs.sectionName == rhs.sectionName));
- }
- };
-
- /// Given an order id, check if it matches the tuple
- /// <archivePath, memberPath, sectionName> and returns the
- /// internal id that matched, or -1 if no matches.
- int matchSectionName(int id, const SectionKey &key) const;
-
- /// Returns a number that will determine the order of this input section
- /// in the final layout. If coarse is true, we simply return the layour order
- /// of the higher-level node InputSectionsCmd, used to order input sections.
- /// If coarse is false, we return the layout index down to the internal
- /// InputSectionsCmd arrangement, used to get the set of preceding linker
- ///expressions.
- int getLayoutOrder(const SectionKey &key, bool coarse) const;
-
- /// Compare two sections that have the same mapping rule (i.e., are matched
- /// by the same InputSectionsCmd).
- /// Determine if lhs < rhs by analyzing the InputSectionsCmd structure.
- 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
- /// thus enforcing order among nodes (which comes first).
- ///
- /// The order among nodes is determined by their indexes in this vector
- /// (_layoutCommands). This index allows us to solve the problem of
- /// establishing the order among two different input sections: we match each
- /// input sections with their respective layout command and use the indexes
- /// of these commands to order these sections.
- ///
- /// Example:
- ///
- /// Given the linker script:
- /// SECTIONS {
- /// .text : { *(.text) }
- /// .data : { *(.data) }
- /// }
- ///
- /// The _layoutCommands vector should contain:
- /// id 0 : <OutputSectionDescription> (_sectionName = ".text")
- /// id 1 : <InputSectionsCmd> (_memberName = "*")
- /// id 2 : <InputSectionName> (_name = ".text)
- /// id 3 : <OutputSectionDescription> (_sectionName = ".data")
- /// id 4 : <InputSectionsCmd> (_memberName = "*")
- /// id 5 : <InputSectionName> (_name = ".data")
- ///
- /// If we need to sort the following input sections:
- ///
- /// input section A: .text from libc.a (member errno.o)
- /// input section B: .data from libc.a (member write.o)
- ///
- /// Then we match input section A with the InputSectionsCmd of id 1, and
- /// input section B with the InputSectionsCmd of id 4. Since 1 < 4, we
- /// put A before B.
- ///
- /// The second problem handled by the linearization of the AST is the task
- /// of finding all preceding expressions that need to be calculated before
- /// emitting a given section. This task is easier to deal with when all nodes
- /// are in a vector because otherwise we would need to traverse multiple
- /// levels of the AST to find the set of expressions that preceed a layout
- /// command.
- ///
- /// The linker script commands that are linearized ("layout commands") are:
- ///
- /// * OutputSectionDescription, containing an output section name
- /// * InputSectionsCmd, containing an input file name
- /// * InputSectionName, containing a single input section name
- /// * InputSectionSortedName, a group of input section names
- /// * SymbolAssignment, containing an expression that may
- /// change the address where the linker is outputting data
- ///
- void linearizeAST(const Sections *sections);
- void linearizeAST(const InputSectionsCmd *inputSections);
- void linearizeAST(const InputSection *inputSection);
-
- std::vector<std::unique_ptr<Parser>> _scripts;
- std::vector<const Command *> _layoutCommands;
- std::unordered_multimap<std::string, int> _memberToLayoutOrder;
- std::vector<std::pair<StringRef, int>> _memberNameWildcards;
- mutable std::unordered_map<SectionKey, int, SectionKeyHash, SectionKeyEq>
- _cacheSectionOrder, _cacheExpressionOrder;
- llvm::DenseSet<int> _deliveredExprs;
- mutable llvm::StringSet<> _definedSymbols;
-
- llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
- const PHDR *_programPHDR;
-
- Expression::SymbolTableTy _symbolTable;
-};
-
-llvm::BumpPtrAllocator &Command::getAllocator() const {
- return _ctx.getAllocator();
-}
-llvm::BumpPtrAllocator &Expression::getAllocator() const {
- return _ctx.getAllocator();
-}
-} // end namespace script
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/MachOLinkingContext.h b/include/lld/ReaderWriter/MachOLinkingContext.h
index dc44d3f303f8..7b673f0dad3e 100644
--- a/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -13,6 +13,7 @@
#include "lld/Core/LinkingContext.h"
#include "lld/Core/Reader.h"
#include "lld/Core/Writer.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -71,10 +72,21 @@ public:
dynamicLookup
};
+ enum ObjCConstraint {
+ objc_unknown = 0,
+ objc_supports_gc = 2,
+ objc_gc_only = 4,
+ // Image optimized by dyld = 8
+ // GC compaction = 16
+ objc_retainReleaseForSimulator = 32,
+ objc_retainRelease
+ };
+
/// 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.
- void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion);
+ void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
+ bool exportDynamicSymbols);
void addPasses(PassManager &pm) override;
bool validateImpl(raw_ostream &diagnostics) override;
@@ -82,6 +94,18 @@ public:
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ /// Creates a new file which is owned by the context. Returns a pointer to
+ /// the new file.
+ template <class T, class... Args>
+ typename std::enable_if<!std::is_array<T>::value, T *>::type
+ make_file(Args &&... args) const {
+ auto file = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ auto *filePtr = file.get();
+ auto *ctx = const_cast<MachOLinkingContext *>(this);
+ ctx->getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
+ return filePtr;
+ }
+
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
@@ -118,6 +142,8 @@ public:
void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
bool demangleSymbols() const { return _demangle; }
void setDemangleSymbols(bool d) { _demangle = d; }
+ bool mergeObjCCategories() const { return _mergeObjCCategories; }
+ void setMergeObjCCategories(bool v) { _mergeObjCCategories = v; }
/// Create file at specified path which will contain a binary encoding
/// of all input and output file paths.
std::error_code createDependencyFile(StringRef path);
@@ -136,6 +162,26 @@ public:
const StringRefVector &sysLibRoots() const { return _syslibRoots; }
bool PIE() const { return _pie; }
void setPIE(bool pie) { _pie = pie; }
+ bool generateVersionLoadCommand() const {
+ return _generateVersionLoadCommand;
+ }
+ void setGenerateVersionLoadCommand(bool v) {
+ _generateVersionLoadCommand = v;
+ }
+
+ bool generateFunctionStartsLoadCommand() const {
+ return _generateFunctionStartsLoadCommand;
+ }
+ void setGenerateFunctionStartsLoadCommand(bool v) {
+ _generateFunctionStartsLoadCommand = v;
+ }
+
+ bool generateDataInCodeLoadCommand() const {
+ return _generateDataInCodeLoadCommand;
+ }
+ void setGenerateDataInCodeLoadCommand(bool v) {
+ _generateDataInCodeLoadCommand = v;
+ }
uint64_t stackSize() const { return _stackSize; }
void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
@@ -143,6 +189,18 @@ public:
uint64_t baseAddress() const { return _baseAddress; }
void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
+ ObjCConstraint objcConstraint() const { return _objcConstraint; }
+
+ uint32_t osMinVersion() const { return _osMinVersion; }
+
+ uint32_t sdkVersion() const { return _sdkVersion; }
+ void setSdkVersion(uint64_t v) { _sdkVersion = v; }
+
+ uint64_t sourceVersion() const { return _sourceVersion; }
+ void setSourceVersion(uint64_t v) { _sourceVersion = v; }
+
+ uint32_t swiftVersion() const { return _swiftVersion; }
+
/// \brief Checks whether a given path on the filesystem exists.
///
/// When running in -test_file_usage mode, this method consults an
@@ -167,12 +225,12 @@ public:
/// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
/// that order, unless Foo ends in ".o", in which case only the exact file
/// matches (e.g. -lfoo.o would only find foo.o).
- ErrorOr<StringRef> searchDirForLibrary(StringRef path,
- StringRef libName) const;
+ llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
+ StringRef libName) const;
/// \brief Iterates through all search path entries looking for libName (as
/// specified by -lFoo).
- ErrorOr<StringRef> searchLibrary(StringRef libName) const;
+ llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
/// Add a framework search path. Internally, this method may be prepended
/// the path with syslibroot.
@@ -180,7 +238,7 @@ public:
/// \brief Iterates through all framework directories looking for
/// Foo.framework/Foo (when fwName = "Foo").
- ErrorOr<StringRef> findPathForFramework(StringRef fwName) const;
+ llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
/// \brief The dylib's binary compatibility version, in the raw uint32 format.
///
@@ -297,6 +355,9 @@ public:
/// Pass to add shims switching between thumb and arm mode.
bool needsShimPass() const;
+ /// Pass to add objc image info and optimized objc data.
+ bool needsObjCPass() const;
+
/// Magic symbol name stubs will need to help lazy bind.
StringRef binderSymbolName() const;
@@ -340,8 +401,14 @@ public:
/// bits are xxxx.yy.zz. Largest number is 65535.255.255
static bool parsePackedVersion(StringRef str, uint32_t &result);
+ /// Construct 64-bit value from string "A.B.C.D.E" where
+ /// bits are aaaa.bb.cc.dd.ee. Largest number is 16777215.1023.1023.1023.1023
+ static bool parsePackedVersion(StringRef str, uint64_t &result);
+
void finalizeInputFiles() override;
+ llvm::Error handleLoadedFile(File &file) override;
+
bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
bool &leftBeforeRight) const;
@@ -383,28 +450,36 @@ private:
StringRefVector _searchDirs;
StringRefVector _syslibRoots;
StringRefVector _frameworkDirs;
- HeaderFileType _outputMachOType; // e.g MH_EXECUTE
- bool _outputMachOTypeStatic; // Disambiguate static vs dynamic prog
- bool _doNothing; // for -help and -v which just print info
- bool _pie;
- Arch _arch;
- OS _os;
- uint32_t _osMinVersion;
- uint64_t _pageZeroSize;
- uint64_t _pageSize;
- uint64_t _baseAddress;
- uint64_t _stackSize;
- uint32_t _compatibilityVersion;
- uint32_t _currentVersion;
+ HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
+ bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
+ bool _doNothing = false; // for -help and -v which just print info
+ bool _pie = false;
+ Arch _arch = arch_unknown;
+ OS _os = OS::macOSX;
+ uint32_t _osMinVersion = 0;
+ uint32_t _sdkVersion = 0;
+ uint64_t _sourceVersion = 0;
+ uint64_t _pageZeroSize = 0;
+ uint64_t _pageSize = 4096;
+ uint64_t _baseAddress = 0;
+ uint64_t _stackSize = 0;
+ uint32_t _compatibilityVersion = 0;
+ uint32_t _currentVersion = 0;
+ ObjCConstraint _objcConstraint = objc_unknown;
+ uint32_t _swiftVersion = 0;
StringRef _installName;
StringRefVector _rpaths;
- bool _flatNamespace;
- UndefinedMode _undefinedMode;
- bool _deadStrippableDylib;
- bool _printAtoms;
- bool _testingFileUsage;
- bool _keepPrivateExterns;
- bool _demangle;
+ bool _flatNamespace = false;
+ UndefinedMode _undefinedMode = UndefinedMode::error;
+ bool _deadStrippableDylib = false;
+ bool _printAtoms = false;
+ bool _testingFileUsage = false;
+ bool _keepPrivateExterns = false;
+ bool _demangle = false;
+ bool _mergeObjCCategories = true;
+ bool _generateVersionLoadCommand = false;
+ bool _generateFunctionStartsLoadCommand = false;
+ bool _generateDataInCodeLoadCommand = false;
StringRef _bundleLoader;
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
mutable std::unique_ptr<Writer> _writer;
@@ -414,13 +489,13 @@ private:
mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
mutable std::mutex _dylibsMutex;
- ExportMode _exportMode;
+ ExportMode _exportMode = ExportMode::globals;
llvm::StringSet<> _exportedSymbols;
- DebugInfoMode _debugInfoMode;
+ DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
- unsigned _orderFileEntries;
- File *_flatNamespaceFile;
+ unsigned _orderFileEntries = 0;
+ File *_flatNamespaceFile = nullptr;
mach_o::SectCreateFile *_sectCreateFile = nullptr;
};