diff options
52 files changed, 458 insertions, 1703 deletions
diff --git a/lld/include/lld/Core/LinkerOptions.h b/lld/include/lld/Core/LinkerOptions.h index 59406ae0f56..72aafcf838e 100644 --- a/lld/include/lld/Core/LinkerOptions.h +++ b/lld/include/lld/Core/LinkerOptions.h @@ -121,6 +121,11 @@ enum OutputKind { Executable, Relocatable, Shared, + SharedStubs, + Core, + DebugSymbols, + Bundle, + Preload, }; struct LinkerOptions { diff --git a/lld/include/lld/Core/Pass.h b/lld/include/lld/Core/Pass.h index 651a565bb19..7458d49de59 100644 --- a/lld/include/lld/Core/Pass.h +++ b/lld/include/lld/Core/Pass.h @@ -61,7 +61,7 @@ public: /// Returns whether the Reference kind is for a call site. The pass /// uses this to find calls that need to be indirected through a stub. - virtual bool isCallSite(Reference::Kind) = 0; + virtual bool isCallSite(int32_t) = 0; /// Returns a file format specific atom for a stub/PLT entry which contains /// instructions which jump to the specified atom. May be called multiple @@ -96,7 +96,7 @@ public: /// Returns whether the Reference kind is a pre-instantiated GOT access. /// The default implementation of perform() uses this to figure out /// what GOT entries to instantiate. - virtual bool isGOTAccess(Reference::Kind, bool &canBypassGOT) = 0; + virtual bool isGOTAccess(int32_t, bool &canBypassGOT) = 0; /// The file format Writer needs to alter the reference kind from a /// pre-instantiated GOT access to an actual access. If targetIsNowGOT is diff --git a/lld/include/lld/Core/TargetInfo.h b/lld/include/lld/Core/TargetInfo.h index d181d60bdba..6be71fc5a75 100644 --- a/lld/include/lld/Core/TargetInfo.h +++ b/lld/include/lld/Core/TargetInfo.h @@ -56,14 +56,14 @@ public: virtual GOTPass *getGOTPass() const { return nullptr; } // TODO: Split out to TargetRelocationInfo. - virtual ErrorOr<uint32_t> relocKindFromString(StringRef str) const { - uint32_t val; + virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const { + int32_t val; if (str.getAsInteger(10, val)) return llvm::make_error_code(llvm::errc::invalid_argument); return val; } - virtual ErrorOr<std::string> stringFromRelocKind(uint32_t kind) const { + virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const { std::string s; llvm::raw_string_ostream str(s); str << kind; diff --git a/lld/include/lld/Driver/Target.h b/lld/include/lld/Driver/Target.h index 65defd632a4..b30d70709e9 100644 --- a/lld/include/lld/Driver/Target.h +++ b/lld/include/lld/Driver/Target.h @@ -17,17 +17,29 @@ #ifndef LLD_DRIVER_TARGET_H #define LLD_DRIVER_TARGET_H -#include "lld/Core/LinkerOptions.h" -#include "lld/ReaderWriter/Reader.h" -#include "lld/ReaderWriter/Writer.h" +#include "lld/Core/TargetInfo.h" + +#include "llvm/Support/ErrorOr.h" + +#include <memory> namespace lld { +class LinkerInput; +struct LinkerOptions; +class Reader; +class TargetInfo; +class Writer; + /// \brief Represents a specific target. class Target { +protected: + Target(std::unique_ptr<TargetInfo> ti) : _targetInfo(std::move(ti)) {} + public: - Target(const LinkerOptions &lo) : _options(lo) {} virtual ~Target(); + const TargetInfo &getTargetInfo() const { return *_targetInfo; }; + /// \brief Get a reference to a Reader for the given input. /// /// Will always return the same object for the same input. @@ -39,7 +51,7 @@ public: static std::unique_ptr<Target> create(const LinkerOptions&); protected: - const LinkerOptions &_options; + std::unique_ptr<TargetInfo> _targetInfo; }; } diff --git a/lld/include/lld/ReaderWriter/MachOTargetInfo.h b/lld/include/lld/ReaderWriter/MachOTargetInfo.h index aaa06fa5aa2..9055316f269 100644 --- a/lld/include/lld/ReaderWriter/MachOTargetInfo.h +++ b/lld/include/lld/ReaderWriter/MachOTargetInfo.h @@ -23,6 +23,9 @@ public: uint32_t getCPUType() const; uint32_t getCPUSubType() const; + bool addEntryPointLoadCommand() const; + bool addUnixThreadLoadCommand() const; + virtual uint64_t getPageZeroSize() const = 0; static std::unique_ptr<MachOTargetInfo> create(const LinkerOptions &lo); diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h index 8f590bc333b..c1f6084345d 100644 --- a/lld/include/lld/ReaderWriter/Reader.h +++ b/lld/include/lld/ReaderWriter/Reader.h @@ -1,4 +1,4 @@ -//===- ReaderWriter/Reader.h - Abstract File Format Reading Interface -----===// +//===- lld/ReaderWriter/Reader.h - Abstract File Format Reading Interface -===// // // The LLVM Linker // @@ -7,68 +7,60 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_READERWRITER_READER_H_ -#define LLD_READERWRITER_READER_H_ +#ifndef LLD_READERWRITER_READER_H +#define LLD_READERWRITER_READER_H #include "lld/Core/LLVM.h" +#include "lld/Core/TargetInfo.h" + +#include <functional> #include <memory> #include <vector> namespace lld { class File; +class LinkerInput; +struct LinkerOptions; +/// \brief An abstract class for reading object files, library files, and +/// executable files. /// -/// The Reader is 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 subclass -/// of Reader. -/// +/// Each file format (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete +/// subclass of Reader. class Reader { public: virtual ~Reader(); - - /// Parse a file given its file system path and create a File object. + /// \brief Parse a file given its file system path and create a File object. virtual error_code readFile(StringRef path, std::vector<std::unique_ptr<File>> &result); - /// Parse a supplied buffer (already filled with the contents of a file) - /// and create a File object. - /// On success, the resulting File object takes ownership of - /// the MemoryBuffer. + /// \brief Parse a supplied buffer (already filled with the contents of a + /// file) and create a File object. + /// + /// On success, the resulting File object takes ownership of the MemoryBuffer. virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<std::unique_ptr<File>> &result) = 0; protected: // only concrete subclasses can be instantiated - Reader(); -}; - - - -/// -/// The ReaderOptions encapsulates the options used by all Readers. -/// Each file format defines a subclass of ReaderOptions -/// to hold file format specific options. The option objects are the only -/// way to control the behaviour of Readers. -/// -class ReaderOptions { -public: - // Any options common to all file format Readers will go here. + Reader(const TargetInfo &ti) + : _targetInfo(ti), _options(ti.getLinkerOptions()) {} -protected: - // only concrete subclasses can be instantiated - ReaderOptions(); + const TargetInfo &_targetInfo; + const LinkerOptions &_options; }; +typedef ErrorOr<Reader&> ReaderFunc(const LinkerInput &); +std::unique_ptr<Reader> createReaderELF(const TargetInfo &, + std::function<ReaderFunc>); +std::unique_ptr<Reader> createReaderMachO(const TargetInfo &, + std::function<ReaderFunc>); +std::unique_ptr<Reader> createReaderNative(const TargetInfo &); +std::unique_ptr<Reader> createReaderPECOFF(const TargetInfo &, + std::function<ReaderFunc>); +std::unique_ptr<Reader> createReaderYAML(const TargetInfo &); +} // end namespace lld - - -} // namespace lld - -#endif // LLD_READERWRITER_READER_H_ - - - - +#endif diff --git a/lld/include/lld/ReaderWriter/ReaderArchive.h b/lld/include/lld/ReaderWriter/ReaderArchive.h index bf98d844429..3f1b0dc9da7 100644 --- a/lld/include/lld/ReaderWriter/ReaderArchive.h +++ b/lld/include/lld/ReaderWriter/ReaderArchive.h @@ -1,66 +1,38 @@ -//===- ReaderWriter/ReaderArchive.h - Archive Library Reader ------------===// +//===- lld/ReaderWriter/ReaderArchive.h - Archive Library Reader ----------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // -//===--------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #ifndef LLD_READER_ARCHIVE_H #define LLD_READER_ARCHIVE_H -#include "lld/Core/ArchiveLibraryFile.h" -#include "lld/Core/File.h" #include "lld/Core/LLVM.h" #include "lld/ReaderWriter/Reader.h" -#include "lld/ReaderWriter/ReaderArchive.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Object/Archive.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/system_error.h" +#include <functional> #include <memory> #include <vector> namespace lld { - -/// \brief The ReaderOptionsArchive encapsulates the options used by the -/// ReaderArchive. The option objects are the only way to control the -/// behaviour of Readers. -class ReaderOptionsArchive { -public: - ReaderOptionsArchive(bool isForceLoad = false) - : _isForceLoad(isForceLoad) - , _reader(nullptr) - { } - - bool isForceLoad() const { - return _isForceLoad; - } - - Reader *reader() const { - return _reader; - } - - void setReader(Reader *r) { - _reader = r; - } - -private: - bool _isForceLoad; - Reader *_reader; -}; +class File; +class LinkerInput; +class TargetInfo; /// \brief ReaderArchive is a class for reading archive libraries class ReaderArchive : public Reader { public: - ReaderArchive(const ReaderOptionsArchive &options) - : _options(options) - { } + ReaderArchive(const TargetInfo &ti, + std::function<ErrorOr<Reader&> (const LinkerInput &)> getReader) + : Reader(ti), + _getReader(getReader) {} /// \brief Returns a vector of Files that are contained in the archive file /// pointed to by the Memorybuffer @@ -68,10 +40,9 @@ public: std::vector<std::unique_ptr<File>> &result); private: - const ReaderOptionsArchive &_options; + std::function<ErrorOr<Reader&> (const LinkerInput &)> _getReader; std::unique_ptr<llvm::object::Archive> _archive; }; +} // end namespace lld -} // namespace lld - -#endif // LLD_READER_ARCHIVE_H +#endif diff --git a/lld/include/lld/ReaderWriter/ReaderELF.h b/lld/include/lld/ReaderWriter/ReaderELF.h deleted file mode 100644 index 93434ddf84a..00000000000 --- a/lld/include/lld/ReaderWriter/ReaderELF.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- ReaderWriter/ReaderELF.h - ELF File Format Reading Interface -------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_READER_ELF_H_ -#define LLD_READERWRITER_READER_ELF_H_ - -#include "lld/ReaderWriter/Reader.h" -#include "lld/ReaderWriter/ReaderArchive.h" -#include "lld/Core/LLVM.h" - - -namespace lld { - -/// -/// The ReaderOptionsELF class encapsulates options needed -/// to process mach-o files. You can create an ReaderOptionsELF -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class ReaderOptionsELF : public ReaderOptions { -public: - virtual ~ReaderOptionsELF(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - ReaderOptionsELF(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - ReaderOptionsELF(); - - - -protected: -}; - - - - -/// -/// The only way to instantiate a ReaderELF object -/// is via this createReaderELF function. The is no public -/// ReaderELF class that you might be tempted to subclass. -/// Support for all variants must be represented in the ReaderOptionsELF -/// object. -/// The Reader object created retains a reference to the -/// ReaderOptionsELF object supplied, so the objects object must not be -/// destroyed before the Reader object. -/// -Reader* createReaderELF(const ReaderOptionsELF &options, - ReaderOptionsArchive &optionsArchive); - - - -} // namespace lld - -#endif // LLD_READERWRITER_READER_ELF_H_ diff --git a/lld/include/lld/ReaderWriter/ReaderMachO.h b/lld/include/lld/ReaderWriter/ReaderMachO.h deleted file mode 100644 index 669a199b7ab..00000000000 --- a/lld/include/lld/ReaderWriter/ReaderMachO.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- ReaderWriter/ReaderMachO.h - MachO File Format Reading Interface ---===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READER_WRITER_READER_MACHO_H_ -#define LLD_READER_WRITER_READER_MACHO_H_ - -#include "lld/ReaderWriter/Reader.h" -#include "lld/Core/LLVM.h" -#include "llvm/ADT/StringRef.h" - - -namespace lld { - -/// -/// The ReaderOptionsMachO class encapsulates options needed -/// to process mach-o files. You can create an ReaderOptionsMachO -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class ReaderOptionsMachO : public ReaderOptions { -public: - virtual ~ReaderOptionsMachO() { } - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - ReaderOptionsMachO(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - ReaderOptionsMachO(); - - - StringRef archName() const { return _archName; } - -protected: - StringRef _archName; -}; - - - - -/// -/// The only way to instantiate a ReaderMachO object -/// is via this createReaderMachO function. The is no public -/// ReaderMachO class that you might be tempted to subclass. -/// Support for all variants must be represented in the ReaderOptionsMachO -/// object. -/// The Reader object created retains a reference to the -/// ReaderOptionsMachO object supplied, so the objects object must not be -/// destroyed before the Reader object. -/// -Reader* createReaderMachO(const ReaderOptionsMachO &options); - - - -} // namespace lld - -#endif // LLD_READER_WRITER_READER_MACHO_H_ diff --git a/lld/include/lld/ReaderWriter/ReaderNative.h b/lld/include/lld/ReaderWriter/ReaderNative.h deleted file mode 100644 index 21f4415536d..00000000000 --- a/lld/include/lld/ReaderWriter/ReaderNative.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- ReaderWriter/ReaderNative.h - Native File Format Reading Interface ---===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_READER_NATIVE_H_ -#define LLD_READERWRITER_READER_NATIVE_H_ - -#include "lld/ReaderWriter/Reader.h" -#include "lld/Core/LLVM.h" - - -namespace lld { - -/// -/// The ReaderOptionsNative class encapsulates options needed -/// to process mach-o files. You can create an ReaderOptionsNative -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class ReaderOptionsNative : public ReaderOptions { -public: - virtual ~ReaderOptionsNative(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - ReaderOptionsNative(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - ReaderOptionsNative(); - -protected: -}; - - - - -/// -/// The only way to instantiate a ReaderNative object -/// is via this createReaderNative function. The is no public -/// ReaderNative class that you might be tempted to subclass. -/// Support for all variants must be represented in the ReaderOptionsNative -/// object. -/// The Reader object created retains a reference to the -/// ReaderOptionsNative object supplied, so the objects object must not be -/// destroyed before the Reader object. -/// -Reader* createReaderNative(const ReaderOptionsNative &options); - - - -} // namespace lld - -#endif // LLD_READERWRITER_READER_NATIVE_H_ diff --git a/lld/include/lld/ReaderWriter/ReaderPECOFF.h b/lld/include/lld/ReaderWriter/ReaderPECOFF.h deleted file mode 100644 index cb1dc375491..00000000000 --- a/lld/include/lld/ReaderWriter/ReaderPECOFF.h +++ /dev/null @@ -1,64 +0,0 @@ -//===- ReaderWriter/ReaderPECOFF.h - PECOFF File Format Reading Interface ---===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_READER_PECOFF_H_ -#define LLD_READERWRITER_READER_PECOFF_H_ - -#include "lld/ReaderWriter/Reader.h" -#include "lld/Core/LLVM.h" - - -namespace lld { - -/// -/// The ReaderOptionsPECOFF class encapsulates options needed -/// to process mach-o files. You can create an ReaderOptionsPECOFF -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class ReaderOptionsPECOFF : public ReaderOptions { -public: - virtual ~ReaderOptionsPECOFF(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - ReaderOptionsPECOFF(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - ReaderOptionsPECOFF(); - - -protected: -}; - - - - -/// -/// The only way to instantiate a ReaderPECOFF object -/// is via this createReaderPECOFF function. The is no public -/// ReaderPECOFF class that you might be tempted to subclass. -/// Support for all variants must be represented in the ReaderOptionsPECOFF -/// object. -/// The Reader object created retains a reference to the -/// ReaderOptionsPECOFF object supplied, so the objects object must not be -/// destroyed before the Reader object. -/// -Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options); - - - -} // namespace lld - -#endif // LLD_READERWRITER_READER_PECOFF_H_ diff --git a/lld/include/lld/ReaderWriter/ReaderYAML.h b/lld/include/lld/ReaderWriter/ReaderYAML.h deleted file mode 100644 index c49711f5b7b..00000000000 --- a/lld/include/lld/ReaderWriter/ReaderYAML.h +++ /dev/null @@ -1,73 +0,0 @@ -//===- ReaderWriter/ReaderYAML.h - YAML File Format Reading Interface -----===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_READER_YAML_H_ -#define LLD_READERWRITER_READER_YAML_H_ - -#include "lld/ReaderWriter/Reader.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Reference.h" -#include "llvm/ADT/StringRef.h" - - -namespace lld { - -/// -/// The ReaderOptionsYAML class encapsulates options needed -/// to process mach-o files. You can create an ReaderOptionsYAML -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class ReaderOptionsYAML : public ReaderOptions { -public: - virtual ~ReaderOptionsYAML(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - ReaderOptionsYAML(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - ReaderOptionsYAML(); - - - /// Converts a reference kind string to a in-memory numeric value. - /// Used when parsing YAML encoded object files. - virtual Reference::Kind kindFromString(StringRef) const = 0; - - -protected: -}; - - - - -/// -/// The only way to instantiate a ReaderYAML object -/// is via this createReaderYAML function. The is no public -/// ReaderYAML class that you might be tempted to subclass. -/// Support for all variants must be represented in the ReaderOptionsYAML -/// object. -/// The Reader object created retains a reference to the -/// ReaderOptionsYAML object supplied, so the objects object must not be -/// destroyed before the Reader object. -/// -Reader* createReaderYAML(const ReaderOptionsYAML &options); - - - -} // namespace lld - -#endif // LLD_READERWRITER_READER_YAML_H_ - - diff --git a/lld/include/lld/ReaderWriter/Writer.h b/lld/include/lld/ReaderWriter/Writer.h index 7165fb6abde..bfae628657c 100644 --- a/lld/include/lld/ReaderWriter/Writer.h +++ b/lld/include/lld/ReaderWriter/Writer.h @@ -1,4 +1,4 @@ -//===- ReaderWriter/Writer.h - Abstract File Format Interface -------===// +//===- lld/ReaderWriter/Writer.h - Abstract File Format Interface ---------===// // // The LLVM Linker // @@ -7,80 +7,57 @@ // //===----------------------------------------------------------------------===// -#ifndef LLD_READERWRITER_WRITER_H_ -#define LLD_READERWRITER_WRITER_H_ +#ifndef LLD_READERWRITER_WRITER_H +#define LLD_READERWRITER_WRITER_H #include "lld/Core/LLVM.h" + #include <memory> -#include <vector> namespace lld { +class ELFTargetInfo; class File; +class GOTPass; class InputFiles; +class MachOTargetInfo; class StubsPass; -class GOTPass; +class TargetInfo; - -/// -/// 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. -/// +/// \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. class Writer { public: virtual ~Writer(); - /// Write a file from the supplied File object - virtual error_code writeFile(const lld::File &linkedFile, StringRef path) = 0; + /// \brief Write a file from the supplied File object + virtual error_code writeFile(const File &linkedFile, StringRef path) = 0; - /// Return a Pass object for creating stubs/PLT entries + /// \brief Return a Pass object for creating stubs/PLT entries virtual StubsPass *stubPass() { return nullptr; } - /// Return a Pass object for creating GOT entries + /// \brief Return a Pass object for creating GOT entries virtual GOTPass *gotPass() { return nullptr; } - /// This method is called by Core Linking to give the Writer a chance to - /// add file format specific "files" to set of files to be linked. - /// This is how file format specific atoms can be added to the link. - virtual void addFiles(InputFiles&) { - } - + /// \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 void addFiles(InputFiles&) {} protected: // only concrete subclasses can be instantiated Writer(); }; +std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &); +std::unique_ptr<Writer> createWriterMachO(const MachOTargetInfo &); +std::unique_ptr<Writer> createWriterNative(const TargetInfo &); +std::unique_ptr<Writer> createWriterPECOFF(const TargetInfo &); +std::unique_ptr<Writer> createWriterYAML(const TargetInfo &); +} // end namespace lld - -/// -/// The WriterOptions encapsulates the options used by Writers. -/// Each file format defines a subclass of WriterOptions -/// to hold file format specific options. The option objects are the only -/// way to control the behaviour of Writers. -/// -class WriterOptions { -public: - // Any options common to all file formats will go here. - -protected: - // only concrete subclasses can be instantiated - WriterOptions(); -}; - - - - - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_H_ - - - - +#endif diff --git a/lld/include/lld/ReaderWriter/WriterELF.h b/lld/include/lld/ReaderWriter/WriterELF.h deleted file mode 100644 index cb60a1bcc0b..00000000000 --- a/lld/include/lld/ReaderWriter/WriterELF.h +++ /dev/null @@ -1,94 +0,0 @@ -//===- ReaderWriter/WriterELF.h - ELF File Format Writing Interface -------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_WRITER_ELF_H_ -#define LLD_READERWRITER_WRITER_ELF_H_ - -#include "lld/ReaderWriter/Writer.h" - -#include "lld/Core/LLVM.h" - -#include "llvm/Support/ELF.h" -#include "llvm/Support/Endian.h" - -namespace lld { - -/// \brief The WriterOptionsELF class encapsulates options needed to process ELF -/// files. -/// -/// You can create an WriterOptionsELF instance from command line arguments or -/// by subclassing and setting the instance variables in the subclass's -/// constructor. -class WriterOptionsELF { -public: - WriterOptionsELF() - : _is64Bit(false) - , _endianness(llvm::support::little) - , _type(llvm::ELF::ET_EXEC) - , _pointerWidth(4) - , _machine(llvm::ELF::EM_386) - , _baseAddress(0x400000) - , _pageSize(0x1000) - , _entryPoint("start") {} - - /// \brief Create a specific instance of an architecture. - /// - /// \param[in] Is64Bit Is this a ELF64 file or ELF32 file. - /// \param[in] Endianness Is this an ELFDATA2LSB or ELFDATA2MSB file. - /// \param[in] Type The e_type of the file. (Relocatable, Executable, etc...). - /// \param[in] Machine The e_machine of the file. (EM_386, EM_X86_86, etc...). - WriterOptionsELF(const bool Is64Bit, - const llvm::support::endianness endian, - const uint16_t Type, - const uint16_t Machine, - uint64_t pointerWidth = 4, - uint64_t baseAddress = 0, - uint64_t pageSize = 0x1000) - : _is64Bit(Is64Bit) - , _endianness(endian) - , _type(Type) - , _pointerWidth(pointerWidth) - , _machine(Machine) - , _baseAddress(baseAddress) - , _pageSize(pageSize) - , _entryPoint("start") {} - - bool is64Bit() const { return _is64Bit; } - llvm::support::endianness endianness() const { return _endianness; } - uint16_t type() const { return _type; } - uint16_t machine() const { return _machine; } - uint16_t pointerWidth() const { return _pointerWidth; } - uint64_t baseAddress() const { return _baseAddress; } - uint64_t pageSize() const { return _pageSize; } - void setEntryPoint(StringRef name) { _entryPoint = name; } - - /// \brief Get the entry point if type() is ET_EXEC. Empty otherwise. - StringRef entryPoint() const; - -protected: - bool _is64Bit; - llvm::support::endianness _endianness; - uint16_t _type; - uint16_t _pointerWidth; - uint16_t _machine; - uint64_t _baseAddress; - uint64_t _pageSize; - StringRef _entryPoint; -}; - -/// \brief Create a WriterELF using the given options. -/// -/// The only way to instantiate a WriterELF object is via this function. The -/// Writer object created retains a reference to the WriterOptionsELF object -/// supplied, so it must not be destroyed before the Writer object. -Writer *createWriterELF(const WriterOptionsELF &Options); - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_ELF_H_ diff --git a/lld/include/lld/ReaderWriter/WriterMachO.h b/lld/include/lld/ReaderWriter/WriterMachO.h deleted file mode 100644 index 49a7232a4b9..00000000000 --- a/lld/include/lld/ReaderWriter/WriterMachO.h +++ /dev/null @@ -1,111 +0,0 @@ -//===- ReaderWriter/WriterMachO.h - MachO File Format Reading Interface ---===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_WRITER_MACHO_H_ -#define LLD_READERWRITER_WRITER_MACHO_H_ - -#include "lld/ReaderWriter/Writer.h" -#include "lld/Core/LLVM.h" -#include "llvm/ADT/StringRef.h" - - -namespace lld { - -/// -/// The WriterOptionsMachO class encapsulates options needed -/// to process mach-o files. You can create an WriterOptionsMachO -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class WriterOptionsMachO : public WriterOptions { -public: - virtual ~WriterOptionsMachO(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - WriterOptionsMachO(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - WriterOptionsMachO(); - - - - enum OutputKind { - outputDynamicExecutable, - outputDylib, - outputBundle, - outputObjectFile - }; - - enum Architecture { - arch_x86_64, - arch_x86, - arch_armv6, - arch_armv7, - }; - - OutputKind outputKind() const { return _outputkind; } - Architecture architecture() const { return _architecture; } - StringRef archName() const; - uint32_t cpuType() const; - uint32_t cpuSubtype() const; - uint64_t pageZeroSize() const; - bool noTextRelocations() const { return _noTextRelocations; } - bool addEntryPointLoadCommand() const; - bool addUnixThreadLoadCommand() const; - StringRef entryPointName() const; - -protected: - OutputKind _outputkind; - Architecture _architecture; - uint64_t _pageZeroSize; - bool _noTextRelocations; - StringRef _customEntryPointName; -}; - - - - -/// -/// The only way to instantiate a WriterMachO object -/// is via this createWriterMachO function. The is no public -/// WriterMachO class that you might be tempted to subclass. -/// Support for all variants must be represented in the -/// WriterOptionsMachO object. -/// The Writer object created retains a reference to the -/// WriterOptionsMachO object supplied, so it must not be destroyed -/// before the Writer object. -/// -Writer* createWriterMachO(const WriterOptionsMachO &options); - - -/// -/// Returns an options object that can be used with the -/// WriterYAML to write mach-o object files as YAML. -/// -const class WriterOptionsYAML& writerOptionsMachOAsYAML(); - - -/// -/// Returns an options object that can be used with the -/// ReaderYAML to reader YAML encoded mach-o files. -/// -const class ReaderOptionsYAML& readerOptionsMachOAsYAML(); - - - - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_MACHO_H_ diff --git a/lld/include/lld/ReaderWriter/WriterNative.h b/lld/include/lld/ReaderWriter/WriterNative.h deleted file mode 100644 index fdc99cf28a5..00000000000 --- a/lld/include/lld/ReaderWriter/WriterNative.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- ReaderWriter/WriterNative.h - Native File Format Reading Interface ---===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_WRITER_NATIVE_H_ -#define LLD_READERWRITER_WRITER_NATIVE_H_ - -#include "lld/ReaderWriter/Writer.h" -#include "lld/Core/LLVM.h" - - -namespace lld { - -/// -/// The WriterOptionsNative class encapsulates options needed -/// to process mach-o files. You can create an WriterOptionsNative -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class WriterOptionsNative : public WriterOptions { -public: - virtual ~WriterOptionsNative(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - WriterOptionsNative(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - WriterOptionsNative(); - -protected: -}; - - - - -/// -/// The only way to instantiate a WriterNative object -/// is via this createWriterNative function. The is no public -/// WriterNative class that you might be tempted to subclass. -/// Support for all variants must be represented in the WriterOptionsNative -/// object. -/// The Writer object created retains a reference to the -/// WriterOptionsNative object supplied, so it must not be destroyed -/// before the Writer object. -/// -Writer* createWriterNative(const WriterOptionsNative &options); - - - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_NATIVE_H_ diff --git a/lld/include/lld/ReaderWriter/WriterPECOFF.h b/lld/include/lld/ReaderWriter/WriterPECOFF.h deleted file mode 100644 index 740190729e0..00000000000 --- a/lld/include/lld/ReaderWriter/WriterPECOFF.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- ReaderWriter/WriterPECOFF.h - PECOFF File Format Writing Interface -===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_WRITER_PECOFF_H_ -#define LLD_READERWRITER_WRITER_PECOFF_H_ - -#include "lld/ReaderWriter/Writer.h" -#include "lld/Core/LLVM.h" -#include "llvm/ADT/StringRef.h" - - -namespace lld { - -/// -/// The WriterOptionsPECOFF class encapsulates options needed -/// to process mach-o files. You can create an WriterOptionsPECOFF -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class WriterOptionsPECOFF : public WriterOptions { -public: - virtual ~WriterOptionsPECOFF(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - WriterOptionsPECOFF(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - WriterOptionsPECOFF(); - -protected: -}; - - - -/// -/// The only way to instantiate a WriterPECOFF object -/// is via this createWriterPECOFF function. The is no public -/// WriterPECOFF class that you might be tempted to subclass. -/// Support for all variants must be represented in the WriterOptionsPECOFF -/// object. -/// The Writer object created retains a reference to the -/// WriterOptionsPECOFF object supplied, so it must not be destroyed -/// before the Writer object. -/// -Writer* createWriterPECOFF(const WriterOptionsPECOFF &options); - - - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_PECOFF_H_ diff --git a/lld/include/lld/ReaderWriter/WriterYAML.h b/lld/include/lld/ReaderWriter/WriterYAML.h deleted file mode 100644 index 26dfbb852c5..00000000000 --- a/lld/include/lld/ReaderWriter/WriterYAML.h +++ /dev/null @@ -1,82 +0,0 @@ -//===- ReaderWriter/WriterYAML.h - YAML File Format Writing Interface -----===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READERWRITER_WRITER_YAML_H_ -#define LLD_READERWRITER_WRITER_YAML_H_ - -#include "lld/ReaderWriter/Writer.h" - -#include "lld/Core/LLVM.h" -#include "lld/Core/Reference.h" -#include "lld/Core/Pass.h" - -#include "llvm/ADT/StringRef.h" - - -namespace lld { - -/// -/// The WriterOptionsYAML class encapsulates options needed -/// to process mach-o files. You can create an WriterOptionsYAML -/// instance from command line arguments or by subclassing and setting the -/// instance variables in the subclass's constructor. -/// -class WriterOptionsYAML : public WriterOptions { -public: - virtual ~WriterOptionsYAML(); - - /// - /// Creates a Options object from darwin linker command line arguments. - /// FIXME: to be replaced with new option processing mechanism. - /// - WriterOptionsYAML(int argc, const char* argv[]); - - /// - /// Creates a Options object with default settings. For use when - /// programmatically constructing options. - /// - WriterOptionsYAML(); - - - /// Converts an in-memory reference kind value to a string. - /// Used when writing YAML encoded object files. - virtual StringRef kindToString(Reference::Kind) const = 0; - - - /// Enable Stubs pass to be run - virtual StubsPass *stubPass() const { - return nullptr; - } - - /// Enable GOT pass to be run - virtual GOTPass *gotPass() const { - return nullptr; - } - -}; - - - - -/// -/// The only way to instantiate a WriterYAML object -/// is via this createWriterYAML function. The is no public -/// WriterYAML class that you might be tempted to subclass. -/// Support for all variants must be represented in the WriterOptionsYAML -/// object. -/// The Writer object created retains a reference to the -/// WriterOptionsYAML object supplied, so it must not be destroyed -/// before the Writer object. -/// -Writer* createWriterYAML(const WriterOptionsYAML &options); - - -} // namespace lld - -#endif // LLD_READERWRITER_WRITER_YAML_H_ diff --git a/lld/lib/Driver/Drivers.cpp b/lld/lib/Driver/Drivers.cpp index 2063878495d..d6c29ca175e 100644 --- a/lld/lib/Driver/Drivers.cpp +++ b/lld/lib/Driver/Drivers.cpp @@ -228,7 +228,8 @@ LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) { ret._target = llvm::Triple::normalize(args.getLastArgValue(core::OPT_target)); ret._outputPath = args.getLastArgValue(core::OPT_output); ret._entrySymbol = args.getLastArgValue(core::OPT_entry); - ret._relocatable = args.hasArg(core::OPT_relocatable); + if (args.hasArg(core::OPT_relocatable)) + ret._outputKind = OutputKind::Relocatable; ret._outputCommands = args.hasArg(core::OPT_OCTOTHORPE_OCTOTHORPE_OCTOTHORPE); ret._outputYAML = args.hasArg(core::OPT_emit_yaml); ret._noInhibitExec = args.hasArg(core::OPT_noinhibit_exec); diff --git a/lld/lib/Driver/LinkerInvocation.cpp b/lld/lib/Driver/LinkerInvocation.cpp index 268a3ce1530..51cd74b3de0 100644 --- a/lld/lib/Driver/LinkerInvocation.cpp +++ b/lld/lib/Driver/LinkerInvocation.cpp @@ -11,8 +11,9 @@ #include "lld/Core/InputFiles.h" #include "lld/Core/Resolver.h" -#include "lld/Core/TargetInfo.h" #include "lld/Driver/Target.h" +#include "lld/ReaderWriter/Reader.h" +#include "lld/ReaderWriter/Writer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" @@ -67,19 +68,12 @@ void LinkerInvocation::operator()() { inputs.appendFiles(files); } - class TestingTargetInfo LLVM_FINAL : public TargetInfo { - public: - TestingTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {} - - virtual uint64_t getPageSize() const { return 0x1000; } - } tti(_options); - auto writer = target->getWriter(); // Give writer a chance to add files writer->addFiles(inputs); - Resolver resolver(tti, inputs); + Resolver resolver(target->getTargetInfo(), inputs); resolver.resolve(); File &merged = resolver.resultFile(); diff --git a/lld/lib/Driver/Targets.cpp b/lld/lib/Driver/Targets.cpp index ae82e905d2d..55ae206bac9 100644 --- a/lld/lib/Driver/Targets.cpp +++ b/lld/lib/Driver/Targets.cpp @@ -16,11 +16,10 @@ #include "lld/Driver/Target.h" #include "lld/Core/LinkerOptions.h" -#include "lld/ReaderWriter/ReaderArchive.h" -#include "lld/ReaderWriter/ReaderELF.h" -#include "lld/ReaderWriter/ReaderYAML.h" -#include "lld/ReaderWriter/WriterELF.h" -#include "lld/ReaderWriter/WriterYAML.h" +#include "lld/Core/TargetInfo.h" +#include "lld/ReaderWriter/Reader.h" +#include "lld/ReaderWriter/Writer.h" +#include "lld/ReaderWriter/ELFTargetInfo.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/raw_ostream.h" @@ -28,15 +27,18 @@ #include <set> using namespace lld; +using namespace std::placeholders; -class X86LinuxTarget LLVM_FINAL : public Target { +class ELFTarget : public Target { public: - X86LinuxTarget(const LinkerOptions &lo) : Target(lo), _woe(lo._entrySymbol) { - _readerELF.reset(createReaderELF(_roe, _roa)); - _readerYAML.reset(createReaderYAML(_roy)); - _writer.reset(createWriterELF(_woe)); - _writerYAML.reset(createWriterYAML(_woy)); - } + ELFTarget(std::unique_ptr<ELFTargetInfo> ti) + : Target(std::unique_ptr<TargetInfo>(ti.get())), + _elfTargetInfo(*ti.release()), + _readerELF(createReaderELF( + *_targetInfo, std::bind(&ELFTarget::getReader, this, _1))), + _readerYAML(createReaderYAML(*_targetInfo)), + _writer(createWriterELF(_elfTargetInfo)), + _writerYAML(createWriterYAML(*_targetInfo)) {} virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) { auto kind = input.getKind(); @@ -53,188 +55,38 @@ public: } virtual ErrorOr<lld::Writer&> getWriter() { - return _options._outputYAML ? *_writerYAML : *_writer; + return _targetInfo->getLinkerOptions()._outputYAML ? *_writerYAML + : *_writer; } -private: - lld::ReaderOptionsELF _roe; - lld::ReaderOptionsArchive _roa; - struct : lld::ReaderOptionsYAML { - virtual Reference::Kind kindFromString(StringRef kindName) const { - int k; - if (kindName.getAsInteger(0, k)) - k = 0; - return k; - } - } _roy; - - struct WOpts : lld::WriterOptionsELF { - WOpts(StringRef entry) { - _endianness = llvm::support::little; - _is64Bit = false; - _type = llvm::ELF::ET_EXEC; - _machine = llvm::ELF::EM_386; - _entryPoint = entry; - } - } _woe; - - struct WYOpts : lld::WriterOptionsYAML { - virtual StringRef kindToString(Reference::Kind k) const { - std::string str; - llvm::raw_string_ostream rso(str); - rso << (unsigned)k; - rso.flush(); - return *_strings.insert(str).first; - } - - mutable std::set<std::string> _strings; - } _woy; - +protected: + const ELFTargetInfo &_elfTargetInfo; std::unique_ptr<lld::Reader> _readerELF, _readerYAML; std::unique_ptr<lld::Writer> _writer, _writerYAML; }; -class X86_64LinuxTarget LLVM_FINAL : public Target { +class X86LinuxTarget LLVM_FINAL : public ELFTarget { public: - X86_64LinuxTarget(const LinkerOptions &lo) - : Target(lo), _woe(lo._entrySymbol) { - _readerELF.reset(createReaderELF(_roe, _roa)); - _readerYAML.reset(createReaderYAML(_roy)); - _writer.reset(createWriterELF(_woe)); - _writerYAML.reset(createWriterYAML(_woy)); - } - - virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) { - auto kind = input.getKind(); - if (!kind) - return error_code(kind); - - if (*kind == InputKind::YAML) - return *_readerYAML; - - if (*kind == InputKind::Object) - return *_readerELF; - - return llvm::make_error_code(llvm::errc::invalid_argument); - } - - virtual ErrorOr<lld::Writer&> getWriter() { - return _options._outputYAML ? *_writerYAML : *_writer; - } - -private: - lld::ReaderOptionsELF _roe; - lld::ReaderOptionsArchive _roa; - struct : lld::ReaderOptionsYAML { - virtual Reference::Kind kindFromString(StringRef kindName) const { - int k; - if (kindName.getAsInteger(0, k)) - k = 0; - return k; - } - } _roy; - - struct WOpts : lld::WriterOptionsELF { - WOpts(StringRef entry) { - _endianness = llvm::support::little; - _is64Bit = true; - _type = llvm::ELF::ET_EXEC; - _machine = llvm::ELF::EM_X86_64; - _entryPoint = entry; - } - } _woe; - - struct WYOpts : lld::WriterOptionsYAML { - virtual StringRef kindToString(Reference::Kind k) const { - std::string str; - llvm::raw_string_ostream rso(str); - rso << (unsigned)k; - rso.flush(); - return *_strings.insert(str).first; - } - - mutable std::set<std::string> _strings; - } _woy; - - std::unique_ptr<lld::Reader> _readerELF, _readerYAML; - std::unique_ptr<lld::Writer> _writer, _writerYAML; + X86LinuxTarget(std::unique_ptr<ELFTargetInfo> ti) + : ELFTarget(std::move(ti)) {} }; -class HexagonTarget LLVM_FINAL : public Target { +class HexagonTarget LLVM_FINAL : public ELFTarget { public: - HexagonTarget(const LinkerOptions &lo) - : Target(lo), _woe(lo._entrySymbol) { - _readerELF.reset(createReaderELF(_roe, _roa)); - _readerYAML.reset(createReaderYAML(_roy)); - _writer.reset(createWriterELF(_woe)); - _writerYAML.reset(createWriterYAML(_woy)); - } - - virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) { - auto kind = input.getKind(); - if (!kind) - return error_code(kind); - - if (*kind == InputKind::YAML) - return *_readerYAML; - - if (*kind == InputKind::Object) - return *_readerELF; - - return llvm::make_error_code(llvm::errc::invalid_argument); - } - - virtual ErrorOr<lld::Writer&> getWriter() { - return _options._outputYAML ? *_writerYAML : *_writer; - } - -private: - lld::ReaderOptionsELF _roe; - lld::ReaderOptionsArchive _roa; - struct : lld::ReaderOptionsYAML { - virtual Reference::Kind kindFromString(StringRef kindName) const { - int k; - if (kindName.getAsInteger(0, k)) - k = 0; - return k; - } - } _roy; - - struct WOpts : lld::WriterOptionsELF { - WOpts(StringRef entry) { - _endianness = llvm::support::little; - _is64Bit = false; - _type = llvm::ELF::ET_EXEC; - _machine = llvm::ELF::EM_HEXAGON; - _entryPoint = entry; - } - } _woe; - - struct WYOpts : lld::WriterOptionsYAML { - virtual StringRef kindToString(Reference::Kind k) const { - std::string str; - llvm::raw_string_ostream rso(str); - rso << (unsigned)k; - rso.flush(); - return *_strings.insert(str).first; - } - - mutable std::set<std::string> _strings; - } _woy; - - std::unique_ptr<lld::Reader> _readerELF, _readerYAML; - std::unique_ptr<lld::Writer> _writer, _writerYAML; + HexagonTarget(std::unique_ptr<ELFTargetInfo> ti) + : ELFTarget(std::move(ti)) {} }; std::unique_ptr<Target> Target::create(const LinkerOptions &lo) { llvm::Triple t(lo._target); - if (t.getOS() == llvm::Triple::Linux && t.getArch() == llvm::Triple::x86) - return std::unique_ptr<Target>(new X86LinuxTarget(lo)); - else if (t.getOS() == llvm::Triple::Linux && - t.getArch() == llvm::Triple::x86_64) - return std::unique_ptr<Target>(new X86_64LinuxTarget(lo)); + // Create a TargetInfo. + std::unique_ptr<ELFTargetInfo> ti(ELFTargetInfo::create(lo)); + + // Create the Target + if (t.getOS() == llvm::Triple::Linux && (t.getArch() == llvm::Triple::x86 || + t.getArch() == llvm::Triple::x86_64)) + return std::unique_ptr<Target>(new X86LinuxTarget(std::move(ti))); else if (t.getArch() == llvm::Triple::hexagon) - return std::unique_ptr<Target>(new HexagonTarget(lo)); + return std::unique_ptr<Target>(new HexagonTarget(std::move(ti))); return std::unique_ptr<Target>(); } - diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt index aa3e54cd1ab..b12d56450c1 100644 --- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt +++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt @@ -5,7 +5,6 @@ add_lld_library(lldELF ReaderELF.cpp ReferenceKinds.cpp WriterELF.cpp - WriterOptionsELF.cpp X86Reference.cpp X86_64Reference.cpp ) diff --git a/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h b/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h index ae859d8d05f..86e61ecc020 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h @@ -10,6 +10,8 @@ #ifndef LLD_READER_WRITER_DEFAULT_ELF_LAYOUT_H_ #define LLD_READER_WRITER_DEFAULT_ELF_LAYOUT_H_ +#include "lld/Core/LinkerOptions.h" + #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" @@ -150,7 +152,7 @@ public: typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT; - DefaultELFLayout(const WriterOptionsELF &options) : _options(options) {} + DefaultELFLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {} /// \brief Return the section order for a input section virtual SectionOrder getSectionOrder @@ -250,7 +252,7 @@ private: ELFProgramHeader<ELFT> *_programHeader; std::vector<AbsoluteAtomPair> _absoluteAtoms; llvm::BumpPtrAllocator _allocator; - const WriterOptionsELF _options; + const ELFTargetInfo &_targetInfo; }; template<class ELFT> @@ -483,7 +485,7 @@ DefaultELFLayout<ELFT>::assignSectionsToSegments() { segment = segmentInsert.first->second; } else { segment = new (_allocator.Allocate<Segment<ELFT>>()) Segment<ELFT>( - segmentName, getSegmentType(section), _options); + segmentName, getSegmentType(section), _targetInfo); segmentInsert.first->second = segment; _segments.push_back(segment); } @@ -516,7 +518,7 @@ DefaultELFLayout<ELFT>::assignVirtualAddress() { if (_segments.empty()) return; - uint64_t virtualAddress = _options.baseAddress(); + uint64_t virtualAddress = _targetInfo.getLinkerOptions()._baseAddress; // HACK: This is a super dirty hack. The elf header and program header are // not part of a section, but we need them to be loaded at the base address @@ -539,7 +541,7 @@ DefaultELFLayout<ELFT>::assignVirtualAddress() { for (auto &si : _segments) { // Align the segment to a page boundary fileoffset = llvm::RoundUpToAlignment(fileoffset, - _options.pageSize()); + _targetInfo.getPageSize()); si->assignOffsets(fileoffset); fileoffset = si->fileOffset() + si->fileSize(); } @@ -552,7 +554,7 @@ DefaultELFLayout<ELFT>::assignVirtualAddress() { (*si)->assignVirtualAddress(address); (*si)->setMemSize(address - virtualAddress); virtualAddress = llvm::RoundUpToAlignment(address, - _options.pageSize()); + _targetInfo.getPageSize()); } _programHeader->resetProgramHeaders(); } diff --git a/lld/lib/ReaderWriter/ELF/ELFSegmentChunks.h b/lld/lib/ReaderWriter/ELF/ELFSegmentChunks.h index 0e329b4c6fd..177313776b9 100644 --- a/lld/lib/ReaderWriter/ELF/ELFSegmentChunks.h +++ b/lld/lib/ReaderWriter/ELF/ELFSegmentChunks.h @@ -11,7 +11,7 @@ #define LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H_ #include "lld/Core/range.h" -#include "lld/ReaderWriter/WriterELF.h" +#include "lld/ReaderWriter/Writer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/OwningPtr.h" @@ -113,7 +113,7 @@ public: Segment(const StringRef name, const ELFLayout::SegmentType type, - const WriterOptionsELF &options); + const ELFTargetInfo &ti); /// append a section to a segment void append(Section<ELFT> *section); @@ -168,7 +168,7 @@ public: inline ELFLayout::SegmentType segmentType() { return _segmentType; } - inline int pageSize() const { return _options.pageSize(); } + inline int pageSize() const { return _targetInfo.getPageSize(); } inline int64_t atomflags() const { return _atomflags; } @@ -195,19 +195,19 @@ protected: ELFLayout::SegmentType _segmentType; int64_t _flags; int64_t _atomflags; - const WriterOptionsELF _options; + const ELFTargetInfo &_targetInfo; llvm::BumpPtrAllocator _segmentAllocate; }; template<class ELFT> Segment<ELFT>::Segment(const StringRef name, const ELFLayout::SegmentType type, - const WriterOptionsELF &options) + const ELFTargetInfo &ti) : Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment) , _segmentType(type) , _flags(0) , _atomflags(0) - , _options(options) { + , _targetInfo(ti) { this->_align2 = 0; this->_fsize = 0; } @@ -268,7 +268,7 @@ Segment<ELFT>::assignOffsets(uint64_t startOffset) { SegmentSlice<ELFT> *slice = nullptr; // If the newOffset computed is more than a page away, lets create // a seperate segment, so that memory is not used up while running - if ((newOffset - curOffset) > _options.pageSize()) { + if ((newOffset - curOffset) > _targetInfo.getPageSize()) { // TODO: use std::find here for (auto s : slices()) { if (s->startSection() == startSection) { @@ -286,7 +286,7 @@ Segment<ELFT>::assignOffsets(uint64_t startOffset) { slice->setSize(curSliceSize); slice->setAlign(sliceAlign); uint64_t newPageOffset = - llvm::RoundUpToAlignment(curOffset, _options.pageSize()); + llvm::RoundUpToAlignment(curOffset, _targetInfo.getPageSize()); newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2()); curSliceFileOffset = newOffset; startSectionIter = endSectionIter; @@ -332,7 +332,7 @@ void Segment<ELFT>::assignVirtualAddress(uint64_t &addr) { for (auto slice : slices()) { // Align to a page - addr = llvm::RoundUpToAlignment(addr, _options.pageSize()); + addr = llvm::RoundUpToAlignment(addr, _targetInfo.getPageSize()); // Align to the slice alignment addr = llvm::RoundUpToAlignment(addr, slice->align2()); diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp index 9a086f83cef..5c4cbfceb00 100644 --- a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp +++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp @@ -23,6 +23,13 @@ uint16_t ELFTargetInfo::getOutputType() const { return llvm::ELF::ET_REL; case OutputKind::Shared: return llvm::ELF::ET_DYN; + case OutputKind::Core: + return llvm::ELF::ET_CORE; + case OutputKind::SharedStubs: + case OutputKind::DebugSymbols: + case OutputKind::Bundle: + case OutputKind::Preload: + break; } llvm_unreachable("Unhandled OutputKind"); } @@ -42,21 +49,21 @@ uint16_t ELFTargetInfo::getOutputMachine() const { } } -class X86ELFTargetInfo final : public ELFTargetInfo { +class X86ELFTargetInfo LLVM_FINAL : public ELFTargetInfo { public: X86ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} virtual uint64_t getPageSize() const { return 0x1000; } }; -class HexagonELFTargetInfo final : public ELFTargetInfo { +class HexagonELFTargetInfo LLVM_FINAL : public ELFTargetInfo { public: HexagonELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} virtual uint64_t getPageSize() const { return 0x1000; } }; -class PPCELFTargetInfo final : public ELFTargetInfo { +class PPCELFTargetInfo LLVM_FINAL : public ELFTargetInfo { public: PPCELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} diff --git a/lld/lib/ReaderWriter/ELF/ELFWriter.h b/lld/lib/ReaderWriter/ELF/ELFWriter.h index 517d61c9569..20b83fd0713 100644 --- a/lld/lib/ReaderWriter/ELF/ELFWriter.h +++ b/lld/lib/ReaderWriter/ELF/ELFWriter.h @@ -12,7 +12,7 @@ #include "lld/Core/File.h" #include "lld/Core/InputFiles.h" -#include "lld/ReaderWriter/WriterELF.h" +#include "lld/ReaderWriter/Writer.h" #include "ReferenceKinds.h" namespace lld { diff --git a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h index 1820b2cbf35..f0531ac6d13 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h @@ -15,7 +15,7 @@ #include "lld/Core/UndefinedAtom.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" -#include "lld/ReaderWriter/WriterELF.h" +#include "lld/ReaderWriter/Writer.h" #include "AtomsELF.h" namespace lld { @@ -30,9 +30,7 @@ template<class ELFT> class CRuntimeFile : public File { public: typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; - CRuntimeFile(const WriterOptionsELF &options) - : File("C runtime") - { } + CRuntimeFile(const ELFTargetInfo &) : File("C runtime") {} /// \brief add a global absolute atom void addAbsoluteAtom(const StringRef symbolName) { diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp index 16e53f221c6..deaf66354c4 100644 --- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp +++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp @@ -13,10 +13,12 @@ /// //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/ReaderELF.h" -#include "lld/ReaderWriter/ReaderArchive.h" +#include "lld/ReaderWriter/Reader.h" + #include "lld/Core/File.h" #include "lld/Core/Reference.h" +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "lld/ReaderWriter/ReaderArchive.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" @@ -326,12 +328,9 @@ private: /// memory buffer for ELF class and bit width class ReaderELF : public Reader { public: - ReaderELF(const ReaderOptionsELF &, - ReaderOptionsArchive &readerOptionsArchive) - : _readerOptionsArchive(readerOptionsArchive), - _readerArchive(_readerOptionsArchive) { - _readerOptionsArchive.setReader(this); - } + ReaderELF(const TargetInfo & ti, std::function<ReaderFunc> read) + : Reader(ti), + _readerArchive(ti, read) {} error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<std::unique_ptr<File>> &result) { @@ -411,18 +410,13 @@ public: } private: - ReaderOptionsArchive &_readerOptionsArchive; ReaderArchive _readerArchive; }; } // end anon namespace. namespace lld { -ReaderOptionsELF::ReaderOptionsELF() {} - -ReaderOptionsELF::~ReaderOptionsELF() {} - -Reader *createReaderELF(const ReaderOptionsELF &options, - ReaderOptionsArchive &optionsArchive) { - return new ReaderELF(options, optionsArchive); +std::unique_ptr<Reader> createReaderELF(const TargetInfo & ti, + std::function<ReaderFunc> read) { + return std::unique_ptr<Reader>(new ReaderELF(ti, std::move(read))); } } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp b/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp index 083e843237c..769895ab843 100644 --- a/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp +++ b/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp @@ -11,29 +11,30 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ELF.h" namespace lld { namespace elf { -KindHandler::KindHandler() { -} +KindHandler::KindHandler() {} -KindHandler::~KindHandler() { -} +KindHandler::~KindHandler() {} std::unique_ptr<KindHandler> -KindHandler::makeHandler(uint16_t arch, llvm::support::endianness endian) { +KindHandler::makeHandler(llvm::Triple::ArchType arch, bool isLittleEndian) { switch(arch) { - case llvm::ELF::EM_HEXAGON: + case llvm::Triple::hexagon: return std::unique_ptr<KindHandler>(new HexagonKindHandler()); - case llvm::ELF::EM_386: + case llvm::Triple::x86: return std::unique_ptr<KindHandler>(new X86KindHandler()); - case llvm::ELF::EM_X86_64: + case llvm::Triple::x86_64: return std::unique_ptr<KindHandler>(new X86_64KindHandler()); - case llvm::ELF::EM_PPC: - return std::unique_ptr<KindHandler>(new PPCKindHandler(endian)); + case llvm::Triple::ppc: + return std::unique_ptr<KindHandler>( + new PPCKindHandler(isLittleEndian ? llvm::support::little + : llvm::support::big)); default: llvm_unreachable("arch not supported"); } diff --git a/lld/lib/ReaderWriter/ELF/ReferenceKinds.h b/lld/lib/ReaderWriter/ELF/ReferenceKinds.h index faa4299700c..45f6cae66da 100644 --- a/lld/lib/ReaderWriter/ELF/ReferenceKinds.h +++ b/lld/lib/ReaderWriter/ELF/ReferenceKinds.h @@ -9,9 +9,12 @@ #include "lld/Core/LLVM.h" #include "lld/Core/Reference.h" -#include "lld/ReaderWriter/WriterELF.h" +#include "lld/ReaderWriter/Writer.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" #include <functional> #include <map> @@ -32,8 +35,8 @@ class KindHandler { public: typedef Reference::Kind Kind; - static std::unique_ptr<KindHandler> makeHandler(uint16_t arch, - llvm::support::endianness endian); + static std::unique_ptr<KindHandler> makeHandler(llvm::Triple::ArchType arch, + bool isLittleEndian); virtual ~KindHandler(); virtual Kind stringToKind(StringRef str) = 0; virtual StringRef kindToString(Kind) = 0; diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index d9be025c5ca..73bb6bb6103 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "lld/ReaderWriter/ELFTargetInfo.h" + #include "DefaultELFLayout.h" #include "ExecutableAtoms.h" @@ -26,7 +28,7 @@ public: typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; typedef Elf_Sym_Impl<ELFT> Elf_Sym; - ELFExecutableWriter(const WriterOptionsELF &options); + ELFExecutableWriter(const ELFTargetInfo &ti); private: // build the sections that need to be created @@ -49,7 +51,7 @@ private: void createDefaultSections(); - const WriterOptionsELF &_options; + const ELFTargetInfo &_targetInfo; typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress; std::unique_ptr<KindHandler> _referenceKindHandler; @@ -69,12 +71,12 @@ private: // ELFExecutableWriter //===----------------------------------------------------------------------===// template<class ELFT> -ELFExecutableWriter<ELFT>::ELFExecutableWriter(const WriterOptionsELF &options) - : _options(options) +ELFExecutableWriter<ELFT>::ELFExecutableWriter(const ELFTargetInfo &ti) + : _targetInfo(ti) , _referenceKindHandler(KindHandler::makeHandler( - _options.machine(), (endianness)ELFT::TargetEndianness)) - , _runtimeFile(options) { - _layout =new DefaultELFLayout<ELFT>(options); + ti.getTriple().getArch(), ti.isLittleEndian())) + , _runtimeFile(ti) { + _layout = new DefaultELFLayout<ELFT>(ti); } template<class ELFT> @@ -248,14 +250,14 @@ ELFExecutableWriter<ELFT>::writeFile(const lld::File &file, StringRef path) { if (ec) return ec; - _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64 - : ELF::ELFCLASS32)); - _elfHeader->e_ident(ELF::EI_DATA, _options.endianness() == llvm::support::big - ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB); + _elfHeader->e_ident(ELF::EI_CLASS, _targetInfo.is64Bits() ? ELF::ELFCLASS64 + : ELF::ELFCLASS32); + _elfHeader->e_ident(ELF::EI_DATA, _targetInfo.isLittleEndian() + ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); _elfHeader->e_ident(ELF::EI_VERSION, 1); _elfHeader->e_ident(ELF::EI_OSABI, 0); - _elfHeader->e_type(_options.type()); - _elfHeader->e_machine(_options.machine()); + _elfHeader->e_type(_targetInfo.getOutputType()); + _elfHeader->e_machine(_targetInfo.getOutputMachine()); _elfHeader->e_version(1); _elfHeader->e_entry(0ULL); _elfHeader->e_phoff(_programHeader->fileOffset()); @@ -305,24 +307,24 @@ void ELFExecutableWriter<ELFT>::createDefaultSections() { } } // namespace elf -Writer *createWriterELF(const WriterOptionsELF &options) { +std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &TI) { using llvm::object::ELFType; // Set the default layout to be the static executable layout // We would set the layout to a dynamic executable layout // if we came across any shared libraries in the process - if (!options.is64Bit() && options.endianness() == llvm::support::little) - return - new elf::ELFExecutableWriter<ELFType<support::little, 4, false>>(options); - else if (options.is64Bit() && options.endianness() == llvm::support::little) - return - new elf::ELFExecutableWriter<ELFType<support::little, 8, true>>(options); - else if (!options.is64Bit() && options.endianness() == llvm::support::big) - return - new elf::ELFExecutableWriter<ELFType<support::big, 4, false>>(options); - else if (options.is64Bit() && options.endianness() == llvm::support::big) - return - new elf::ELFExecutableWriter<ELFType<support::big, 8, true>>(options); + if (!TI.is64Bits() && TI.isLittleEndian()) + return std::unique_ptr<Writer>(new + elf::ELFExecutableWriter<ELFType<support::little, 4, false>>(TI)); + else if (TI.is64Bits() && TI.isLittleEndian()) + return std::unique_ptr<Writer>(new + elf::ELFExecutableWriter<ELFType<support::little, 8, true>>(TI)); + else if (!TI.is64Bits() && !TI.isLittleEndian()) + return std::unique_ptr<Writer>(new + elf::ELFExecutableWriter<ELFType<support::big, 4, false>>(TI)); + else if (TI.is64Bits() && !TI.isLittleEndian()) + return std::unique_ptr<Writer>(new + elf::ELFExecutableWriter<ELFType<support::big, 8, true>>(TI)); llvm_unreachable("Invalid Options!"); } diff --git a/lld/lib/ReaderWriter/ELF/WriterOptionsELF.cpp b/lld/lib/ReaderWriter/ELF/WriterOptionsELF.cpp deleted file mode 100644 index 4d832aed05e..00000000000 --- a/lld/lib/ReaderWriter/ELF/WriterOptionsELF.cpp +++ /dev/null @@ -1,28 +0,0 @@ -//===- lib/ReaderWriter/ELF/WriterOptionsELF.cpp ----------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/ReaderWriter/WriterELF.h" - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ELF.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/system_error.h" - - -namespace lld { - -StringRef WriterOptionsELF::entryPoint() const { - if (_type == llvm::ELF::ET_EXEC) - return _entryPoint; - return StringRef(); -} - -} // namespace lld diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt index db64d87ec3a..c23ca186dbb 100644 --- a/lld/lib/ReaderWriter/MachO/CMakeLists.txt +++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt @@ -1,7 +1,6 @@ add_lld_library(lldMachO MachOTargetInfo.cpp WriterMachO.cpp - WriterOptionsMachO.cpp ReferenceKinds.cpp ) diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp index ac80059624c..fb1e575652c 100644 --- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp +++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp @@ -15,8 +15,7 @@ #include "lld/Core/UndefinedAtom.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" - -#include "lld/ReaderWriter/WriterMachO.h" +#include "lld/Core/TargetInfo.h" #include "SimpleAtoms.hpp" @@ -30,10 +29,10 @@ namespace mach_o { // class CRuntimeFile : public SimpleFile { public: - CRuntimeFile(const WriterOptionsMachO &options) + CRuntimeFile(const MachOTargetInfo &ti) : SimpleFile("C runtime"), _undefMain(*this, "_main") { // only main executables need _main - if ( options.outputKind() == WriterOptionsMachO::outputDynamicExecutable) + if (ti.getLinkerOptions()._outputKind == OutputKind::Executable) this->addAtom(_undefMain); } diff --git a/lld/lib/ReaderWriter/MachO/GOTPass.hpp b/lld/lib/ReaderWriter/MachO/GOTPass.hpp index 6a7c451e448..9618302ede4 100644 --- a/lld/lib/ReaderWriter/MachO/GOTPass.hpp +++ b/lld/lib/ReaderWriter/MachO/GOTPass.hpp @@ -29,7 +29,7 @@ public: return true; } - virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) { + virtual bool isGOTAccess(int32_t, bool& canBypassGOT) { return false; } diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp index d24680a7b91..f37496612fa 100644 --- a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp @@ -41,7 +41,25 @@ uint32_t MachOTargetInfo::getCPUSubType() const { } } -class GenericMachOTargetInfo final : public MachOTargetInfo { +bool MachOTargetInfo::addEntryPointLoadCommand() const { + switch (_options._outputKind) { + case OutputKind::Executable: + return true; + default: + return false; + } +} + +bool MachOTargetInfo::addUnixThreadLoadCommand() const { + switch (_options._outputKind) { + case OutputKind::Executable: + return true; + default: + return false; + } +} + +class GenericMachOTargetInfo LLVM_FINAL : public MachOTargetInfo { public: GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {} @@ -49,6 +67,8 @@ public: virtual uint64_t getPageZeroSize() const { return getPageSize(); } virtual StringRef getEntry() const { + if (_options._outputKind != OutputKind::Executable) + return ""; if (!_options._entrySymbol.empty()) return _options._entrySymbol; return "_main"; diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp index 6186aa2d234..5d21a88ad5d 100644 --- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp +++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" @@ -28,18 +29,16 @@ KindHandler::KindHandler() { KindHandler::~KindHandler() { } -KindHandler *KindHandler::makeHandler(WriterOptionsMachO::Architecture arch) { +KindHandler *KindHandler::makeHandler(llvm::Triple::ArchType arch) { switch( arch ) { - case WriterOptionsMachO::arch_x86_64: + case llvm::Triple::x86_64: return new KindHandler_x86_64(); - break; - case WriterOptionsMachO::arch_x86: + case llvm::Triple::x86: return new KindHandler_x86(); - break; - case WriterOptionsMachO::arch_armv6: - case WriterOptionsMachO::arch_armv7: + case llvm::Triple::arm: return new KindHandler_arm(); - break; + default: + llvm_unreachable("Unknown arch"); } } diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h index 08118082649..fcae76e81e7 100644 --- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h +++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h @@ -10,7 +10,8 @@ #include "lld/Core/LLVM.h" #include "lld/Core/Reference.h" -#include "lld/ReaderWriter/WriterMachO.h" + +#include "llvm/ADT/Triple.h" #ifndef LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_ #define LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_ @@ -28,7 +29,7 @@ class KindHandler { public: typedef Reference::Kind Kind; - static KindHandler *makeHandler(WriterOptionsMachO::Architecture arch); + static KindHandler *makeHandler(llvm::Triple::ArchType arch); virtual ~KindHandler(); virtual Kind stringToKind(StringRef str) = 0; virtual StringRef kindToString(Kind) = 0; diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp index 71e76541f72..28453cf359e 100644 --- a/lld/lib/ReaderWriter/MachO/StubsPass.hpp +++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp @@ -28,19 +28,19 @@ namespace mach_o { class StubsPass : public lld::StubsPass { public: - StubsPass(const WriterOptionsMachO &options) - : _options(options), - _kindHandler(KindHandler::makeHandler(options.architecture())), + StubsPass(const MachOTargetInfo &ti) + : _targetInfo(ti), + _kindHandler(KindHandler::makeHandler(_targetInfo.getTriple().getArch())), _helperCommonAtom(nullptr), _helperCacheAtom(nullptr), _helperBinderAtom(nullptr) { } virtual bool noTextRelocs() { - return _options.noTextRelocations(); + return !_targetInfo.getLinkerOptions()._textRelocations; } - virtual bool isCallSite(Reference::Kind kind) { + virtual bool isCallSite(int32_t kind) { return _kindHandler->isCallSite(kind); } @@ -58,16 +58,15 @@ public: } const DefinedAtom* makeStub(const Atom& target) { - switch ( _options.architecture() ) { - case WriterOptionsMachO::arch_x86_64: + switch (_targetInfo.getTriple().getArch()) { + case llvm::Triple::x86_64: return makeStub_x86_64(target); - - case WriterOptionsMachO::arch_x86: + case llvm::Triple::x86: return makeStub_x86(target); - - case WriterOptionsMachO::arch_armv6: - case WriterOptionsMachO::arch_armv7: + case llvm::Triple::arm: return makeStub_arm(target); + default: + llvm_unreachable("Unknown arch"); } } @@ -151,7 +150,7 @@ private: } }; - const WriterOptionsMachO &_options; + const MachOTargetInfo &_targetInfo; KindHandler *_kindHandler; File _file; llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub; diff --git a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp index 0a833381a76..64a6be32fe9 100644 --- a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp +++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/WriterMachO.h" +#include "lld/ReaderWriter/Writer.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -23,12 +23,15 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "lld/Core/DefinedAtom.h" #include "lld/Core/File.h" #include "lld/Core/InputFiles.h" +#include "lld/Core/LinkerOptions.h" #include "lld/Core/Reference.h" #include "lld/Core/SharedLibraryAtom.h" +#include "lld/ReaderWriter/MachOTargetInfo.h" #include <vector> #include <map> @@ -104,7 +107,7 @@ protected: class SectionChunk : public Chunk { public: static SectionChunk* make(DefinedAtom::ContentType, - const WriterOptionsMachO &options, + const MachOTargetInfo &ti, class MachOWriter &writer); virtual StringRef segmentName() const; virtual bool occupiesNoDiskSpace(); @@ -126,12 +129,12 @@ private: SectionChunk(StringRef seg, StringRef sect, uint32_t flags, - const WriterOptionsMachO &options, + const MachOTargetInfo &ti, class MachOWriter &writer); StringRef _segmentName; StringRef _sectionName; - const WriterOptionsMachO &_options; + const MachOTargetInfo &_targetInfo; class MachOWriter &_writer; uint32_t _flags; uint32_t _permissions; @@ -146,7 +149,7 @@ private: // class MachHeaderChunk : public Chunk { public: - MachHeaderChunk(const WriterOptionsMachO &options, + MachHeaderChunk(const MachOTargetInfo &ti, const File &file); virtual StringRef segmentName() const; virtual void write(uint8_t *fileBuffer); @@ -155,7 +158,7 @@ public: uint64_t loadCommandsSize(); private: - uint32_t filetype(WriterOptionsMachO::OutputKind kind); + uint32_t filetype(OutputKind); uint32_t magic(uint32_t cpuType); mach_header _mh; @@ -171,7 +174,7 @@ private: class LoadCommandsChunk : public Chunk { public: LoadCommandsChunk(MachHeaderChunk&, - const WriterOptionsMachO &options, + const MachOTargetInfo &, class MachOWriter&); virtual StringRef segmentName() const; virtual void write(uint8_t *fileBuffer); @@ -197,7 +200,7 @@ private: }; MachHeaderChunk &_mh; - const WriterOptionsMachO &_options; + const MachOTargetInfo &_targetInfo; class MachOWriter &_writer; segment_command *_linkEditSegment; symtab_command *_symbolTableLoadCommand; @@ -340,7 +343,7 @@ private: // class MachOWriter : public Writer { public: - MachOWriter(const WriterOptionsMachO &options); + MachOWriter(const MachOTargetInfo &ti); virtual error_code writeFile(const lld::File &file, StringRef path); virtual StubsPass *stubPass(); @@ -373,7 +376,7 @@ private: typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress; - const WriterOptionsMachO &_options; + const MachOTargetInfo &_targetInfo; KindHandler *_referenceKindHandler; StubsPass _stubsPass; GOTPass _gotPass; @@ -459,46 +462,46 @@ void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) { //===----------------------------------------------------------------------===// SectionChunk::SectionChunk(StringRef seg, StringRef sect, - uint32_t flags, const WriterOptionsMachO &options, + uint32_t flags, const MachOTargetInfo &ti, MachOWriter &writer) - : _segmentName(seg), _sectionName(sect), _options(options), + : _segmentName(seg), _sectionName(sect), _targetInfo(ti), _writer(writer), _flags(flags), _permissions(0) { } SectionChunk* SectionChunk::make(DefinedAtom::ContentType type, - const WriterOptionsMachO &options, + const MachOTargetInfo &ti, MachOWriter &writer) { switch ( type ) { case DefinedAtom::typeCode: return new SectionChunk("__TEXT", "__text", S_REGULAR | S_ATTR_PURE_INSTRUCTIONS, - options, writer); + ti, writer); break; case DefinedAtom::typeCString: return new SectionChunk("__TEXT", "__cstring", S_CSTRING_LITERALS, - options, writer); + ti, writer); break; case DefinedAtom::typeStub: return new SectionChunk("__TEXT", "__stubs", S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS, - options, writer); + ti, writer); break; case DefinedAtom::typeStubHelper: return new SectionChunk("__TEXT", "__stub_helper", S_REGULAR | S_ATTR_PURE_INSTRUCTIONS, - options, writer); + ti, writer); break; case DefinedAtom::typeLazyPointer: return new SectionChunk("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS, - options, writer); + ti, writer); break; case DefinedAtom::typeGOT: return new SectionChunk("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS, - options, writer); + ti, writer); break; default: assert(0 && "TO DO: add support for more sections"); @@ -595,13 +598,12 @@ void SectionChunk::write(uint8_t *chunkBuffer) { // MachHeaderChunk //===----------------------------------------------------------------------===// -MachHeaderChunk::MachHeaderChunk(const WriterOptionsMachO &options, - const File &file) { +MachHeaderChunk::MachHeaderChunk(const MachOTargetInfo &ti, const File &file) { // Set up mach_header based on options - _mh.magic = this->magic(options.cpuType()); - _mh.cputype = options.cpuType(); - _mh.cpusubtype = options.cpuSubtype(); - _mh.filetype = this->filetype(options.outputKind()); + _mh.magic = this->magic(ti.getCPUType()); + _mh.cputype = ti.getCPUType(); + _mh.cpusubtype = ti.getCPUSubType(); + _mh.filetype = this->filetype(ti.getLinkerOptions()._outputKind); _mh.ncmds = 0; _mh.sizeofcmds = 0; _mh.flags = 0; @@ -639,22 +641,29 @@ uint32_t MachHeaderChunk::magic(uint32_t cpuType) { case CPU_TYPE_X86_64: return MH_MAGIC_64; } - assert(0 && "file cpu type not supported"); + llvm_unreachable("file CPU type not supported"); return 0; } -uint32_t MachHeaderChunk::filetype(WriterOptionsMachO::OutputKind kind) { +uint32_t MachHeaderChunk::filetype(OutputKind kind) { switch ( kind ) { - case WriterOptionsMachO::outputDynamicExecutable: - return MH_EXECUTE; - case WriterOptionsMachO::outputDylib: - return MH_DYLIB; - case WriterOptionsMachO::outputBundle: - return MH_BUNDLE; - case WriterOptionsMachO::outputObjectFile: - return MH_OBJECT; + case OutputKind::Executable: + return MH_EXECUTE; + case OutputKind::Relocatable: + return MH_OBJECT; + case OutputKind::Shared: + return MH_DYLIB; + case OutputKind::SharedStubs: + return MH_DYLIB_STUB; + case OutputKind::Bundle: + return MH_BUNDLE; + case OutputKind::Preload: + case OutputKind::DebugSymbols: + case OutputKind::Core: + break; } - assert(0 && "file outputkind not supported"); + llvm_unreachable("file OutputKind not supported"); + return 0; } @@ -664,9 +673,9 @@ uint32_t MachHeaderChunk::filetype(WriterOptionsMachO::OutputKind kind) { //===----------------------------------------------------------------------===// LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh, - const WriterOptionsMachO &options, + const MachOTargetInfo &ti, MachOWriter& writer) - : _mh(mh), _options(options), _writer(writer), + : _mh(mh), _targetInfo(ti), _writer(writer), _linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr), _entryPointLoadCommand(nullptr), _threadLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) { @@ -714,7 +723,7 @@ uint32_t LoadCommandsChunk::permissionsFromSections( void LoadCommandsChunk::computeSize(const lld::File &file) { const bool is64 = _writer.use64BitMachO(); // Main executables have a __PAGEZERO segment. - uint64_t pageZeroSize = _options.pageZeroSize(); + uint64_t pageZeroSize = _targetInfo.getPageZeroSize(); if ( pageZeroSize != 0 ) { assert(is64 || (pageZeroSize < 0xFFFFFFFF)); segment_command* pzSegCmd = new segment_command(0, is64); @@ -796,12 +805,11 @@ void LoadCommandsChunk::computeSize(const lld::File &file) { this->addLoadCommand(_dyldInfoLoadCommand); // Add entry point load command to main executables - if ( _options.addEntryPointLoadCommand() ) { + if (_targetInfo.addEntryPointLoadCommand()) { _entryPointLoadCommand = new entry_point_command(is64); this->addLoadCommand(_entryPointLoadCommand); - } - else if ( _options.addUnixThreadLoadCommand() ) { - _threadLoadCommand = new thread_command(_options.cpuType(), is64); + } else if (_targetInfo.addUnixThreadLoadCommand()) { + _threadLoadCommand = new thread_command(_targetInfo.getCPUType(), is64); this->addLoadCommand(_threadLoadCommand); } @@ -1295,10 +1303,10 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) { // MachOWriter //===----------------------------------------------------------------------===// -MachOWriter::MachOWriter(const WriterOptionsMachO &options) - : _options(options), - _referenceKindHandler(KindHandler::makeHandler(_options.architecture())), - _stubsPass(options), _cRuntimeFile(options), +MachOWriter::MachOWriter(const MachOTargetInfo &ti) + : _targetInfo(ti), + _referenceKindHandler(KindHandler::makeHandler(ti.getTriple().getArch())), + _stubsPass(ti), _cRuntimeFile(ti), _bindingInfo(nullptr), _lazyBindingInfo(nullptr), _symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr), _linkEditStartOffset(0), _linkEditStartAddress(0) { @@ -1339,7 +1347,7 @@ void MachOWriter::createChunks(const lld::File &file) { DefinedAtom::ContentType type = atom->contentType(); auto pos = map.find(type); if ( pos == map.end() ) { - SectionChunk *chunk = SectionChunk::make(type, _options, *this); + SectionChunk *chunk = SectionChunk::make(type, _targetInfo, *this); map[type] = chunk; chunk->appendAtom(atom); } @@ -1352,10 +1360,10 @@ void MachOWriter::createChunks(const lld::File &file) { // Make chunks in __TEXT for mach_header and load commands at start. - MachHeaderChunk *mhc = new MachHeaderChunk(_options, file); + MachHeaderChunk *mhc = new MachHeaderChunk(_targetInfo, file); _chunks.push_back(mhc); - _loadCommandsChunk = new LoadCommandsChunk(*mhc, _options, *this); + _loadCommandsChunk = new LoadCommandsChunk(*mhc, _targetInfo, *this); _chunks.push_back(_loadCommandsChunk); _paddingChunk = new LoadCommandPaddingChunk(*_loadCommandsChunk); @@ -1388,15 +1396,15 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) { void MachOWriter::buildAtomToAddressMap() { DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() << "assign atom addresses:\n"); - const bool lookForEntry = - (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable); + const bool lookForEntry = _targetInfo.getLinkerOptions()._outputKind == + OutputKind::Executable; for (SectionChunk *chunk : _sectionChunks ) { for (const SectionChunk::AtomInfo &info : chunk->atoms() ) { _atomToAddress[info.atom] = chunk->address() + info.offsetInSection; if ( lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) && (info.atom->size() != 0) - && info.atom->name().equals(_options.entryPointName()) ) { + && info.atom->name() == _targetInfo.getEntry()) { _entryAtom = info.atom; } DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() @@ -1419,7 +1427,7 @@ void MachOWriter::assignFileOffsets() { DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() << "assign file offsets:\n"); uint64_t offset = 0; - uint64_t address = _options.pageZeroSize(); + uint64_t address = _targetInfo.getPageZeroSize(); for ( Chunk *chunk : _chunks ) { if ( chunk->segmentName().equals("__LINKEDIT") ) { _linkEditStartOffset = Chunk::alignTo(offset, 12); @@ -1457,7 +1465,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex, const uint64_t kInvalidAddress = (uint64_t)(-1); StringRef lastSegName("__TEXT"); *segIndex = 0; - if ( _options.pageZeroSize() != 0 ) { + if ( _targetInfo.getPageZeroSize() != 0 ) { *segIndex = 1; } *segStartAddr = kInvalidAddress; @@ -1481,15 +1489,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex, } bool MachOWriter::use64BitMachO() const { - switch ( _options.cpuType() ) { - case CPU_TYPE_ARM: - case CPU_TYPE_I386: - return false; - case CPU_TYPE_X86_64: - return true; - } - assert(0 && "unknown cpu type"); - return false; + return _targetInfo.getTriple().isArch64Bit(); } @@ -1542,8 +1542,8 @@ void MachOWriter::addFiles(InputFiles &inputFiles) { } // namespace mach_o -Writer* createWriterMachO(const WriterOptionsMachO &options) { - return new lld::mach_o::MachOWriter(options); +std::unique_ptr<Writer> createWriterMachO(const MachOTargetInfo &ti) { + return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(ti)); } } // namespace lld diff --git a/lld/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp b/lld/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp deleted file mode 100644 index bb831b42d3f..00000000000 --- a/lld/lib/ReaderWriter/MachO/WriterOptionsMachO.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//===- lib/ReaderWriter/MachO/WriterOptionsMachO.cpp ----------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/ReaderWriter/WriterMachO.h" - -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/system_error.h" - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" - -#include "MachOFormat.hpp" - -namespace lld { - -WriterOptionsMachO::WriterOptionsMachO() - : _outputkind(outputDynamicExecutable), - _architecture(arch_x86), - _pageZeroSize(0x1000), - _noTextRelocations(true) { -} - -WriterOptionsMachO::~WriterOptionsMachO() { -} - -StringRef WriterOptionsMachO::archName() const { - switch ( _architecture ) { - case arch_x86_64: - return StringRef("x86_64"); - case arch_x86: - return StringRef("i386"); - case arch_armv6: - return StringRef("armv6"); - case arch_armv7: - return StringRef("armv7"); - } - llvm_unreachable("unknown arch"); -} - -uint32_t WriterOptionsMachO::cpuType() const { - switch ( _architecture ) { - case arch_x86_64: - return mach_o::CPU_TYPE_X86_64; - case arch_x86: - return mach_o::CPU_TYPE_I386; - case arch_armv6: - case arch_armv7: - return mach_o::CPU_TYPE_ARM; - } - llvm_unreachable("unknown arch"); -} - -uint32_t WriterOptionsMachO::cpuSubtype() const { - switch ( _architecture ) { - case arch_x86_64: - return mach_o::CPU_SUBTYPE_X86_64_ALL; - case arch_x86: - return mach_o::CPU_SUBTYPE_X86_ALL; - case arch_armv6: - return mach_o::CPU_SUBTYPE_ARM_V6; - case arch_armv7: - return mach_o::CPU_SUBTYPE_ARM_V7; - } - llvm_unreachable("unknown arch"); -} - -uint64_t WriterOptionsMachO::pageZeroSize() const { - switch ( _outputkind ) { - case outputDynamicExecutable: - return _pageZeroSize; - case outputDylib: - case outputBundle: - case outputObjectFile: - assert(_pageZeroSize == 0); - return 0; - } - llvm_unreachable("unknown outputkind"); -} - -bool WriterOptionsMachO::addEntryPointLoadCommand() const { - switch ( _outputkind ) { - case outputDynamicExecutable: - // Only main executables have an entry point - return false; - case outputDylib: - case outputBundle: - case outputObjectFile: - return false; - } - llvm_unreachable("unknown outputkind"); -} - -bool WriterOptionsMachO::addUnixThreadLoadCommand() const { - switch ( _outputkind ) { - case outputDynamicExecutable: - // Only main executables have an entry point - return true; - case outputDylib: - case outputBundle: - case outputObjectFile: - return false; - } - llvm_unreachable("unknown outputkind"); -} - -StringRef WriterOptionsMachO::entryPointName() const { - switch ( _outputkind ) { - case outputDynamicExecutable: - // Only main executables have an entry point - if ( ! _customEntryPointName.empty() ) { - return _customEntryPointName; - } - else { - if ( true || this->addEntryPointLoadCommand() ) - return StringRef("_main"); - else - return StringRef("start"); - } - break; - case outputDylib: - case outputBundle: - case outputObjectFile: - return StringRef(); - } - llvm_unreachable("unknown outputkind"); -} - - -} // namespace lld - diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp index 36389d0cb51..0a69ae4171d 100644 --- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp +++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/ReaderNative.h" +#include "lld/ReaderWriter/Reader.h" #include "lld/Core/Atom.h" #include "lld/Core/Error.h" @@ -914,39 +914,24 @@ inline void NativeReferenceV1::setTarget(const Atom* newAtom) { inline void NativeReferenceV1::setAddend(Addend a) { // Do nothing if addend value is not being changed. - if ( this->addend() == a ) + if (addend() == a) return; - assert(0 && "setAddend() not supported"); + llvm_unreachable("setAddend() not supported"); } - class Reader : public lld::Reader { public: - Reader(const ReaderOptionsNative &options) {} + Reader(const TargetInfo &ti) + : lld::Reader(ti) {} virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<std::unique_ptr<lld::File>> &result) { return File::make(mb, mb->getBufferIdentifier(), result); } }; +} // end namespace native - - -} // namespace native - -Reader* createReaderNative(const ReaderOptionsNative &options) { - return new lld::native::Reader(options); -} - -ReaderOptionsNative::ReaderOptionsNative() { -} - -ReaderOptionsNative::~ReaderOptionsNative() { +std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) { + return std::unique_ptr<Reader>(new lld::native::Reader(ti)); } - - -} // namespace lld - - - - +} // end namespace lld diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp index 615dfac3dfc..8b7026d50da 100644 --- a/lld/lib/ReaderWriter/Native/WriterNative.cpp +++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/WriterNative.h" +#include "lld/ReaderWriter/Writer.h" #include "lld/Core/File.h" #include "llvm/ADT/ArrayRef.h" @@ -28,7 +28,7 @@ namespace native { /// class Writer : public lld::Writer { public: - Writer(const WriterOptionsNative &options) {} + Writer(const TargetInfo &ti) {} virtual error_code writeFile(const lld::File &file, StringRef outPath) { // reserve first byte for unnamed atoms @@ -576,21 +576,9 @@ private: NameToOffsetVector _sectionNames; NameToOffsetVector _sharedLibraryNames; }; +} // end namespace native - -} // namespace native - -Writer* createWriterNative(const WriterOptionsNative &options) { - return new lld::native::Writer(options); -} - -WriterOptionsNative::WriterOptionsNative() { -} - -WriterOptionsNative::~WriterOptionsNative() { +std::unique_ptr<Writer> createWriterNative(const TargetInfo &ti) { + return std::unique_ptr<Writer>(new native::Writer(ti)); } - - -} // namespace lld - - +} // end namespace lld diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index 3058e81ec89..f9e473e31cc 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/ReaderPECOFF.h" +#include "lld/ReaderWriter/Reader.h" #include "lld/Core/File.h" #include "llvm/ADT/ArrayRef.h" @@ -359,7 +359,7 @@ private: class ReaderCOFF : public Reader { public: - ReaderCOFF(const ReaderOptionsPECOFF &options) {} + ReaderCOFF(const TargetInfo &ti) : Reader(ti) {} error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<std::unique_ptr<File>> &result) { @@ -373,22 +373,11 @@ public: return error_code::success(); } }; - -} // namespace anonymous - +} // end namespace anonymous namespace lld { - -Reader *createReaderPECOFF(const ReaderOptionsPECOFF &options) { - return new ReaderCOFF(options); +std::unique_ptr<Reader> createReaderPECOFF(const TargetInfo & ti, + std::function<ReaderFunc>) { + return std::unique_ptr<Reader>(new ReaderCOFF(ti)); } - -ReaderOptionsPECOFF::ReaderOptionsPECOFF() { } - -ReaderOptionsPECOFF::~ReaderOptionsPECOFF() { -} - -} // namespace lld - - diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index 8fec44e777b..f9163ea3c7b 100644 --- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp @@ -7,29 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "lld/ReaderWriter/WriterPECOFF.h" +#include "lld/ReaderWriter/Writer.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" namespace lld { -namespace pe_coff { - -// define PE/COFF writer class here - - -} // namespace pe_coff - -Writer* createWriterPECOFF(const WriterOptionsPECOFF &options) { - assert(0 && "PE/COFF support not implemented yet"); +std::unique_ptr<Writer> createWriterPECOFF(const TargetInfo &) { + llvm_unreachable("PE/COFF support not implemented yet"); return nullptr; } - -WriterOptionsPECOFF::WriterOptionsPECOFF() { -} - -WriterOptionsPECOFF::~WriterOptionsPECOFF() { -} - -} // namespace lld - +} // end namespace lld diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp index f4395e8ff38..29c1aec5196 100644 --- a/lld/lib/ReaderWriter/Reader.cpp +++ b/lld/lib/ReaderWriter/Reader.cpp @@ -14,29 +14,17 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/system_error.h" - namespace lld { - -Reader::Reader() { -} - Reader::~Reader() { } error_code Reader::readFile(StringRef path, - std::vector<std::unique_ptr<File>> &result) { + std::vector<std::unique_ptr<File>> &result) { OwningPtr<llvm::MemoryBuffer> opmb; - if ( error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb) ) + if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb)) return ec; std::unique_ptr<MemoryBuffer> mb(opmb.take()); return this->parseFile(std::move(mb), result); } - - - -ReaderOptions::ReaderOptions() { -} - -} // namespace lld - +} // end namespace lld diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp index 99955617396..0fe4c2d1930 100644 --- a/lld/lib/ReaderWriter/ReaderArchive.cpp +++ b/lld/lib/ReaderWriter/ReaderArchive.cpp @@ -9,7 +9,11 @@ #include "lld/ReaderWriter/ReaderArchive.h" +#include "lld/Core/ArchiveLibraryFile.h" +#include "lld/Core/LinkerOptions.h" + #include "llvm/ADT/Hashing.h" +#include "llvm/Object/ObjectFile.h" #include <unordered_map> @@ -46,8 +50,8 @@ public: std::vector<std::unique_ptr<File>> result; - if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer> - (ci->getBuffer()), result))) + LinkerInput li(std::unique_ptr<MemoryBuffer>(ci->getBuffer())); + if ((ec = _getReader(li)->parseFile(li.takeBuffer(), result))) return nullptr; assert(result.size() == 1); @@ -109,8 +113,8 @@ protected: } private: + std::function<ErrorOr<Reader&> (const LinkerInput &)> _getReader; std::unique_ptr<llvm::object::Archive> _archive; - const ReaderOptionsArchive _options; atom_collection_vector<DefinedAtom> _definedAtoms; atom_collection_vector<UndefinedAtom> _undefinedAtoms; atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; @@ -118,13 +122,13 @@ private: public: /// only subclasses of ArchiveLibraryFile can be instantiated - explicit FileArchive(llvm::MemoryBuffer *mb, - const ReaderOptionsArchive &options, - error_code &ec) - :ArchiveLibraryFile(mb->getBufferIdentifier()), - _options(options) { + FileArchive(const TargetInfo &ti, + std::function<ErrorOr<Reader&> (const LinkerInput &)> getReader, + std::unique_ptr<llvm::MemoryBuffer> mb, + error_code &ec) + : ArchiveLibraryFile(mb->getBufferIdentifier()), _getReader(getReader) { std::unique_ptr<llvm::object::Archive> archive_obj( - new llvm::object::Archive(mb, ec)); + new llvm::object::Archive(mb.release(), ec)); if (ec) return; _archive.swap(archive_obj); @@ -148,23 +152,23 @@ public: // Returns a vector of Files that are contained in the archive file // pointed to by the MemoryBuffer error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb, - std::vector<std::unique_ptr<File>> &result) { + std::vector<std::unique_ptr<File>> &result){ error_code ec; - if (_options.isForceLoad()) { + if (_options._forceLoadArchives) { _archive.reset(new llvm::object::Archive(mb.release(), ec)); if (ec) return ec; for (auto mf = _archive->begin_children(), me = _archive->end_children(); mf != me; ++mf) { - if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer> - (mf->getBuffer()), result))) + LinkerInput li(std::unique_ptr<MemoryBuffer>(mf->getBuffer())); + if ((ec = _getReader(li)->parseFile(li.takeBuffer(), result))) return ec; } } else { std::unique_ptr<File> f; - f.reset(new FileArchive(mb.release(), _options, ec)); + f.reset(new FileArchive(_targetInfo, _getReader, std::move(mb), ec)); if (ec) return ec; @@ -172,5 +176,4 @@ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb, } return llvm::error_code::success(); } - -} // namespace lld +} // end namespace lld diff --git a/lld/lib/ReaderWriter/Writer.cpp b/lld/lib/ReaderWriter/Writer.cpp index 93dbcf5f967..5b8be077d2f 100644 --- a/lld/lib/ReaderWriter/Writer.cpp +++ b/lld/lib/ReaderWriter/Writer.cpp @@ -9,17 +9,10 @@ #include "lld/ReaderWriter/Writer.h" - namespace lld { - Writer::Writer() { } Writer::~Writer() { } - -WriterOptions::WriterOptions() { -} - -} // namespace lld - +} // end namespace lld diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 310e8b41654..30e52d0c94c 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -8,14 +8,15 @@ //===----------------------------------------------------------------------===// +#include "lld/ReaderWriter/Reader.h" +#include "lld/ReaderWriter/Writer.h" + #include "lld/Core/ArchiveLibraryFile.h" #include "lld/Core/DefinedAtom.h" #include "lld/Core/Error.h" #include "lld/Core/File.h" #include "lld/Core/LLVM.h" #include "lld/Core/Reference.h" -#include "lld/ReaderWriter/ReaderYAML.h" -#include "lld/ReaderWriter/WriterYAML.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/OwningPtr.h" @@ -38,6 +39,7 @@ using llvm::yaml::IO; using llvm::yaml::SequenceTraits; using llvm::yaml::DocumentListTraits; +using namespace lld; /// The conversion of Atoms to and from YAML uses LLVM's YAML I/O. This /// file just defines template specializations on the lld types which control @@ -51,16 +53,11 @@ namespace { /// supplies contextual information. class ContextInfo { public: - ContextInfo(const lld::ReaderOptionsYAML &ro) - : _currentFile(nullptr), _readerOptions(&ro), _writerOptions(nullptr) { } - ContextInfo(const lld::WriterOptionsYAML &wo) - : _currentFile(nullptr), _readerOptions(nullptr), _writerOptions(&wo) { } - - lld::File *_currentFile; - const lld::ReaderOptionsYAML *_readerOptions; - const lld::WriterOptionsYAML *_writerOptions; -}; + ContextInfo(const TargetInfo &ti) : _currentFile(nullptr), _targetInfo(ti) {} + lld::File *_currentFile; + const TargetInfo &_targetInfo; +}; /// Used when writing yaml files. /// In most cases, atoms names are unambiguous, so references can just @@ -293,13 +290,17 @@ struct ScalarTraits<RefKind> { llvm::raw_ostream &out) { assert(ctxt != nullptr); ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt); - out << info->_writerOptions->kindToString(value); + auto relocStr = info->_targetInfo.stringFromRelocKind(value); + out << (relocStr ? *relocStr : "<unknown>"); } static StringRef input(StringRef scalar, void *ctxt, RefKind &value) { assert(ctxt != nullptr); ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt); - value = info->_readerOptions->kindFromString(scalar); + auto relocKind = info->_targetInfo.relocKindFromString(scalar); + if (!relocKind) + return "Invalid relocation kind"; + value = *relocKind; return StringRef(); } }; @@ -1260,8 +1261,7 @@ namespace yaml { class Writer : public lld::Writer { public: - Writer(const WriterOptionsYAML &options) : _options(options) { - } + Writer(const TargetInfo &ti) : _targetInfo(ti) {} virtual error_code writeFile(const lld::File &file, StringRef outPath) { // Create stream to path. @@ -1271,7 +1271,7 @@ public: return llvm::make_error_code(llvm::errc::no_such_file_or_directory); // Create yaml Output writer, using yaml options for context. - ContextInfo context(_options); + ContextInfo context(_targetInfo); llvm::yaml::Output yout(out, &context); // Write yaml output. @@ -1282,24 +1282,21 @@ public: } virtual StubsPass *stubPass() { - return _options.stubPass(); + return _targetInfo.getStubPass(); } virtual GOTPass *gotPass() { - return _options.gotPass(); + return _targetInfo.getGOTPass(); } private: - const WriterOptionsYAML &_options; + const TargetInfo &_targetInfo; }; - - class ReaderYAML : public Reader { public: - ReaderYAML(const ReaderOptionsYAML &options) : _options(options) { - } + ReaderYAML(const TargetInfo &ti) : Reader(ti) {} error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<std::unique_ptr<File>> &result) { @@ -1311,7 +1308,7 @@ public: // is deallocated. // Create YAML Input parser. - ContextInfo context(_options); + ContextInfo context(_targetInfo); llvm::yaml::Input yin(mb->getBuffer(), &context); // Fill vector with File objects created by parsing yaml. @@ -1329,38 +1326,14 @@ public: } return make_error_code(lld::yaml_reader_error::success); } - -private: - const ReaderOptionsYAML &_options; }; +} // end namespace yaml - - -} // namespace yaml - - -Writer *createWriterYAML(const WriterOptionsYAML &options) { - return new lld::yaml::Writer(options); +std::unique_ptr<Writer> createWriterYAML(const TargetInfo &ti) { + return std::unique_ptr<Writer>(new lld::yaml::Writer(ti)); } -WriterOptionsYAML::WriterOptionsYAML() { +std::unique_ptr<Reader> createReaderYAML(const TargetInfo &ti) { + return std::unique_ptr<Reader>(new lld::yaml::ReaderYAML(ti)); } - -WriterOptionsYAML::~WriterOptionsYAML() { -} - - - -Reader *createReaderYAML(const ReaderOptionsYAML &options) { - return new lld::yaml::ReaderYAML(options); -} - -ReaderOptionsYAML::ReaderOptionsYAML() { -} - -ReaderOptionsYAML::~ReaderOptionsYAML() { -} - - -} // namespace lld - +} // end namespace lld diff --git a/lld/test/elf/reloc.objtxt b/lld/test/elf/reloc.objtxt index 0f569248eaf..5dd776bd2ee 100644 --- a/lld/test/elf/reloc.objtxt +++ b/lld/test/elf/reloc.objtxt @@ -27,13 +27,13 @@ ELF-i386: section-name: .text.startup ELF-i386: - name: main ELF-i386: scope: global -ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24, -ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9, +ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24, +ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9, ELF-i386: C3 ] ELF-i386: section-choice: custom-required ELF-i386: section-name: .text.startup ELF-i386: references: -ELF-i386: - kind: ??? +ELF-i386: - kind: <unknown> ELF-i386: offset: 12 ELF-i386: target: .rodata.str1.1 ELF-i386: - kind: call32 @@ -42,7 +42,7 @@ ELF-i386: target: puts ELF-i386: - name: .comment ELF-i386: type: constant -ELF-i386: content: [ 00, 47, 43, 43, 3A, 20, 28, 47, 4E, 55, 29, 20, +ELF-i386: content: [ 00, 47, 43, 43, 3A, 20, 28, 47, 4E, 55, 29, 20, ELF-i386: 34, 2E, 37, 2E, 30, 00 ] ELF-i386: section-choice: custom-required ELF-i386: section-name: .comment @@ -52,10 +52,10 @@ ELF-i386: section-choice: custom-required ELF-i386: section-name: .note.GNU-stack ELF-i386: - name: .eh_frame -ELF-i386: content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, -ELF-i386: 01, 7C, 08, 01, 1B, 0C, 04, 04, 88, 01, 00, 00, -ELF-i386: 1C, 00, 00, 00, 1C, 00, 00, 00, 00, 00, 00, 00, -ELF-i386: 19, 00, 00, 00, 00, 41, 0E, 08, 85, 02, 42, 0D, +ELF-i386: content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, +ELF-i386: 01, 7C, 08, 01, 1B, 0C, 04, 04, 88, 01, 00, 00, +ELF-i386: 1C, 00, 00, 00, 1C, 00, 00, 00, 00, 00, 00, 00, +ELF-i386: 19, 00, 00, 00, 00, 41, 0E, 08, 85, 02, 42, 0D, ELF-i386: 05, 55, C5, 0C, 04, 04, 00, 00 ] ELF-i386: section-choice: custom-required ELF-i386: section-name: .eh_frame diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp index 4c82630a55e..68e7c3a534f 100644 --- a/lld/tools/lld-core/TestingHelpers.hpp +++ b/lld/tools/lld-core/TestingHelpers.hpp @@ -14,7 +14,7 @@ #include "lld/Core/LLVM.h" #include "lld/Core/Pass.h" #include "lld/Core/Resolver.h" -#include "lld/ReaderWriter/WriterYAML.h" +#include "lld/ReaderWriter/Writer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/CommandLine.h" @@ -246,7 +246,7 @@ private: struct TestingKindMapping { const char *string; - Reference::Kind value; + int32_t value; bool isBranch; bool isGotLoad; bool isGotUse; @@ -270,7 +270,7 @@ public: return true; } - virtual bool isCallSite(Reference::Kind kind) { + virtual bool isCallSite(int32_t kind) { for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { if (kind == p->value) return p->isBranch; @@ -300,7 +300,7 @@ public: return true; } - virtual bool isGOTAccess(Reference::Kind kind, bool &canBypassGOT) { + virtual bool isGOTAccess(int32_t kind, bool &canBypassGOT) { for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { if (kind == p->value) { canBypassGOT = p->isGotLoad; @@ -325,51 +325,4 @@ private: TestingPassFile _file; }; -class TestingWriterOptionsYAML : public lld::WriterOptionsYAML { -public: - TestingWriterOptionsYAML(bool stubs, bool got) - : _doStubs(stubs), _doGOT(got) { - } - - virtual StubsPass *stubPass() const { - if (_doStubs) - return const_cast<TestingStubsPass*>(&_stubsPass); - else - return nullptr; - } - - virtual GOTPass *gotPass() const { - if (_doGOT) - return const_cast<TestingGOTPass*>(&_gotPass); - else - return nullptr; - } - - virtual StringRef kindToString(Reference::Kind value) const { - for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (value == p->value) - return p->string; - } - return StringRef("???"); - } -private: - bool _doStubs; - bool _doGOT; - TestingStubsPass _stubsPass; - TestingGOTPass _gotPass; -}; - -class TestingReaderOptionsYAML : public lld::ReaderOptionsYAML { - virtual Reference::Kind kindFromString(StringRef kindName) const { - for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (kindName.equals(p->string)) - return p->value; - } - int k; - if (kindName.getAsInteger(0, k)) - k = 0; - return k; - } -}; - #endif // LLD_TOOLS_TESTING_HELPERS_H_ diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp index d50b9fcf6fa..11431b0e9a5 100644 --- a/lld/tools/lld-core/lld-core.cpp +++ b/lld/tools/lld-core/lld-core.cpp @@ -12,22 +12,15 @@ #include "lld/Core/LLVM.h" #include "lld/Core/Pass.h" #include "lld/Core/Resolver.h" -#include "lld/Core/TargetInfo.h" +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "lld/ReaderWriter/MachOTargetInfo.h" #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/ReaderArchive.h" -#include "lld/ReaderWriter/ReaderNative.h" -#include "lld/ReaderWriter/ReaderYAML.h" -#include "lld/ReaderWriter/ReaderELF.h" -#include "lld/ReaderWriter/ReaderPECOFF.h" -#include "lld/ReaderWriter/ReaderMachO.h" #include "lld/ReaderWriter/Writer.h" -#include "lld/ReaderWriter/WriterELF.h" -#include "lld/ReaderWriter/WriterMachO.h" -#include "lld/ReaderWriter/WriterNative.h" -#include "lld/ReaderWriter/WriterPECOFF.h" -#include "lld/ReaderWriter/WriterYAML.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -107,7 +100,8 @@ writeSelected("writer", clEnumValN(writeMachO, "mach-o", "link as darwin would"), clEnumValN(writePECOFF, "PECOFF", "link as windows would"), clEnumValN(writeELF, "ELF", "link as linux would"), - clEnumValEnd)); + clEnumValEnd), + llvm::cl::init(writeYAML)); enum ReaderChoice { readerYAML, readerMachO, readerPECOFF, readerELF @@ -120,7 +114,8 @@ readerSelected("reader", clEnumValN(readerMachO, "mach-o", "read as darwin would"), clEnumValN(readerPECOFF, "PECOFF", "read as windows would"), clEnumValN(readerELF, "ELF", "read as linux would"), - clEnumValEnd)); + clEnumValEnd), + llvm::cl::init(readerYAML)); enum ArchChoice { i386 = llvm::ELF::EM_386, @@ -140,7 +135,8 @@ archSelected("arch", "hexagon", "output Hexagon, EM_HEXAGON file"), clEnumValN(ppc, "ppc", "output PowerPC, EM_PPC file"), - clEnumValEnd)); + clEnumValEnd), + llvm::cl::init(i386)); enum endianChoice { @@ -156,7 +152,7 @@ endianSelected("endian", "output little endian format"), clEnumValEnd)); -class TestingTargetInfo LLVM_FINAL : public TargetInfo { +class TestingTargetInfo : public TargetInfo { public: TestingTargetInfo(const LinkerOptions &lo, bool stubs, bool got) : TargetInfo(lo), _doStubs(stubs), _doGOT(got) {} @@ -177,7 +173,7 @@ public: return nullptr; } - virtual ErrorOr<uint32_t> relocKindFromString(StringRef str) const { + virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const { // Try parsing as a number. if (auto kind = TargetInfo::relocKindFromString(str)) return kind; @@ -187,9 +183,9 @@ public: return llvm::make_error_code(llvm::errc::invalid_argument); } - virtual ErrorOr<std::string> stringFromRelocKind(uint32_t kind) const { + virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const { for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (kind == static_cast<uint32_t>(p->value)) + if (kind == p->value) return std::string(p->string); } return llvm::make_error_code(llvm::errc::invalid_argument); @@ -244,49 +240,32 @@ int main(int argc, char *argv[]) { TestingTargetInfo tti(lo, cmdLineDoStubsPass, cmdLineDoGotPass); - // create writer for final output, default to i386 if none selected - WriterOptionsELF writerOptionsELF(false, - endianSelected == big - ? llvm::support::big - : llvm::support::little, - llvm::ELF::ET_EXEC, - archSelected.getValue() == 0 - ? i386 - : archSelected); - - TestingWriterOptionsYAML writerOptionsYAML(cmdLineDoStubsPass, - cmdLineDoGotPass); - WriterOptionsMachO writerOptionsMachO; - WriterOptionsPECOFF writerOptionsPECOFF; - - Writer* writer = nullptr; + std::unique_ptr<ELFTargetInfo> eti = ELFTargetInfo::create(lo); + std::unique_ptr<MachOTargetInfo> mti = MachOTargetInfo::create(lo); + std::unique_ptr<Writer> writer; switch ( writeSelected ) { case writeYAML: - writer = createWriterYAML(writerOptionsYAML); + writer = createWriterYAML(tti); break; case writeMachO: - writer = createWriterMachO(writerOptionsMachO); + writer = createWriterMachO(*mti); break; case writePECOFF: - writer = createWriterPECOFF(writerOptionsPECOFF); + writer = createWriterPECOFF(tti); break; case writeELF: - writer = createWriterELF(writerOptionsELF); + writer = createWriterELF(*eti); break; } // create object to mange input files InputFiles inputFiles; - ReaderOptionsArchive readerOptionsArchive(cmdLineForceLoad); - // read input files into in-memory File objects - - TestingReaderOptionsYAML readerOptionsYAML; - Reader *reader = nullptr; + std::unique_ptr<Reader> reader; switch ( readerSelected ) { case readerYAML: - reader = createReaderYAML(readerOptionsYAML); + reader = createReaderYAML(tti); break; #if 0 case readerMachO: @@ -294,15 +273,19 @@ int main(int argc, char *argv[]) { break; #endif case readerPECOFF: - reader = createReaderPECOFF(lld::ReaderOptionsPECOFF()); + reader = createReaderPECOFF(tti, + [&] (const LinkerInput &) -> ErrorOr<Reader&> { + return *reader; + }); break; case readerELF: - reader = createReaderELF(lld::ReaderOptionsELF(), - readerOptionsArchive); - + reader = createReaderELF(*eti, + [&] (const LinkerInput &) -> ErrorOr<Reader&> { + return *reader; + }); break; default: - reader = createReaderYAML(readerOptionsYAML); + reader = createReaderYAML(tti); break; } @@ -342,14 +325,12 @@ int main(int argc, char *argv[]) { } // write as native file - WriterOptionsNative optionsNativeWriter; - Writer *natWriter = createWriterNative(optionsNativeWriter); + std::unique_ptr<Writer> natWriter = createWriterNative(tti); if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str()))) return 1; // read as native file - ReaderOptionsNative optionsNativeReader; - Reader *natReader = createReaderNative(optionsNativeReader); + std::unique_ptr<Reader> natReader = createReaderNative(tti); std::vector<std::unique_ptr<File>> readNativeFiles; if (error(natReader->readFile(tmpNativePath.c_str(), readNativeFiles))) return 1; |