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