From 3256d4ff621a14cfbb45f7206e84e5c018042a0a Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Fri, 25 Jan 2013 07:39:18 +0000 Subject: [PATCH] add elf targethandler llvm-svn: 173430 --- lld/include/lld/Core/ArchiveLibraryFile.h | 9 +- lld/include/lld/Core/File.h | 16 +- lld/include/lld/Core/Resolver.h | 17 +- lld/include/lld/Core/SharedLibraryFile.h | 11 +- lld/include/lld/ReaderWriter/ELFTargetInfo.h | 19 ++ lld/include/lld/ReaderWriter/Reader.h | 5 +- lld/include/lld/ReaderWriter/Simple.h | 2 +- lld/lib/Driver/Targets.cpp | 8 +- lld/lib/ReaderWriter/ELF/AtomsELF.h | 53 ++-- lld/lib/ReaderWriter/ELF/CMakeLists.txt | 18 ++ lld/lib/ReaderWriter/ELF/DefaultELFTargetHandler.h | 69 +++++ lld/lib/ReaderWriter/ELF/ELFTargetHandler.h | 142 +++++++++ lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp | 35 +-- lld/lib/ReaderWriter/ELF/ELFTargets.h | 17 ++ lld/lib/ReaderWriter/ELF/ExecutableAtoms.h | 27 +- lld/lib/ReaderWriter/ELF/FileELF.h | 333 +++++++++++++++++++++ lld/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt | 5 + .../ReaderWriter/ELF/Hexagon/HexagonELFTarget.h | 9 + .../ELF/Hexagon/HexagonELFTargetInfo.h | 36 +++ .../ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp | 0 lld/lib/ReaderWriter/ELF/PPC/CMakeLists.txt | 5 + lld/lib/ReaderWriter/ELF/PPC/PPCELFTarget.h | 9 + lld/lib/ReaderWriter/ELF/PPC/PPCELFTargetInfo.h | 38 +++ lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp | 0 lld/lib/ReaderWriter/ELF/ReaderELF.cpp | 323 ++------------------ lld/lib/ReaderWriter/ELF/WriterELF.cpp | 2 +- lld/lib/ReaderWriter/ELF/X86/CMakeLists.txt | 5 + lld/lib/ReaderWriter/ELF/X86/X86ELFTarget.h | 9 + lld/lib/ReaderWriter/ELF/X86/X86ELFTargetInfo.h | 34 +++ lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp | 0 lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt | 5 + lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTarget.h | 9 + .../ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h | 37 +++ .../ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp | 0 lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp | 2 +- lld/lib/ReaderWriter/MachO/StubsPass.hpp | 15 +- lld/lib/ReaderWriter/Native/ReaderNative.cpp | 74 +++-- lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp | 16 +- lld/lib/ReaderWriter/ReaderArchive.cpp | 8 +- lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 92 +++--- lld/tools/lld-core/TestingHelpers.hpp | 8 +- lld/tools/lld-core/lld-core.cpp | 4 +- 42 files changed, 1030 insertions(+), 496 deletions(-) create mode 100644 lld/lib/ReaderWriter/ELF/DefaultELFTargetHandler.h create mode 100644 lld/lib/ReaderWriter/ELF/ELFTargetHandler.h create mode 100644 lld/lib/ReaderWriter/ELF/ELFTargets.h create mode 100644 lld/lib/ReaderWriter/ELF/FileELF.h create mode 100644 lld/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt create mode 100644 lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTarget.h create mode 100644 lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTargetInfo.h create mode 100644 lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp create mode 100644 lld/lib/ReaderWriter/ELF/PPC/CMakeLists.txt create mode 100644 lld/lib/ReaderWriter/ELF/PPC/PPCELFTarget.h create mode 100644 lld/lib/ReaderWriter/ELF/PPC/PPCELFTargetInfo.h create mode 100644 lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp create mode 100644 lld/lib/ReaderWriter/ELF/X86/CMakeLists.txt create mode 100644 lld/lib/ReaderWriter/ELF/X86/X86ELFTarget.h create mode 100644 lld/lib/ReaderWriter/ELF/X86/X86ELFTargetInfo.h create mode 100644 lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp create mode 100644 lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt create mode 100644 lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTarget.h create mode 100644 lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h create mode 100644 lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp diff --git a/lld/include/lld/Core/ArchiveLibraryFile.h b/lld/include/lld/Core/ArchiveLibraryFile.h index e385e80..a69e0d5 100644 --- a/lld/include/lld/Core/ArchiveLibraryFile.h +++ b/lld/include/lld/Core/ArchiveLibraryFile.h @@ -39,9 +39,16 @@ public: /// specified name and return the File object for that member, or nullptr. virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0; + virtual const TargetInfo &getTargetInfo() const { return _targetInfo; } + protected: /// only subclasses of ArchiveLibraryFile can be instantiated - ArchiveLibraryFile(StringRef path) : File(path) { } + ArchiveLibraryFile(const TargetInfo &ti, StringRef path) + : File(path), _targetInfo(ti) { + } + +private: + const TargetInfo &_targetInfo; }; } // namespace lld diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h index 5b183d5..4242c20 100644 --- a/lld/include/lld/Core/File.h +++ b/lld/include/lld/Core/File.h @@ -14,6 +14,7 @@ #include "lld/Core/DefinedAtom.h" #include "lld/Core/range.h" #include "lld/Core/SharedLibraryAtom.h" +#include "lld/Core/TargetInfo.h" #include "lld/Core/UndefinedAtom.h" #include "llvm/ADT/StringRef.h" @@ -152,11 +153,12 @@ public: /// all AbsoluteAtoms in this File. virtual const atom_collection &absolute() const = 0; + virtual const TargetInfo &getTargetInfo() const = 0; + protected: /// \brief only subclasses of File can be instantiated File(StringRef p) : _path(p), _ordinal(UINT64_MAX) {} - /// \brief This is a convenience class for File subclasses which manage their /// atoms as a simple std::vector<>. template @@ -217,14 +219,18 @@ public: /// \brief Add an atom to the file. Invalidates iterators for all returned /// containters. virtual void addAtom(const Atom&) = 0; - - typedef range::iterator> DefinedAtomRange; + + typedef range::iterator> DefinedAtomRange; virtual DefinedAtomRange definedAtoms() = 0; - + + virtual const TargetInfo &getTargetInfo() const { return _targetInfo; } protected: /// \brief only subclasses of MutableFile can be instantiated - MutableFile(StringRef p) : File(p) {} + MutableFile(const TargetInfo &ti, StringRef p) : File(p), _targetInfo(ti) {} + +private: + const TargetInfo &_targetInfo; }; } // end namespace lld diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h index 95ccd2c..0d73100 100644 --- a/lld/include/lld/Core/Resolver.h +++ b/lld/include/lld/Core/Resolver.h @@ -29,12 +29,10 @@ class TargetInfo; class Resolver : public InputFiles::Handler { public: Resolver(const TargetInfo &ti, const InputFiles &inputs) - : _targetInfo(ti) - , _inputFiles(inputs) - , _symbolTable(ti) - , _haveLLVMObjs(false) - , _addToFinalSection(false) - , _completedInitialObjectFiles(false) {} + : _targetInfo(ti), _inputFiles(inputs), _symbolTable(ti), _result(ti), + _haveLLVMObjs(false), _addToFinalSection(false), + _completedInitialObjectFiles(false) { + } // InputFiles::Handler methods virtual void doDefinedAtom(const class DefinedAtom&); @@ -65,13 +63,12 @@ private: void markLive(const Atom &atom); void addAtoms(const std::vector&); - class MergedFile : public MutableFile { public: - MergedFile() : MutableFile("") { } + MergedFile(const TargetInfo &ti) : MutableFile(ti, "") {} - virtual const atom_collection& defined() const { - return _definedAtoms; + virtual const atom_collection &defined() const { + return _definedAtoms; } virtual const atom_collection& undefined() const { return _undefinedAtoms; diff --git a/lld/include/lld/Core/SharedLibraryFile.h b/lld/include/lld/Core/SharedLibraryFile.h index 9d08b0f..0303363 100644 --- a/lld/include/lld/Core/SharedLibraryFile.h +++ b/lld/include/lld/Core/SharedLibraryFile.h @@ -40,11 +40,16 @@ public: /// Check if the shared library exports a symbol with the specified name. /// If so, return a SharedLibraryAtom which represents that exported /// symbol. Otherwise return nullptr. - virtual const SharedLibraryAtom *exports(StringRef name, - bool dataSymbolOnly) const; + virtual const SharedLibraryAtom *exports(StringRef name, + bool dataSymbolOnly) const; protected: /// only subclasses of SharedLibraryFile can be instantiated - SharedLibraryFile(StringRef path) : File(path) { } + SharedLibraryFile(const TargetInfo &ti, StringRef path) + : File(path), _targetInfo(ti) { + } + +private: + const TargetInfo &_targetInfo; }; } // namespace lld diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h index be877d3..37874c0 100644 --- a/lld/include/lld/ReaderWriter/ELFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -11,10 +11,20 @@ #define LLD_READER_WRITER_ELF_TARGET_INFO_H #include "lld/Core/TargetInfo.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ELF.h" #include namespace lld { + +namespace elf { template class ELFTargetHandler; } + +class ELFTargetHandlerBase { +public: + virtual ~ELFTargetHandlerBase() {} +}; + class ELFTargetInfo : public TargetInfo { protected: ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {} @@ -24,6 +34,15 @@ public: uint16_t getOutputMachine() const; static std::unique_ptr create(const LinkerOptions &lo); + + template + lld::elf::ELFTargetHandler &getTargetHandler() const { + return static_cast< + lld::elf::ELFTargetHandler &>(*_targetHandler.get()); + } + +protected: + std::unique_ptr _targetHandler; }; } // end namespace lld diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h index c1f6084..2f10fe6 100644 --- a/lld/include/lld/ReaderWriter/Reader.h +++ b/lld/include/lld/ReaderWriter/Reader.h @@ -18,6 +18,7 @@ #include namespace lld { +class ELFTargetInfo; class File; class LinkerInput; struct LinkerOptions; @@ -51,9 +52,9 @@ protected: const LinkerOptions &_options; }; -typedef ErrorOr ReaderFunc(const LinkerInput &); +typedef ErrorOr ReaderFunc(const LinkerInput &); -std::unique_ptr createReaderELF(const TargetInfo &, +std::unique_ptr createReaderELF(const ELFTargetInfo &, std::function); std::unique_ptr createReaderMachO(const TargetInfo &, std::function); diff --git a/lld/include/lld/ReaderWriter/Simple.h b/lld/include/lld/ReaderWriter/Simple.h index 7ebddba..be611d6 100644 --- a/lld/include/lld/ReaderWriter/Simple.h +++ b/lld/include/lld/ReaderWriter/Simple.h @@ -23,7 +23,7 @@ namespace lld { class SimpleFile : public MutableFile { public: - SimpleFile(StringRef path) : MutableFile(path) {} + SimpleFile(const TargetInfo &ti, StringRef path) : MutableFile(ti, path) {} virtual void addAtom(const Atom &atom) { if (const DefinedAtom *defAtom = dyn_cast(&atom)) { diff --git a/lld/lib/Driver/Targets.cpp b/lld/lib/Driver/Targets.cpp index 55ae206..2e2bc59 100644 --- a/lld/lib/Driver/Targets.cpp +++ b/lld/lib/Driver/Targets.cpp @@ -33,12 +33,12 @@ class ELFTarget : public Target { public: ELFTarget(std::unique_ptr ti) : Target(std::unique_ptr(ti.get())), - _elfTargetInfo(*ti.release()), - _readerELF(createReaderELF( - *_targetInfo, std::bind(&ELFTarget::getReader, this, _1))), + _elfTargetInfo(*ti.release()), _readerELF(createReaderELF( + _elfTargetInfo, std::bind(&ELFTarget::getReader, this, _1))), _readerYAML(createReaderYAML(*_targetInfo)), _writer(createWriterELF(_elfTargetInfo)), - _writerYAML(createWriterYAML(*_targetInfo)) {} + _writerYAML(createWriterYAML(*_targetInfo)) { + } virtual ErrorOr getReader(const LinkerInput &input) { auto kind = input.getKind(); diff --git a/lld/lib/ReaderWriter/ELF/AtomsELF.h b/lld/lib/ReaderWriter/ELF/AtomsELF.h index b4f0a5d..58f2fa6 100644 --- a/lld/lib/ReaderWriter/ELF/AtomsELF.h +++ b/lld/lib/ReaderWriter/ELF/AtomsELF.h @@ -1,15 +1,20 @@ -#ifndef LLD_ELFATOMS_H_ -#define LLD_ELFATOMS_H_ +#ifndef LLD_ELFATOMS_H +#define LLD_ELFATOMS_H #include "lld/Core/LLVM.h" +#include "ELFTargetHandler.h" + #include #include namespace lld { + +template class FileELF; + +namespace elf { template class ELFTargetAtomHandler; } /// \brief Relocation References: Defined Atoms may contain references that will /// need to be patched before the executable is written. -template -class ELFReference LLVM_FINAL : public Reference { +template class ELFReference LLVM_FINAL : public Reference { typedef llvm::object::Elf_Rel_Impl Elf_Rel; typedef llvm::object::Elf_Rel_Impl Elf_Rela; public: @@ -76,21 +81,14 @@ class ELFAbsoluteAtom LLVM_FINAL : public AbsoluteAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; public: - ELFAbsoluteAtom(const File &file, - llvm::StringRef name, - const Elf_Sym *symbol, - uint64_t value) - : _owningFile(file) - , _name(name) - , _symbol(symbol) - , _value(value) - {} - - virtual const class File &file() const { - return _owningFile; + ELFAbsoluteAtom(const FileELF &file, llvm::StringRef name, + const Elf_Sym *symbol, uint64_t value) + : _owningFile(file), _name(name), _symbol(symbol), _value(value) { } - virtual Scope scope() const { + virtual const class FileELF &file() const { + return _owningFile; + } virtual Scope scope() const { if (_symbol->st_other == llvm::ELF::STV_HIDDEN) return scopeLinkageUnit; if (_symbol->getBinding() == llvm::ELF::STB_LOCAL) @@ -108,7 +106,7 @@ public: } private: - const File &_owningFile; + const FileELF &_owningFile; llvm::StringRef _name; const Elf_Sym *_symbol; uint64_t _value; @@ -121,13 +119,9 @@ class ELFUndefinedAtom LLVM_FINAL : public UndefinedAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; public: - ELFUndefinedAtom(const File &file, - llvm::StringRef name, + ELFUndefinedAtom(const FileELF &file, llvm::StringRef name, const Elf_Sym *symbol) - : _owningFile(file) - , _name(name) - , _symbol(symbol) - {} + : _owningFile(file), _name(name), _symbol(symbol) {} virtual const class File &file() const { return _owningFile; @@ -236,6 +230,17 @@ public: ContentType ret = typeUnknown; uint64_t flags = _section->sh_flags; + if (_symbol->st_shndx > llvm::ELF::SHN_LOPROC && + _symbol->st_shndx < llvm::ELF::SHN_HIPROC) { + const ELFTargetInfo &eti = + static_cast(_owningFile.getTargetInfo()); + elf::ELFTargetHandler &elfTargetHandler = + eti.getTargetHandler(); + elf::ELFTargetAtomHandler &elfAtomHandler = + elfTargetHandler.targetAtomHandler(); + return elfAtomHandler.contentType(this); + } + if (_symbol->getType() == llvm::ELF::STT_GNU_IFUNC) return typeResolver; diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt index b12d564..cbbffd7 100644 --- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt +++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt @@ -1,3 +1,21 @@ +file(GLOB all_valid_subdirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/CMakeLists.txt") + +foreach(dir ${all_valid_subdirs}) + message(STATUS "AUTOADD ELFTarget = ${dir}") + if(${dir} MATCHES "^([^/]*)//CMakeLists.txt") + string(REGEX REPLACE "^([^/]*)//CMakeLists.txt" "\\1" dir_trimmed ${dir}) + include_directories(AFTER + ${CMAKE_CURRENT_SOURCE_DIR}/${dir_trimmed}) + endif() +endforeach(dir) + +foreach(dir ${all_valid_subdirs}) + if(${dir} MATCHES "^([^/]*)//CMakeLists.txt") + string(REGEX REPLACE "^([^/]*)//CMakeLists.txt" "\\1" dir_trimmed ${dir}) + add_subdirectory(${dir_trimmed}) + endif() +endforeach(dir) + add_lld_library(lldELF ELFTargetInfo.cpp HexagonReference.cpp diff --git a/lld/lib/ReaderWriter/ELF/DefaultELFTargetHandler.h b/lld/lib/ReaderWriter/ELF/DefaultELFTargetHandler.h new file mode 100644 index 0000000..b70901c --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/DefaultELFTargetHandler.h @@ -0,0 +1,69 @@ +//===- lib/ReaderWriter/ELF/DefaultELFTargetHandler.h ---------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLD_READER_WRITER_DEFAULT_ELF_TARGETHANDLER_H +#define LLD_READER_WRITER_DEFAULT_ELF_TARGETHANDLER_H + +#include "lld/ReaderWriter/ELFTargetInfo.h" + +#include "lld/Core/LinkerOptions.h" + +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ELF.h" + +#include "DefaultELFLayout.h" +#include "ELFTargetHandler.h" + +namespace lld { +namespace elf { + +template +class DefaultELFTargetHandler : public ELFTargetHandler { + +public: + DefaultELFTargetHandler(ELFTargetInfo &targetInfo) + : ELFTargetHandler(targetInfo) { + } + + bool doesOverrideELFHeader() { return false; } + + void setELFHeaderInfo(ELFHeader *elfHeader) { + llvm_unreachable("Target should provide implementation for function "); + } + + /// ELFTargetLayout + ELFTargetLayout &targetLayout() { + llvm_unreachable("Target should provide implementation for function "); + } + + /// ELFTargetAtomHandler + ELFTargetAtomHandler &targetAtomHandler() { + llvm_unreachable("Target should provide implementation for function "); + } + + /// Create a set of Default target sections that a target might needj + void createDefaultSections() {} + + /// \brief Add a section to the current Layout + void addSection(Section *section) {} + + /// \brief add new symbol file + void addFiles(InputFiles &) {} + + /// \brief Finalize the symbol values + void finalizeSymbolValues() {} + + /// \brief allocate Commons, some architectures may move small common + /// symbols over to small data, this would also be used + void allocateCommons() {} +}; + +} // elf +} // lld + +#endif diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetHandler.h b/lld/lib/ReaderWriter/ELF/ELFTargetHandler.h new file mode 100644 index 0000000..641350b --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/ELFTargetHandler.h @@ -0,0 +1,142 @@ +//===- lib/ReaderWriter/ELF/ELFTargetHandler.h -----------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLD_READER_WRITER_ELF_TARGETHANDLER_H +#define LLD_READER_WRITER_ELF_TARGETHANDLER_H + +#include "lld/Core/LinkerOptions.h" +#include "lld/Core/LLVM.h" +#include "lld/Core/TargetInfo.h" +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "DefaultELFLayout.h" +#include "AtomsELF.h" + +#include +#include + +/// \brief All ELF targets would want to override the way the ELF file gets +/// processed by the linker. This class serves as an interface which would be +/// used to derive the needed functionality of a particular target/platform. + +/// \brief The target registers a set of handlers for overriding target specific +/// attributes for a DefinedAtom. The Reader uses this class to query for the +/// type of atom and its permissions + +namespace lld { + +template class ELFDefinedAtom; + +namespace elf { + +template class ELFTargetAtomHandler { +public: + typedef llvm::object::Elf_Sym_Impl Elf_Sym; + + virtual DefinedAtom::ContentType contentType( + const lld::ELFDefinedAtom *atom) const { + return atom->contentType(); + } + + virtual DefinedAtom::ContentType contentType(const Elf_Sym *sym) const { + return DefinedAtom::typeZeroFill; + } + + virtual DefinedAtom::ContentPermissions contentPermissions( + const lld::ELFDefinedAtom *atom) const { + return atom->permissions(); + } +}; + +/// \brief The target can override certain functions in the DefaultELFLayout +/// class so that the order, the name of the section and the segment type could +/// be changed in the final layout +template class ELFTargetLayout : public DefaultELFLayout { +public: + ELFTargetLayout(ELFTargetInfo &targetInfo, DefaultELFLayout &layout) + : _targetInfo(targetInfo), _layout(layout) { + } + + /// isTargetSection provides a way to determine if the section that + /// we are processing has been registered by the target and the target + /// wants to handle them. + /// For example: the Writer may be processing a section but the target + /// might want to override the functionality on how atoms are inserted + /// into the section. Such sections are set the K_TargetSection flag in + /// the SectionKind after they are created + virtual bool isTargetSection(const StringRef name, const int32_t contentType, + const int32_t contentPermissions) = 0; + + /// The target may want to override the sectionName to a different + /// section Name in the output + virtual StringRef sectionName(const StringRef name, const int32_t contentType, + const int32_t contentPermissions) = 0; + + /// The target may want to override the section order that has been + /// set by the DefaultLayout + virtual ELFLayout::SectionOrder getSectionOrder( + const StringRef name, int32_t contentType, + int32_t contentPermissions) = 0; + + /// The target can set the segment type for a Section + virtual ELFLayout::SegmentType segmentType(Section *section) const = 0; + + /// Returns true/false depending on whether the section has a Output + // segment or not + bool hasOutputSegment(Section *section) = 0; + +private: + const ELFTargetInfo &_targetInfo; + const DefaultELFLayout &_layout; +}; + +/// \brief An interface to override functions that are provided by the +/// the default ELF Layout +template class ELFTargetHandler : public ELFTargetHandlerBase { + +public: + + ELFTargetHandler(ELFTargetInfo &targetInfo) : _targetInfo(targetInfo) {} + + /// If the target overrides ELF header information, this API would + /// return true, so that the target can set all fields specific to + /// that target + virtual bool doesOverrideELFHeader() = 0; + + /// Set the ELF Header information + virtual void setELFHeaderInfo(ELFHeader *elfHeader) = 0; + + /// ELFTargetLayout + virtual ELFTargetLayout &targetLayout() = 0; + + /// ELFTargetAtomHandler + virtual ELFTargetAtomHandler &targetAtomHandler() = 0; + + /// Create a set of Default target sections that a target might needj + virtual void createDefaultSections() = 0; + + /// \brief Add a section to the current Layout + virtual void addSection(Section *section) = 0; + + /// \brief add new symbol file + virtual void addFiles(InputFiles &) = 0; + + /// \brief Finalize the symbol values + virtual void finalizeSymbolValues() = 0; + + /// \brief allocate Commons, some architectures may move small common + /// symbols over to small data, this would also be used + virtual void allocateCommons() = 0; + +protected: + const ELFTargetInfo &_targetInfo; +}; + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_TARGETHANDLER_H diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp index 5c4cbfc..cb398eb 100644 --- a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp +++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp @@ -14,6 +14,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/Support/ELF.h" +#include "ELFTargetHandler.h" +#include "ELFTargets.h" + namespace lld { uint16_t ELFTargetInfo::getOutputType() const { switch (_options._outputKind) { @@ -49,38 +52,18 @@ uint16_t ELFTargetInfo::getOutputMachine() const { } } -class X86ELFTargetInfo LLVM_FINAL : public ELFTargetInfo { -public: - X86ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} - - virtual uint64_t getPageSize() const { return 0x1000; } -}; - -class HexagonELFTargetInfo LLVM_FINAL : public ELFTargetInfo { -public: - HexagonELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} - - virtual uint64_t getPageSize() const { return 0x1000; } -}; - -class PPCELFTargetInfo LLVM_FINAL : public ELFTargetInfo { -public: - PPCELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {} - - virtual bool isLittleEndian() const { return false; } - - virtual uint64_t getPageSize() const { return 0x1000; } -}; - std::unique_ptr ELFTargetInfo::create(const LinkerOptions &lo) { switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) { case llvm::Triple::x86: + return std::unique_ptr(new lld::elf::X86ELFTargetInfo(lo)); case llvm::Triple::x86_64: - return std::unique_ptr(new X86ELFTargetInfo(lo)); + return std::unique_ptr< + ELFTargetInfo>(new lld::elf::X86_64ELFTargetInfo(lo)); case llvm::Triple::hexagon: - return std::unique_ptr(new HexagonELFTargetInfo(lo)); + return std::unique_ptr< + ELFTargetInfo>(new lld::elf::HexagonELFTargetInfo(lo)); case llvm::Triple::ppc: - return std::unique_ptr(new PPCELFTargetInfo(lo)); + return std::unique_ptr(new lld::elf::PPCELFTargetInfo(lo)); default: return std::unique_ptr(); } diff --git a/lld/lib/ReaderWriter/ELF/ELFTargets.h b/lld/lib/ReaderWriter/ELF/ELFTargets.h new file mode 100644 index 0000000..6ab1c1e --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/ELFTargets.h @@ -0,0 +1,17 @@ +//===- lib/ReaderWriter/ELF/ELFTargets.h ----------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLD_READER_WRITER_ELF_TARGETS_H +#define LLD_READER_WRITER_ELF_TARGETS_H + +#include "X86ELFTarget.h" +#include "X86_64ELFTarget.h" +#include "HexagonELFTarget.h" +#include "PPCELFTarget.h" + +#endif diff --git a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h index f0531ac..930b7f4 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h @@ -10,13 +10,13 @@ #ifndef LLD_READER_WRITER_ELF_EXECUTABLE_ATOM_H_ #define LLD_READER_WRITER_ELF_EXECUTABLE_ATOM_H_ - #include "lld/Core/DefinedAtom.h" -#include "lld/Core/UndefinedAtom.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" +#include "lld/Core/UndefinedAtom.h" #include "lld/ReaderWriter/Writer.h" #include "AtomsELF.h" +#include "FileELF.h" namespace lld { namespace elf { @@ -26,12 +26,11 @@ namespace elf { /// are basically additional symbols required by libc and other runtime /// libraries part of executing a program. This class provides support /// for adding absolute symbols and undefined symbols -template -class CRuntimeFile : public File { +template class CRuntimeFileELF : public FileELF { public: typedef llvm::object::Elf_Sym_Impl Elf_Sym; - CRuntimeFile(const ELFTargetInfo &) : File("C runtime") {} - + CRuntimeFileELF(const ELFTargetInfo &ti) : FileELF(ti, "C runtime") {} + /// \brief add a global absolute atom void addAbsoluteAtom(const StringRef symbolName) { Elf_Sym *symbol = new(_allocator.Allocate()) Elf_Sym; @@ -64,19 +63,19 @@ public: _undefinedAtoms._atoms.push_back(newAtom); } - const atom_collection &defined() const { + const File::atom_collection &defined() const { return _definedAtoms; } - const atom_collection &undefined() const { + const File::atom_collection &undefined() const { return _undefinedAtoms; } - const atom_collection &sharedLibrary() const { + const File::atom_collection &sharedLibrary() const { return _sharedLibraryAtoms; } - const atom_collection &absolute() const { + const File::atom_collection &absolute() const { return _absoluteAtoms; } @@ -87,10 +86,10 @@ public: private: llvm::BumpPtrAllocator _allocator; - atom_collection_vector _definedAtoms; - atom_collection_vector _undefinedAtoms; - atom_collection_vector _sharedLibraryAtoms; - atom_collection_vector _absoluteAtoms; + File::atom_collection_vector _definedAtoms; + File::atom_collection_vector _undefinedAtoms; + File::atom_collection_vector _sharedLibraryAtoms; + File::atom_collection_vector _absoluteAtoms; }; } // namespace elf diff --git a/lld/lib/ReaderWriter/ELF/FileELF.h b/lld/lib/ReaderWriter/ELF/FileELF.h new file mode 100644 index 0000000..0b81684 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/FileELF.h @@ -0,0 +1,333 @@ +//===- lib/ReaderWriter/ELF/FileELF.h ------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \brief Read a binary, find out based on the symbol table contents what kind +/// of symbol it is and create corresponding atoms for it + +#ifndef LLD_READER_WRITER_FILE_ELF_H +#define LLD_READER_WRITER_FILE_ELF_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" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "AtomsELF.h" + +namespace lld { + +template class FileELF : public File { + typedef llvm::object::Elf_Sym_Impl Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; + typedef llvm::object::Elf_Rel_Impl Elf_Rel; + typedef llvm::object::Elf_Rel_Impl Elf_Rela; + +public: + FileELF(const ELFTargetInfo &ti, const StringRef name) + : File(name), _elfTargetInfo(ti) { + } + + FileELF(const ELFTargetInfo &ti, std::unique_ptr MB, + llvm::error_code &EC) + : File(MB->getBufferIdentifier()), _elfTargetInfo(ti) { + llvm::OwningPtr binaryFile; + EC = createBinary(MB.release(), binaryFile); + if (EC) + return; + + // Point Obj to correct class and bitwidth ELF object + _objFile.reset( + llvm::dyn_cast >(binaryFile.get())); + + if (!_objFile) { + EC = make_error_code(llvm::object::object_error::invalid_file_type); + return; + } + + binaryFile.take(); + + std::map > sectionSymbols; + + // Handle: SHT_REL and SHT_RELA sections: + // Increment over the sections, when REL/RELA section types are found add + // the contents to the RelocationReferences map. + llvm::object::section_iterator sit(_objFile->begin_sections()); + llvm::object::section_iterator sie(_objFile->end_sections()); + for (; sit != sie; sit.increment(EC)) { + if (EC) + return; + + const Elf_Shdr *section = _objFile->getElfSection(sit); + + if (section->sh_type == llvm::ELF::SHT_RELA) { + llvm::StringRef sectionName; + if ((EC = _objFile->getSectionName(section, sectionName))) + return; + // Get rid of the leading .rela so Atoms can use their own section + // name to find the relocs. + sectionName = sectionName.drop_front(5); + + auto rai(_objFile->beginELFRela(section)); + auto rae(_objFile->endELFRela(section)); + + auto &Ref = _relocationAddendRefences[sectionName]; + for (; rai != rae; ++rai) { + Ref.push_back(&*rai); + } + } + + if (section->sh_type == llvm::ELF::SHT_REL) { + llvm::StringRef sectionName; + if ((EC = _objFile->getSectionName(section, sectionName))) + return; + // Get rid of the leading .rel so Atoms can use their own section + // name to find the relocs. + sectionName = sectionName.drop_front(4); + + auto ri(_objFile->beginELFRel(section)); + auto re(_objFile->endELFRel(section)); + + auto &Ref = _relocationReferences[sectionName]; + for (; ri != re; ++ri) { + Ref.push_back(&*ri); + } + } + } + + // Increment over all the symbols collecting atoms and symbol names for + // later use. + llvm::object::symbol_iterator it(_objFile->begin_symbols()); + llvm::object::symbol_iterator ie(_objFile->end_symbols()); + + for (; it != ie; it.increment(EC)) { + if (EC) + return; + + if ((EC = it->getSection(sit))) + return; + + const Elf_Shdr *section = _objFile->getElfSection(sit); + const Elf_Sym *symbol = _objFile->getElfSymbol(it); + + llvm::StringRef symbolName; + if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) + return; + + if (symbol->st_shndx == llvm::ELF::SHN_ABS) { + // Create an absolute atom. + auto *newAtom = new (_readerStorage) + ELFAbsoluteAtom(*this, symbolName, symbol, symbol->st_value); + + _absoluteAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); + } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) { + // Create an undefined atom. + auto *newAtom = new (_readerStorage) + ELFUndefinedAtom(*this, symbolName, symbol); + + _undefinedAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); + } else { + // This is actually a defined symbol. Add it to its section's list of + // symbols. + if (symbol->getType() == llvm::ELF::STT_NOTYPE || symbol->getType() == + llvm::ELF::STT_OBJECT || symbol->getType() == llvm::ELF::STT_FUNC || + symbol->getType() == llvm::ELF::STT_GNU_IFUNC || + symbol->getType() == llvm::ELF::STT_SECTION || symbol->getType() == + llvm::ELF::STT_FILE || symbol->getType() == llvm::ELF::STT_TLS || + symbol->getType() == llvm::ELF::STT_COMMON || + symbol->st_shndx == llvm::ELF::SHN_COMMON) { + sectionSymbols[section].push_back(symbol); + } else { + llvm::errs() << "Unable to create atom for: " << symbolName << "\n"; + EC = llvm::object::object_error::parse_failed; + return; + } + } + } + + for (auto &i : sectionSymbols) { + auto &symbols = i.second; + // Sort symbols by position. + std::stable_sort(symbols.begin(), symbols.end(), + [](const Elf_Sym * A, const Elf_Sym * B) { + return A->st_value < B->st_value; + }); + + StringRef sectionContents; + if ((EC = _objFile->getSectionContents(i.first, sectionContents))) + return; + + llvm::StringRef sectionName; + if ((EC = _objFile->getSectionName(i.first, sectionName))) + return; + + // i.first is the section the symbol lives in + for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { + llvm::StringRef symbolName; + if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) + return; + + bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON || + (*si)->st_shndx == llvm::ELF::SHN_COMMON; + + DefinedAtom::ContentType c; + + if (((*si)->st_shndx >= llvm::ELF::SHN_LOPROC) && + ((*si)->st_shndx <= llvm::ELF::SHN_HIPROC)) { + elf::ELFTargetHandler &elfTargetHandler = + _elfTargetInfo.getTargetHandler(); + elf::ELFTargetAtomHandler &elfAtomHandler = + elfTargetHandler.targetAtomHandler(); + c = elfAtomHandler.contentType(*si); + + if (c == DefinedAtom::typeZeroFill) + isCommon = true; + } + + // Get the symbol's content: + uint64_t contentSize; + if (si + 1 == se) { + // if this is the last symbol, take up the remaining data. + contentSize = isCommon ? 0 : i.first->sh_size - (*si)->st_value; + } else { + contentSize = isCommon ? 0 : (*(si + 1))->st_value - (*si)->st_value; + } + + // Don't allocate content to a weak symbol, as they may be merged away. + // Create an anonymous atom to hold the data. + ELFDefinedAtom *anonAtom = nullptr; + if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) { + // Create a new non-weak ELF symbol. + auto sym = new (_readerStorage) Elf_Sym; + *sym = **si; + sym->setBinding(llvm::ELF::STB_GLOBAL); + anonAtom = createDefinedAtomAndAssignRelocations( + "", sectionName, sym, i.first, + ArrayRef((uint8_t *)sectionContents.data() + + (*si)->st_value, contentSize)); + contentSize = 0; + } + + ArrayRef symbolData = ArrayRef( + (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize); + + auto newAtom = createDefinedAtomAndAssignRelocations( + symbolName, sectionName, *si, i.first, symbolData); + + _definedAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair((*si), newAtom)); + if (anonAtom) + _definedAtoms._atoms.push_back(anonAtom); + } + } + + // All the Atoms and References are created. Now update each Reference's + // target with the Atom pointer it refers to. + for (auto &ri : _references) { + const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex()); + ri->setTarget(findAtom(Symbol)); + } + } + + virtual const atom_collection &defined() const { + return _definedAtoms; + } + + virtual const atom_collection &undefined() const { + return _undefinedAtoms; + } + + virtual const atom_collection &sharedLibrary() const { + return _sharedLibraryAtoms; + } + + virtual const atom_collection &absolute() const { + return _absoluteAtoms; + } + + virtual const ELFTargetInfo &getTargetInfo() const { return _elfTargetInfo; } + + Atom *findAtom(const Elf_Sym *symbol) { + return _symbolToAtomMapping.lookup(symbol); + } + +private: + ELFDefinedAtom *createDefinedAtomAndAssignRelocations( + StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol, + const Elf_Shdr *section, ArrayRef content) { + unsigned int referenceStart = _references.size(); + + // Only relocations that are inside the domain of the atom are added. + + // Add Rela (those with r_addend) references: + for (auto &rai : _relocationAddendRefences[sectionName]) { + if (!((rai->r_offset >= symbol->st_value) && + (rai->r_offset < symbol->st_value + content.size()))) + continue; + auto *ERef = new (_readerStorage) + ELFReference(rai, rai->r_offset - symbol->st_value, nullptr); + _references.push_back(ERef); + } + + // Add Rel references. + for (auto &ri : _relocationReferences[sectionName]) { + if ((ri->r_offset >= symbol->st_value) && + (ri->r_offset < symbol->st_value + content.size())) { + auto *ERef = new (_readerStorage) + ELFReference(ri, ri->r_offset - symbol->st_value, nullptr); + _references.push_back(ERef); + } + } + + // Create the DefinedAtom and add it to the list of DefinedAtoms. + return new (_readerStorage) ELFDefinedAtom< + ELFT>(*this, symbolName, sectionName, symbol, section, content, + referenceStart, _references.size(), _references); + } + + std::unique_ptr > _objFile; + atom_collection_vector _definedAtoms; + atom_collection_vector _undefinedAtoms; + atom_collection_vector _sharedLibraryAtoms; + atom_collection_vector _absoluteAtoms; + + /// \brief _relocationAddendRefences and _relocationReferences contain the + /// list of relocations references. In ELF, if a section named, ".text" has + /// relocations will also have a section named ".rel.text" or ".rela.text" + /// which will hold the entries. -- .rel or .rela is prepended to create + /// the SHT_REL(A) section name. + std::map > _relocationAddendRefences; + std::map > _relocationReferences; + std::vector *> _references; + llvm::DenseMap _symbolToAtomMapping; + llvm::BumpPtrAllocator _readerStorage; + const ELFTargetInfo &_elfTargetInfo; +}; +} // lld + +#endif // LLD_READER_WRITER_FILE_ELF_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt new file mode 100644 index 0000000..f86736f --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt @@ -0,0 +1,5 @@ +add_lld_library(lldHexagonELFTarget + HexagonTargetInfo.cpp + ) + +target_link_libraries(lldHexagonELFTarget) diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTarget.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTarget.h new file mode 100644 index 0000000..28b9245a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTarget.h @@ -0,0 +1,9 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonELFTarget.h ---------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "HexagonELFTargetInfo.h" diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTargetInfo.h new file mode 100644 index 0000000..7201a89 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFTargetInfo.h @@ -0,0 +1,36 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h ------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_HEXAGON_TARGETINFO_H +#define LLD_READER_WRITER_ELF_HEXAGON_TARGETINFO_H + +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "lld/Core/LinkerOptions.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ELF.h" + +#include "DefaultELFTargetHandler.h" + +namespace lld { +namespace elf { +class HexagonELFTargetInfo LLVM_FINAL : public ELFTargetInfo { +public: + HexagonELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) { + _targetHandler = std::unique_ptr( + new DefaultELFTargetHandler >(*this)); + } + + virtual uint64_t getPageSize() const { return 0x1000; } +}; + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_HEXAGON_TARGETINFO_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lld/lib/ReaderWriter/ELF/PPC/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/PPC/CMakeLists.txt new file mode 100644 index 0000000..8a825f5 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPC/CMakeLists.txt @@ -0,0 +1,5 @@ +add_lld_library(lldPPCELFTarget + PPCTargetInfo.cpp + ) + +target_link_libraries(lldPPCELFTarget) diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCELFTarget.h b/lld/lib/ReaderWriter/ELF/PPC/PPCELFTarget.h new file mode 100644 index 0000000..7805190 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCELFTarget.h @@ -0,0 +1,9 @@ +//===- lib/ReaderWriter/ELF/PPC/PPCELFTarget.h ---------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "PPCELFTargetInfo.h" diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/PPC/PPCELFTargetInfo.h new file mode 100644 index 0000000..9a6cb83 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCELFTargetInfo.h @@ -0,0 +1,38 @@ +//===- lib/ReaderWriter/ELF/Hexagon/PPCTargetInfo.h -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_PPC_TARGETINFO_H +#define LLD_READER_WRITER_ELF_PPC_TARGETINFO_H + +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "lld/Core/LinkerOptions.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ELF.h" + +#include "DefaultELFTargetHandler.h" + +namespace lld { +namespace elf { +class PPCELFTargetInfo LLVM_FINAL : public ELFTargetInfo { +public: + PPCELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) { + _targetHandler = std::unique_ptr( + new DefaultELFTargetHandler< + llvm::object::ELFType >(*this)); + } + + virtual bool isLittleEndian() const { return false; } + + virtual uint64_t getPageSize() const { return 0x1000; } +}; + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_PPC_TARGETINFO_H diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp index deaf663..a94f307 100644 --- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp +++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp @@ -15,7 +15,6 @@ #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" @@ -39,6 +38,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include "AtomsELF.h" +#include "FileELF.h" #include #include @@ -48,292 +48,16 @@ using llvm::support::endianness; using namespace llvm::object; namespace { -/// \brief Read a binary, find out based on the symbol table contents what kind -/// of symbol it is and create corresponding atoms for it -template class FileELF : public File { - typedef Elf_Sym_Impl Elf_Sym; - typedef Elf_Shdr_Impl Elf_Shdr; - typedef Elf_Rel_Impl Elf_Rel; - typedef Elf_Rel_Impl Elf_Rela; - -public: - FileELF(std::unique_ptr MB, llvm::error_code &EC) - : File(MB->getBufferIdentifier()) { - llvm::OwningPtr binaryFile; - EC = createBinary(MB.release(), binaryFile); - if (EC) - return; - - // Point Obj to correct class and bitwidth ELF object - _objFile.reset(llvm::dyn_cast>(binaryFile.get())); - - if (!_objFile) { - EC = make_error_code(object_error::invalid_file_type); - return; - } - - binaryFile.take(); - - std::map> sectionSymbols; - - // Handle: SHT_REL and SHT_RELA sections: - // Increment over the sections, when REL/RELA section types are found add - // the contents to the RelocationReferences map. - section_iterator sit(_objFile->begin_sections()); - section_iterator sie(_objFile->end_sections()); - for (; sit != sie; sit.increment(EC)) { - if (EC) - return; - - const Elf_Shdr *section = _objFile->getElfSection(sit); - - if (section->sh_type == llvm::ELF::SHT_RELA) { - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(section, sectionName))) - return; - // Get rid of the leading .rela so Atoms can use their own section - // name to find the relocs. - sectionName = sectionName.drop_front(5); - - auto rai(_objFile->beginELFRela(section)); - auto rae(_objFile->endELFRela(section)); - - auto &Ref = _relocationAddendRefences[sectionName]; - for (; rai != rae; ++rai) { - Ref.push_back(&*rai); - } - } - - if (section->sh_type == llvm::ELF::SHT_REL) { - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(section, sectionName))) - return; - // Get rid of the leading .rel so Atoms can use their own section - // name to find the relocs. - sectionName = sectionName.drop_front(4); - - auto ri(_objFile->beginELFRel(section)); - auto re(_objFile->endELFRel(section)); - - auto &Ref = _relocationReferences[sectionName]; - for (; ri != re; ++ri) { - Ref.push_back(&*ri); - } - } - } - - // Increment over all the symbols collecting atoms and symbol names for - // later use. - symbol_iterator it(_objFile->begin_symbols()); - symbol_iterator ie(_objFile->end_symbols()); - - for (; it != ie; it.increment(EC)) { - if (EC) - return; - - if ((EC = it->getSection(sit))) - return; - - const Elf_Shdr *section = _objFile->getElfSection(sit); - const Elf_Sym *symbol = _objFile->getElfSymbol(it); - - llvm::StringRef symbolName; - if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) - return; - - if (symbol->st_shndx == llvm::ELF::SHN_ABS) { - // Create an absolute atom. - auto *newAtom = new (_readerStorage) - ELFAbsoluteAtom(*this, symbolName, symbol, symbol->st_value); - - _absoluteAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); - } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) { - // Create an undefined atom. - auto *newAtom = new (_readerStorage) - ELFUndefinedAtom(*this, symbolName, symbol); - - _undefinedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); - } else { - // This is actually a defined symbol. Add it to its section's list of - // symbols. - if (symbol->getType() == llvm::ELF::STT_NOTYPE || - symbol->getType() == llvm::ELF::STT_OBJECT || - symbol->getType() == llvm::ELF::STT_FUNC || - symbol->getType() == llvm::ELF::STT_GNU_IFUNC || - symbol->getType() == llvm::ELF::STT_SECTION || - symbol->getType() == llvm::ELF::STT_FILE || - symbol->getType() == llvm::ELF::STT_TLS || - symbol->getType() == llvm::ELF::STT_COMMON || - symbol->st_shndx == llvm::ELF::SHN_COMMON) { - sectionSymbols[section].push_back(symbol); - } else { - llvm::errs() << "Unable to create atom for: " << symbolName << "\n"; - EC = object_error::parse_failed; - return; - } - } - } - - for (auto &i : sectionSymbols) { - auto &symbols = i.second; - // Sort symbols by position. - std::stable_sort(symbols.begin(), symbols.end(), - [](const Elf_Sym *A, const Elf_Sym *B) { - return A->st_value < B->st_value; - }); - - StringRef sectionContents; - if ((EC = _objFile->getSectionContents(i.first, sectionContents))) - return; - - llvm::StringRef sectionName; - if ((EC = _objFile->getSectionName(i.first, sectionName))) - return; - - // i.first is the section the symbol lives in - for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { - llvm::StringRef symbolName; - if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) - return; - - bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON || - (*si)->st_shndx == llvm::ELF::SHN_COMMON; - - // Get the symbol's content: - uint64_t contentSize; - if (si + 1 == se) { - // if this is the last symbol, take up the remaining data. - contentSize = isCommon ? 0 - : i.first->sh_size - (*si)->st_value; - } else { - contentSize = isCommon ? 0 - : (*(si + 1))->st_value - (*si)->st_value; - } - - // Don't allocate content to a weak symbol, as they may be merged away. - // Create an anonymous atom to hold the data. - ELFDefinedAtom *anonAtom = nullptr; - if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) { - // Create a new non-weak ELF symbol. - auto sym = new (_readerStorage) Elf_Sym; - *sym = **si; - sym->setBinding(llvm::ELF::STB_GLOBAL); - anonAtom = createDefinedAtomAndAssignRelocations( - "", sectionName, sym, i.first, - ArrayRef((uint8_t *)sectionContents.data() + - (*si)->st_value, contentSize)); - contentSize = 0; - } - - ArrayRef symbolData = ArrayRef( - (uint8_t *)sectionContents.data() + - (*si)->st_value, contentSize); - - auto newAtom = createDefinedAtomAndAssignRelocations( - symbolName, sectionName, *si, i.first, symbolData); - - _definedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair((*si), newAtom)); - if (anonAtom) - _definedAtoms._atoms.push_back(anonAtom); - } - } - - // All the Atoms and References are created. Now update each Reference's - // target with the Atom pointer it refers to. - for (auto &ri : _references) { - const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex()); - ri->setTarget(findAtom(Symbol)); - } - } - - virtual const atom_collection &defined() const { - return _definedAtoms; - } - - virtual const atom_collection &undefined() const { - return _undefinedAtoms; - } - - virtual const atom_collection &sharedLibrary() const { - return _sharedLibraryAtoms; - } - - virtual const atom_collection &absolute() const { - return _absoluteAtoms; - } - - Atom *findAtom(const Elf_Sym *symbol) { - return _symbolToAtomMapping.lookup(symbol); - } - -private: - ELFDefinedAtom *createDefinedAtomAndAssignRelocations( - StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol, - const Elf_Shdr *section, ArrayRef content) { - unsigned int referenceStart = _references.size(); - - // Only relocations that are inside the domain of the atom are added. - - // Add Rela (those with r_addend) references: - for (auto &rai : _relocationAddendRefences[sectionName]) { - if (!((rai->r_offset >= symbol->st_value) && - (rai->r_offset < symbol->st_value + content.size()))) - continue; - auto *ERef = new (_readerStorage) - ELFReference(rai, rai->r_offset - symbol->st_value, nullptr); - _references.push_back(ERef); - } - - // Add Rel references. - for (auto &ri : _relocationReferences[sectionName]) { - if ((ri->r_offset >= symbol->st_value) && - (ri->r_offset < symbol->st_value + content.size())) { - auto *ERef = new (_readerStorage) - ELFReference(ri, ri->r_offset - symbol->st_value, nullptr); - _references.push_back(ERef); - } - } - - // Create the DefinedAtom and add it to the list of DefinedAtoms. - return new (_readerStorage) - ELFDefinedAtom(*this, symbolName, sectionName, symbol, section, - content, referenceStart, _references.size(), - _references); - } - - std::unique_ptr> _objFile; - atom_collection_vector _definedAtoms; - atom_collection_vector _undefinedAtoms; - atom_collection_vector _sharedLibraryAtoms; - atom_collection_vector _absoluteAtoms; - - /// \brief _relocationAddendRefences and _relocationReferences contain the - /// list of relocations references. In ELF, if a section named, ".text" has - /// relocations will also have a section named ".rel.text" or ".rela.text" - /// which will hold the entries. -- .rel or .rela is prepended to create - /// the SHT_REL(A) section name. - std::map> _relocationAddendRefences; - std::map> _relocationReferences; - std::vector *> _references; - llvm::DenseMap _symbolToAtomMapping; - llvm::BumpPtrAllocator _readerStorage; -}; - /// \brief A reader object that will instantiate correct FileELF by examining the /// memory buffer for ELF class and bit width class ReaderELF : public Reader { public: - ReaderELF(const TargetInfo & ti, std::function read) - : Reader(ti), - _readerArchive(ti, read) {} + ReaderELF(const ELFTargetInfo &ti, std::function read) + : Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, read) { + } error_code parseFile(std::unique_ptr mb, - std::vector> &result) { + std::vector > &result) { using llvm::object::ELFType; llvm::sys::LLVMFileType fileType = llvm::sys::IdentifyFileType(mb->getBufferStart(), @@ -353,41 +77,41 @@ public: if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second == llvm::ELF::ELFDATA2LSB) { if (MaxAlignment >= 4) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second == llvm::ELF::ELFDATA2MSB) { if (MaxAlignment >= 4) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second == llvm::ELF::ELFDATA2MSB) { if (MaxAlignment >= 8) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second == llvm::ELF::ELFDATA2LSB) { if (MaxAlignment >= 8) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else if (MaxAlignment >= 2) - f.reset(new FileELF>( - std::move(mb), ec)); + f.reset(new FileELF >( + _elfTargetInfo, std::move(mb), ec)); else llvm_unreachable("Invalid alignment for ELF file!"); } @@ -410,13 +134,14 @@ public: } private: + const ELFTargetInfo &_elfTargetInfo; ReaderArchive _readerArchive; }; } // end anon namespace. namespace lld { -std::unique_ptr createReaderELF(const TargetInfo & ti, +std::unique_ptr createReaderELF(const ELFTargetInfo &eti, std::function read) { - return std::unique_ptr(new ReaderELF(ti, std::move(read))); + return std::unique_ptr(new ReaderELF(eti, std::move(read))); } } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index 73bb6bb..f8d23c5 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -64,7 +64,7 @@ private: ELFStringTable *_strtab; ELFStringTable *_shstrtab; ELFSectionHeader *_shdrtab; - CRuntimeFile _runtimeFile; + CRuntimeFileELF _runtimeFile; }; //===----------------------------------------------------------------------===// diff --git a/lld/lib/ReaderWriter/ELF/X86/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/X86/CMakeLists.txt new file mode 100644 index 0000000..c996757 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86/CMakeLists.txt @@ -0,0 +1,5 @@ +add_lld_library(lldX86ELFTarget + X86TargetInfo.cpp + ) + +target_link_libraries(lldX86ELFTarget) diff --git a/lld/lib/ReaderWriter/ELF/X86/X86ELFTarget.h b/lld/lib/ReaderWriter/ELF/X86/X86ELFTarget.h new file mode 100644 index 0000000..30a0cdd --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86/X86ELFTarget.h @@ -0,0 +1,9 @@ +//===- lib/ReaderWriter/ELF/Hexagon/X86ELFTarget.h -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "X86ELFTargetInfo.h" diff --git a/lld/lib/ReaderWriter/ELF/X86/X86ELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/X86/X86ELFTargetInfo.h new file mode 100644 index 0000000..071e075 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86/X86ELFTargetInfo.h @@ -0,0 +1,34 @@ +//===- lib/ReaderWriter/ELF/Hexagon/X86TargetInfo.h -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_X86_TARGETINFO_H +#define LLD_READER_WRITER_ELF_X86_TARGETINFO_H + +#include "lld/ReaderWriter/ELFTargetInfo.h" +#include "lld/Core/LinkerOptions.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ELF.h" + +#include "DefaultELFTargetHandler.h" + +namespace lld { +namespace elf { +class X86ELFTargetInfo LLVM_FINAL : public ELFTargetInfo { +public: + X86ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) { + _targetHandler = std::unique_ptr( + new DefaultELFTargetHandler >(*this)); + } + + virtual uint64_t getPageSize() const { return 0x1000; } +}; +} // elf +} // lld +#endif // LLD_READER_WRITER_ELF_X86_TARGETINFO_H diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt new file mode 100644 index 0000000..c2f7757 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt @@ -0,0 +1,5 @@ +add_lld_library(lldX86_64ELFTarget + X86_64TargetInfo.cpp + ) + +target_link_libraries(lldX86_64ELFTarget) diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTarget.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTarget.h new file mode 100644 index 0000000..29af114 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTarget.h @@ -0,0 +1,9 @@ +//===- lib/ReaderWriter/ELF/Hexagon/X86ELFTarget.h -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "X86_64ELFTargetInfo.h" diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h new file mode 100644 index 0000000..4410d3b --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h @@ -0,0 +1,37 @@ +//===- lib/ReaderWriter/ELF/Hexagon/X86_64TargetInfo.h -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H +#define LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H + +#include "lld/ReaderWriter/ELFTargetInfo.h" + +#include "lld/Core/LinkerOptions.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ELF.h" + +#include "DefaultELFTargetHandler.h" + +namespace lld { +namespace elf { +class X86_64ELFTargetInfo LLVM_FINAL : public ELFTargetInfo { +public: + X86_64ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) { + _targetHandler = std::unique_ptr( + new DefaultELFTargetHandler >(*this)); + } + + virtual uint64_t getPageSize() const { return 0x1000; } + +}; +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_X86_64_TARGETINFO_H diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp new file mode 100644 index 0000000..e69de29 diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp index 91fd64f..87c6526 100644 --- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp +++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp @@ -29,7 +29,7 @@ namespace mach_o { class CRuntimeFile : public SimpleFile { public: CRuntimeFile(const MachOTargetInfo &ti) - : SimpleFile("C runtime"), _undefMain(*this, "_main") { + : SimpleFile(ti, "C runtime"), _undefMain(*this, "_main") { // only main executables need _main if (ti.getLinkerOptions()._outputKind == OutputKind::Executable) this->addAtom(_undefMain); diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp index ba46df1..6452494 100644 --- a/lld/lib/ReaderWriter/MachO/StubsPass.hpp +++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp @@ -30,11 +30,12 @@ namespace mach_o { class StubsPass : public lld::StubsPass { public: StubsPass(const MachOTargetInfo &ti) - : _targetInfo(ti), - _kindHandler(KindHandler::makeHandler(_targetInfo.getTriple().getArch())), - _helperCommonAtom(nullptr), - _helperCacheAtom(nullptr), - _helperBinderAtom(nullptr) { + : _targetInfo(ti) + , _kindHandler(KindHandler::makeHandler(_targetInfo.getTriple().getArch())) + , _file(ti) + , _helperCommonAtom(nullptr) + , _helperCacheAtom(nullptr) + , _helperBinderAtom(nullptr) { } virtual bool noTextRelocs() { @@ -147,8 +148,8 @@ private: class File : public SimpleFile { public: - File() : SimpleFile("MachO Stubs pass") { - } + File(const MachOTargetInfo &ti) : SimpleFile(ti, "MachO Stubs pass") { + } }; const MachOTargetInfo &_targetInfo; diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp index 814215f..36bc7fc 100644 --- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp +++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp @@ -246,11 +246,11 @@ public: /// Instantiates a File object from a native object file. Ownership /// of the MemoryBuffer is transfered to the resulting File object. - static error_code make(std::unique_ptr &mb, - StringRef path, - std::vector> &result) { - const uint8_t* const base = - reinterpret_cast(mb->getBufferStart()); + static error_code make( + const TargetInfo &ti, std::unique_ptr &mb, + StringRef path, std::vector > &result) { + const uint8_t *const base = + reinterpret_cast(mb->getBufferStart()); const NativeFileHeader* const header = reinterpret_cast(base); const NativeChunk *const chunks = @@ -264,17 +264,16 @@ public: if ( header->fileSize > fileSize ) return make_error_code(native_reader_error::file_too_short); - DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() - << " Native File Header:" - << " fileSize=" << header->fileSize - << " chunkCount=" << header->chunkCount - << "\n"); + DEBUG_WITH_TYPE("ReaderNative", + llvm::dbgs() << " Native File Header:" << " fileSize=" + << header->fileSize << " chunkCount=" + << header->chunkCount << "\n"); // instantiate NativeFile object and add values to it as found - std::unique_ptr file(new File(std::move(mb), path)); + std::unique_ptr file(new File(ti, std::move(mb), path)); // process each chunk - for(uint32_t i=0; i < header->chunkCount; ++i) { + for (uint32_t i = 0; i < header->chunkCount; ++i) { error_code ec; const NativeChunk* chunk = &chunks[i]; // sanity check chunk is within file @@ -373,9 +372,10 @@ public: virtual const atom_collection& sharedLibrary() const { return _sharedLibraryAtoms; } - virtual const atom_collection& absolute() const { - return _absoluteAtoms; + virtual const atom_collection &absolute() const { + return _absoluteAtoms; } + virtual const TargetInfo &getTargetInfo() const { return _targetInfo; } private: friend class NativeDefinedAtomV1; @@ -728,25 +728,18 @@ private: assert(index > _targetsTableCount); _targetsTable[index] = newAtom; } - - // private constructor, only called by make() - File(std::unique_ptr mb, StringRef path) : - lld::File(path), - _buffer(std::move(mb)), // Reader now takes ownership of buffer - _header(nullptr), - _targetsTable(nullptr), - _targetsTableCount(0), - _strings(nullptr), - _stringsMaxOffset(0), - _addends(nullptr), - _addendsMaxIndex(0), - _contentStart(nullptr), - _contentEnd(nullptr) - { - _header = reinterpret_cast - (_buffer->getBufferStart()); + File(const TargetInfo &ti, std::unique_ptr mb, + StringRef path) + : lld::File(path), + _buffer(std::move(mb)), // Reader now takes ownership of buffer + _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0), + _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr), + _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr), + _targetInfo(ti) { + _header = + reinterpret_cast(_buffer->getBufferStart()); } template @@ -805,13 +798,13 @@ private: const char* _strings; uint32_t _stringsMaxOffset; const Reference::Addend* _addends; - uint32_t _addendsMaxIndex; - const uint8_t* _contentStart; - const uint8_t* _contentEnd; + uint32_t _addendsMaxIndex; + const uint8_t *_contentStart; + const uint8_t *_contentEnd; + const TargetInfo &_targetInfo; }; - -inline const class lld::File& NativeDefinedAtomV1::file() const { +inline const class lld::File &NativeDefinedAtomV1::file() const { return *_file; } @@ -929,10 +922,11 @@ class Reader : public lld::Reader { public: Reader(const TargetInfo &ti) : lld::Reader(ti) {} - - virtual error_code parseFile(std::unique_ptr mb, - std::vector> &result) { - return File::make(mb, mb->getBufferIdentifier(), result); + + virtual error_code parseFile( + std::unique_ptr mb, + std::vector > &result) { + return File::make(_targetInfo, mb, mb->getBufferIdentifier(), result); } }; } // end namespace native diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index db63830..07fadcf 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -211,8 +211,9 @@ private: class FileCOFF : public File { public: - FileCOFF(std::unique_ptr MB, llvm::error_code &EC) - : File(MB->getBufferIdentifier()) { + FileCOFF(const TargetInfo &ti, std::unique_ptr MB, + llvm::error_code &EC) + : File(MB->getBufferIdentifier()), _targetInfo(ti) { llvm::OwningPtr Bin; EC = llvm::object::createBinary(MB.release(), Bin); if (EC) @@ -350,13 +351,16 @@ public: return AbsoluteAtoms; } + virtual const TargetInfo &getTargetInfo() const { return _targetInfo; } + private: std::unique_ptr Obj; - atom_collection_vector DefinedAtoms; + atom_collection_vector DefinedAtoms; atom_collection_vector UndefinedAtoms; atom_collection_vector SharedLibraryAtoms; - atom_collection_vector AbsoluteAtoms; + atom_collection_vector AbsoluteAtoms; llvm::BumpPtrAllocator AtomStorage; + const TargetInfo &_targetInfo; }; @@ -366,9 +370,9 @@ public: ReaderCOFF(const TargetInfo &ti) : Reader(ti) {} error_code parseFile(std::unique_ptr mb, - std::vector> &result) { + std::vector > &result) { llvm::error_code ec; - std::unique_ptr f(new FileCOFF(std::move(mb), ec)); + std::unique_ptr f(new FileCOFF(_targetInfo, std::move(mb), ec)); if (ec) { return ec; } diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp index 6dcde18..4fe2f10 100644 --- a/lld/lib/ReaderWriter/ReaderArchive.cpp +++ b/lld/lib/ReaderWriter/ReaderArchive.cpp @@ -134,10 +134,10 @@ private: public: /// only subclasses of ArchiveLibraryFile can be instantiated FileArchive(const TargetInfo &ti, - std::function (const LinkerInput &)> getReader, - std::unique_ptr mb, - error_code &ec) - : ArchiveLibraryFile(mb->getBufferIdentifier()), _getReader(getReader) { + std::function(const LinkerInput &)> getReader, + std::unique_ptr mb, error_code &ec) + : ArchiveLibraryFile(ti, mb->getBufferIdentifier()), + _getReader(getReader) { std::unique_ptr archive_obj( new llvm::object::Archive(mb.release(), ec)); if (ec) diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index c17240e..ef22f078 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -269,19 +269,15 @@ LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull) // type to make template matching work, so invent RefKind. LLVM_YAML_STRONG_TYPEDEF(lld::Reference::Kind, RefKind) - } // namespace anon - -LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember); -LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference*) - -// Always write DefinedAtoms content bytes as a flow sequence. -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8); - -// for compatibility with gcc-4.7 in C++11 mode, add extra namespace -namespace llvm { -namespace yaml { +LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember) + LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *) + // Always write DefinedAtoms content bytes as a flow sequence. + LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8) + // for compatibility with gcc-4.7 in C++11 mode, add extra namespace + namespace llvm { + namespace yaml { // This is a custom formatter for RefKind template<> @@ -607,17 +603,21 @@ struct DocumentListTraits< std::vector > { // YAML conversion for const lld::File* template <> struct MappingTraits { - - class NormArchiveFile : public lld::ArchiveLibraryFile { - public: - NormArchiveFile(IO &io) : ArchiveLibraryFile(""), _path() { - } - NormArchiveFile(IO &io, const lld::File *file) - : ArchiveLibraryFile(file->path()), - _path(file->path()) { + + class NormArchiveFile : public lld::ArchiveLibraryFile { + public: + NormArchiveFile(IO &io) + : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo, + ""), + _path() { + } + NormArchiveFile(IO &io, const lld::File *file) + : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_targetInfo, + file->path()), + _path(file->path()) { // If we want to support writing archives, this constructor would // need to populate _members. - } + } const lld::File *denormalize(IO &io) { return this; @@ -665,19 +665,16 @@ struct MappingTraits { StringRef _path; std::vector _members; }; - - - class NormalizedFile : public lld::File { - public: - NormalizedFile(IO &io) : File(""), _rnb(nullptr) { - } - NormalizedFile(IO &io, const lld::File *file) - : File(file->path()), - _rnb(new RefNameBuilder(*file)), - _path(file->path()) { - for (const lld::DefinedAtom *a : file->defined()) - _definedAtoms.push_back(a); - for (const lld::UndefinedAtom *a : file->undefined()) + + class NormalizedFile : public lld::File { + public: + NormalizedFile(IO &io) : File(""), _IO(io), _rnb(nullptr) {} + NormalizedFile(IO &io, const lld::File *file) + : File(file->path()), _IO(io), _rnb(new RefNameBuilder(*file)), + _path(file->path()) { + for (const lld::DefinedAtom *a : file->defined()) + _definedAtoms.push_back(a); + for (const lld::UndefinedAtom *a : file->undefined()) _undefinedAtoms.push_back(a); for (const lld::SharedLibraryAtom *a : file->sharedLibrary()) _sharedLibraryAtoms.push_back(a); @@ -695,12 +692,16 @@ struct MappingTraits { virtual const atom_collection &sharedLibrary()const{ return _sharedLibraryAtoms; } - virtual const atom_collection &absolute() const { - return _absoluteAtoms; - } - - // Allocate a new copy of this string and keep track of allocations - // in _stringCopies, so they can be freed when File is destroyed. + virtual const atom_collection &absolute() const { + return _absoluteAtoms; + } + + virtual const TargetInfo &getTargetInfo() const { + return ((ContextInfo *)_IO.getContext())->_targetInfo; + } + + // Allocate a new copy of this string and keep track of allocations + // in _stringCopies, so they can be freed when File is destroyed. StringRef copyString(StringRef str) { // We want _stringCopies to own the string memory so it is deallocated // when the File object is destroyed. But we need a StringRef that @@ -709,12 +710,13 @@ struct MappingTraits { memcpy(s.get(), str.data(), str.size()); llvm::StringRef r = llvm::StringRef(s.get(), str.size()); _stringCopies.push_back(std::move(s)); - return r; - } - - RefNameBuilder *_rnb; - StringRef _path; - AtomList _definedAtoms; + return r; + } + + IO &_IO; + RefNameBuilder *_rnb; + StringRef _path; + AtomList _definedAtoms; AtomList _undefinedAtoms; AtomList _sharedLibraryAtoms; AtomList _absoluteAtoms; diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp index f7c0aa8..b2c8d9a 100644 --- a/lld/tools/lld-core/TestingHelpers.hpp +++ b/lld/tools/lld-core/TestingHelpers.hpp @@ -224,7 +224,7 @@ private: class TestingPassFile : public MutableFile { public: - TestingPassFile() : MutableFile("Testing pass") {} + TestingPassFile(const TargetInfo &ti) : MutableFile(ti, "Testing pass") {} virtual void addAtom(const Atom &atom) { if (const DefinedAtom *defAtom = dyn_cast(&atom)) @@ -280,6 +280,9 @@ const TestingKindMapping sKinds[] = { class TestingStubsPass : public StubsPass { public: + TestingStubsPass(const TargetInfo &ti) : _file(TestingPassFile(ti)) + {} + virtual bool noTextRelocs() { return true; } @@ -310,6 +313,9 @@ private: class TestingGOTPass : public GOTPass { public: + TestingGOTPass(const TargetInfo &ti) : _file(TestingPassFile(ti)) + {} + virtual bool noTextRelocs() { return true; } diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp index 22cd570..569aab7 100644 --- a/lld/tools/lld-core/lld-core.cpp +++ b/lld/tools/lld-core/lld-core.cpp @@ -166,9 +166,9 @@ public: virtual void addPasses(PassManager &pm) const { if (_doStubs) - pm.add(std::unique_ptr(new TestingStubsPass)); + pm.add(std::unique_ptr(new TestingStubsPass(*this))); if (_doGOT) - pm.add(std::unique_ptr(new TestingGOTPass)); + pm.add(std::unique_ptr(new TestingGOTPass(*this))); if (_doOrder) pm.add(std::unique_ptr(new OrderPass)); } -- 2.7.4