diff options
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/include/lld/ReaderWriter/ELFLinkingContext.h | 5 | ||||
| -rw-r--r-- | lld/include/lld/ReaderWriter/Reader.h | 3 | ||||
| -rw-r--r-- | lld/lib/Driver/GnuLdDriver.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Atoms.h | 79 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h | 16 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DynamicFile.h | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ELFFile.h | 284 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ELFReader.h | 15 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h | 203 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h | 84 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp | 5 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h | 6 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h | 70 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h | 1 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Reader.cpp | 23 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/TargetHandler.h | 39 |
17 files changed, 521 insertions, 318 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index 3921bfe6d58..6554812d9f8 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -14,6 +14,7 @@ #include "lld/Core/PassManager.h" #include "lld/Core/Pass.h" #include "lld/Core/range.h" +#include "lld/Core/STDExtras.h" #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Writer.h" @@ -37,6 +38,10 @@ class TargetHandlerBase { public: virtual ~TargetHandlerBase() {} virtual void registerRelocationNames(Registry &) = 0; + + virtual std::unique_ptr<Reader> getObjReader(bool) = 0; + + virtual std::unique_ptr<Reader> getDSOReader(bool) = 0; }; class ELFLinkingContext : public LinkingContext { diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h index 31404d346cb..80b1b4d3d94 100644 --- a/lld/include/lld/ReaderWriter/Reader.h +++ b/lld/include/lld/ReaderWriter/Reader.h @@ -125,7 +125,8 @@ public: void addSupportWindowsResourceFiles(); void addSupportMachOObjects(StringRef archName); void addSupportELFObjects(bool atomizeStrings, TargetHandlerBase *handler); - void addSupportELFDynamicSharedObjects(bool useShlibUndefines); + void addSupportELFDynamicSharedObjects(bool useShlibUndefines, + TargetHandlerBase *handler); /// To convert between kind values and names, the registry walks the list /// of registered kind tables. Each table is a zero terminated array of diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index c4b8ab42f6b..c4f1e316614 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -119,7 +119,7 @@ bool GnuLdDriver::linkELF(int argc, const char *argv[], options->registry().addSupportNativeObjects(); if (options->allowLinkWithDynamicLibraries()) options->registry().addSupportELFDynamicSharedObjects( - options->useShlibUndefines()); + options->useShlibUndefines(), options->targetHandler()); return link(*options, diagnostics); } diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index 382e071335d..4290c3ba185 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -25,7 +25,6 @@ namespace lld { namespace elf { template <class ELFT> class DynamicFile; template <typename ELFT> class ELFFile; -template <typename ELFT> class TargetAtomHandler; /// \brief Relocation References: Defined Atoms may contain references that will /// need to be patched before the executable is written. @@ -36,7 +35,7 @@ template <typename ELFT> class TargetAtomHandler; /// (not target atom) about a relocation, so we store the index to /// ELFREference. In the second pass, ELFReferences are revisited to update /// target atoms by target symbol indexes. -template <class ELFT> class ELFReference LLVM_FINAL : public Reference { +template <class ELFT> class ELFReference : public Reference { typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela; public: @@ -88,8 +87,7 @@ private: /// \brief These atoms store symbols that are fixed to a particular address. /// This atom has no content its address will be used by the writer to fixup /// references that point to it. -template<class ELFT> -class ELFAbsoluteAtom LLVM_FINAL : public AbsoluteAtom { +template <class ELFT> class ELFAbsoluteAtom : public AbsoluteAtom { typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; public: @@ -128,8 +126,7 @@ private: /// \brief ELFUndefinedAtom: These atoms store undefined symbols and are place /// holders that will be replaced by defined atoms later in the linking process. -template<class ELFT> -class ELFUndefinedAtom LLVM_FINAL : public lld::UndefinedAtom { +template <class ELFT> class ELFUndefinedAtom : public lld::UndefinedAtom { typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; public: @@ -158,8 +155,7 @@ private: /// \brief This atom stores defined symbols and will contain either data or /// code. -template<class ELFT> -class ELFDefinedAtom LLVM_FINAL : public DefinedAtom { +template <class ELFT> class ELFDefinedAtom : public DefinedAtom { typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; @@ -172,8 +168,8 @@ public: : _owningFile(file), _symbolName(symbolName), _sectionName(sectionName), _symbol(symbol), _section(section), _contentData(contentData), _referenceStartIndex(referenceStart), _referenceEndIndex(referenceEnd), - _referenceList(referenceList), _targetAtomHandler(nullptr), - _contentType(typeUnknown), _permissions(permUnknown) {} + _referenceList(referenceList), _contentType(typeUnknown), + _permissions(permUnknown) {} ~ELFDefinedAtom() {} @@ -196,15 +192,6 @@ public: virtual uint64_t size() const { // Common symbols are not allocated in object files, // so use st_size to tell how many bytes are required. - - // Treat target defined common symbols - if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC && - _symbol->st_shndx < llvm::ELF::SHN_HIPROC)) { - if (!_targetAtomHandler) - _targetAtomHandler = &_owningFile.targetHandler()->targetAtomHandler(); - if (_targetAtomHandler->getType(_symbol) == llvm::ELF::STT_COMMON) - return (uint64_t) _symbol->st_size; - } if ((_symbol->getType() == llvm::ELF::STT_COMMON) || _symbol->st_shndx == llvm::ELF::SHN_COMMON) return (uint64_t) _symbol->st_size; @@ -231,17 +218,6 @@ public: if (_symbol->getBinding() == llvm::ELF::STB_WEAK) return mergeAsWeak; - // If the symbol is a target defined and if the target - // defines the symbol as a common symbol treat it as - // mergeTentative - if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC && - _symbol->st_shndx < llvm::ELF::SHN_HIPROC)) { - if (!_targetAtomHandler) - _targetAtomHandler = &_owningFile.targetHandler()->targetAtomHandler(); - if (_targetAtomHandler->getType(_symbol) == llvm::ELF::STT_COMMON) - return mergeAsTentative; - } - if ((_symbol->getType() == llvm::ELF::STT_COMMON) || _symbol->st_shndx == llvm::ELF::SHN_COMMON) return mergeAsTentative; @@ -256,15 +232,6 @@ public: ContentType ret = typeUnknown; uint64_t flags = _section->sh_flags; - // Treat target defined symbols - if ((_section->sh_flags & llvm::ELF::SHF_MASKPROC) || - ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC && - _symbol->st_shndx < llvm::ELF::SHN_HIPROC))) { - if (!_targetAtomHandler) - _targetAtomHandler = &_owningFile.targetHandler()->targetAtomHandler(); - return _contentType = _targetAtomHandler->contentType(this); - } - if (!(flags & llvm::ELF::SHF_ALLOC)) return _contentType = typeNoAlloc; @@ -337,16 +304,6 @@ public: virtual Alignment alignment() const { // Unallocated common symbols specify their alignment constraints in // st_value. - - // Treat target defined common symbols - if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC && - _symbol->st_shndx < llvm::ELF::SHN_HIPROC)) { - if (!_targetAtomHandler) - _targetAtomHandler = &_owningFile.targetHandler()->targetAtomHandler(); - if (_targetAtomHandler->getType(_symbol) == llvm::ELF::STT_COMMON) - return Alignment(llvm::Log2_64(_symbol->st_value)); - } - if ((_symbol->getType() == llvm::ELF::STT_COMMON) || _symbol->st_shndx == llvm::ELF::SHN_COMMON) { return Alignment(llvm::Log2_64(_symbol->st_value)); @@ -396,13 +353,6 @@ public: return _permissions; uint64_t flags = _section->sh_flags; - // Treat target defined symbols - if ((_symbol->st_shndx > llvm::ELF::SHN_LOPROC && - _symbol->st_shndx < llvm::ELF::SHN_HIPROC)) { - if (!_targetAtomHandler) - _targetAtomHandler = &_owningFile.targetHandler()->targetAtomHandler(); - return _permissions = _targetAtomHandler->contentPermissions(this); - } if (!(flags & llvm::ELF::SHF_ALLOC)) return _permissions = perm___; @@ -492,7 +442,7 @@ public: virtual void setOrdinal(uint64_t ord) { _ordinal = ord; } -private: +protected: const ELFFile<ELFT> &_owningFile; StringRef _symbolName; StringRef _sectionName; @@ -505,14 +455,12 @@ private: unsigned int _referenceStartIndex; unsigned int _referenceEndIndex; std::vector<ELFReference<ELFT> *> &_referenceList; - // Cached size of the TLS segment. - mutable TargetAtomHandler<ELFT> *_targetAtomHandler; mutable ContentType _contentType; mutable ContentPermissions _permissions; }; /// \brief This atom stores mergeable Strings -template <class ELFT> class ELFMergeAtom LLVM_FINAL : public DefinedAtom { +template <class ELFT> class ELFMergeAtom : public DefinedAtom { typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; public: @@ -596,8 +544,7 @@ private: uint64_t _offset; }; -template <class ELFT> -class ELFCommonAtom LLVM_FINAL : public DefinedAtom { +template <class ELFT> class ELFCommonAtom : public DefinedAtom { typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; public: ELFCommonAtom(const ELFFile<ELFT> &file, @@ -643,10 +590,6 @@ public: } virtual ContentType contentType() const { - if (_symbol->st_shndx >= llvm::ELF::SHN_LORESERVE && - _symbol->st_shndx <= llvm::ELF::SHN_HIOS) - return _owningFile.targetHandler()->targetAtomHandler().contentType( - nullptr, _symbol); return typeZeroFill; } @@ -703,7 +646,6 @@ protected: virtual void incrementIterator(const void *&iter) const {} -private: const ELFFile<ELFT> &_owningFile; StringRef _symbolName; const Elf_Sym *_symbol; @@ -711,8 +653,7 @@ private: }; /// \brief An atom from a shared library. -template <class ELFT> -class ELFDynamicAtom LLVM_FINAL : public SharedLibraryAtom { +template <class ELFT> class ELFDynamicAtom : public SharedLibraryAtom { typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; public: diff --git a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h index 143bffdde80..b2cb5d5e001 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h @@ -12,6 +12,7 @@ #include "DefaultLayout.h" #include "TargetHandler.h" +#include "ELFReader.h" #include "lld/ReaderWriter/ELFLinkingContext.h" @@ -32,11 +33,6 @@ public: llvm_unreachable("Target should provide implementation for function "); } - /// TargetAtomHandler - TargetAtomHandler<ELFT> &targetAtomHandler() { - llvm_unreachable("Target should provide implementation for function "); - } - const TargetRelocationHandler<ELFT> &getRelocationHandler() const { llvm_unreachable("Target should provide implementation for function "); } @@ -74,7 +70,15 @@ public: DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS)); } -private: + virtual std::unique_ptr<Reader> getObjReader(bool atomizeStrings) { + return std::unique_ptr<Reader>(new ELFObjectReader(atomizeStrings)); + } + + virtual std::unique_ptr<Reader> getDSOReader(bool useShlibUndefines) { + return std::unique_ptr<Reader>(new ELFDSOReader(useShlibUndefines)); + } + +protected: llvm::BumpPtrAllocator _alloc; }; } // end namespace elf diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.h b/lld/lib/ReaderWriter/ELF/DynamicFile.h index 2e445f8773b..4840257465f 100644 --- a/lld/lib/ReaderWriter/ELF/DynamicFile.h +++ b/lld/lib/ReaderWriter/ELF/DynamicFile.h @@ -22,7 +22,7 @@ namespace lld { namespace elf { -template <class ELFT> class DynamicFile LLVM_FINAL : public SharedLibraryFile { +template <class ELFT> class DynamicFile : public SharedLibraryFile { public: static ErrorOr<std::unique_ptr<DynamicFile>> create(std::unique_ptr<llvm::MemoryBuffer> mb, bool useShlibUndefines); diff --git a/lld/lib/ReaderWriter/ELF/ELFFile.h b/lld/lib/ReaderWriter/ELF/ELFFile.h index 732c1c86b92..7a1b7cf7e76 100644 --- a/lld/lib/ReaderWriter/ELF/ELFFile.h +++ b/lld/lib/ReaderWriter/ELF/ELFFile.h @@ -118,12 +118,10 @@ template <class ELFT> class ELFFile : public File { public: ELFFile(StringRef name, bool atomizeStrings = false) - : File(name, kindObject), _ordinal(0), _doStringsMerge(atomizeStrings), - _targetHandler(nullptr) {} + : File(name, kindObject), _ordinal(0), _doStringsMerge(atomizeStrings) {} static ErrorOr<std::unique_ptr<ELFFile>> - create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings, - TargetHandlerBase *handler); + create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings); virtual Reference::KindArch kindArch(); @@ -159,8 +157,6 @@ public: return _absoluteAtoms; } - TargetHandler<ELFT> *targetHandler() const { return _targetHandler; } - Atom *findAtom(const Elf_Sym *symbol) { return _symbolToAtomMapping.lookup(symbol); } @@ -195,12 +191,8 @@ protected: StringRef sectionName, StringRef sectionContents); - /// Returns true if the symbol is common symbol. A common symbol represents a - /// tentive definition in C. It has name, size and alignment constraint, but - /// actual storage has not yet been allocated. (The linker will allocate - /// storage for them in the later pass after coalescing tentative symbols by - /// name.) - virtual bool isCommonSymbol(const Elf_Sym *symbol); + /// Return the default reloc addend for references. + virtual int64_t defaultRelocAddend(const Reference &) const; /// Returns the symbol's content size. The nextSymbol should be null if the /// symbol is the last one in the section. @@ -211,8 +203,113 @@ protected: virtual void createEdge(ELFDefinedAtom<ELFT> *from, ELFDefinedAtom<ELFT> *to, uint32_t edgeKind); - virtual void setTargetHandler(TargetHandlerBase *handler) { - _targetHandler = reinterpret_cast<TargetHandler<ELFT> *>(handler); + /// Determines if the reader needs to create atoms for the section. + virtual bool ignoreCreateAtomsForSection(const Elf_Shdr *shdr) { + return false; + } + + /// Get the section name for a section. + virtual ErrorOr<StringRef> getSectionName(const Elf_Shdr *shdr) const { + if (!shdr) + return StringRef(); + return _objFile->getSectionName(shdr); + } + + /// Determines if the section occupy memory space. + virtual bool sectionOccupiesMemorySpace(const Elf_Shdr *shdr) const { + return (shdr->sh_type != llvm::ELF::SHT_NOBITS); + } + + /// Return the section contents. + virtual ErrorOr<ArrayRef<uint8_t>> + getSectionContents(const Elf_Shdr *shdr) const { + if (!shdr || !sectionOccupiesMemorySpace(shdr)) + return ArrayRef<uint8_t>(); + return _objFile->getSectionContents(shdr); + } + + /// Returns true if the symbol is a undefined symbol. + virtual bool isUndefinedSymbol(const Elf_Sym *sym) const { + return (sym->st_shndx == llvm::ELF::SHN_UNDEF); + } + + /// Determines if the target wants to create an atom for a section that has no + /// symbol references. + virtual bool + handleSectionWithNoSymbols(const Elf_Shdr *shdr, + std::vector<Elf_Sym_Iter> &symbols) const { + if (shdr && shdr->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty()) + return true; + return false; + } + + /// Process the Undefined symbol and create an atom for it. + virtual ErrorOr<ELFUndefinedAtom<ELFT> *> + handleUndefinedSymbol(StringRef symName, const Elf_Sym *sym) { + return new (_readerStorage) ELFUndefinedAtom<ELFT>(*this, symName, sym); + } + + /// Returns true if the symbol is a absolute symbol. + virtual bool isAbsoluteSymbol(const Elf_Sym *sym) const { + return (sym->st_shndx == llvm::ELF::SHN_ABS); + } + + /// Process the Absolute symbol and create an atom for it. + virtual ErrorOr<ELFAbsoluteAtom<ELFT> *> + handleAbsoluteSymbol(StringRef symName, const Elf_Sym *sym, int64_t value) { + return new (_readerStorage) + ELFAbsoluteAtom<ELFT>(*this, symName, sym, value); + } + + /// Returns true if the symbol is common symbol. A common symbol represents a + /// tentive definition in C. It has name, size and alignment constraint, but + /// actual storage has not yet been allocated. (The linker will allocate + /// storage for them in the later pass after coalescing tentative symbols by + /// name.) + virtual bool isCommonSymbol(const Elf_Sym *symbol) const { + return symbol->getType() == llvm::ELF::STT_COMMON || + symbol->st_shndx == llvm::ELF::SHN_COMMON; + } + + /// Process the common symbol and create an atom for it. + virtual ErrorOr<ELFCommonAtom<ELFT> *> + handleCommonSymbol(StringRef symName, const Elf_Sym *sym) { + return new (_readerStorage) ELFCommonAtom<ELFT>(*this, symName, sym); + } + + /// Returns true if the symbol is a defined symbol. + virtual bool isDefinedSymbol(const Elf_Sym *sym) const { + return (sym->getType() == llvm::ELF::STT_NOTYPE || + sym->getType() == llvm::ELF::STT_OBJECT || + sym->getType() == llvm::ELF::STT_FUNC || + sym->getType() == llvm::ELF::STT_GNU_IFUNC || + sym->getType() == llvm::ELF::STT_SECTION || + sym->getType() == llvm::ELF::STT_FILE || + sym->getType() == llvm::ELF::STT_TLS); + } + + /// Process the Defined symbol and create an atom for it. + virtual ErrorOr<ELFDefinedAtom<ELFT> *> + handleDefinedSymbol(StringRef symName, StringRef sectionName, + const Elf_Sym *sym, const Elf_Shdr *sectionHdr, + ArrayRef<uint8_t> contentData, + unsigned int referenceStart, unsigned int referenceEnd, + std::vector<ELFReference<ELFT> *> &referenceList) { + return new (_readerStorage) ELFDefinedAtom<ELFT>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + } + + /// Process the Merge string and create an atom for it. + virtual ErrorOr<ELFMergeAtom<ELFT> *> + handleMergeString(StringRef sectionName, const Elf_Shdr *sectionHdr, + ArrayRef<uint8_t> contentData, unsigned int offset) { + ELFMergeAtom<ELFT> *mergeAtom = new (_readerStorage) + ELFMergeAtom<ELFT>(*this, sectionName, sectionHdr, contentData, offset); + const MergeSectionKey mergedSectionKey(sectionHdr, offset); + if (_mergedSectionMap.find(mergedSectionKey) == _mergedSectionMap.end()) + _mergedSectionMap.insert(std::make_pair(mergedSectionKey, mergeAtom)); + return mergeAtom; } llvm::BumpPtrAllocator _readerStorage; @@ -225,8 +322,7 @@ protected: /// \brief _relocationAddendReferences 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. + /// which will hold the entries. std::unordered_map< StringRef, range<typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter> > @@ -254,7 +350,6 @@ protected: /// \brief the cached options relevant while reading the ELF File bool _doStringsMerge; - TargetHandler<ELFT> *_targetHandler; }; /// \brief All atoms are owned by a File. To add linker specific atoms @@ -271,53 +366,45 @@ public: /// \brief add a global absolute atom virtual Atom *addAbsoluteAtom(StringRef symbolName) { assert(!symbolName.empty() && "AbsoluteAtoms must have a name"); - Elf_Sym *symbol = new (_allocator) Elf_Sym; + Elf_Sym *symbol = new (this->_readerStorage) Elf_Sym; symbol->st_name = 0; symbol->st_value = 0; symbol->st_shndx = llvm::ELF::SHN_ABS; symbol->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_OBJECT); symbol->st_other = llvm::ELF::STV_DEFAULT; symbol->st_size = 0; - auto *newAtom = - new (_allocator) ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, -1); - this->_absoluteAtoms._atoms.push_back(newAtom); - return newAtom; + auto newAtom = this->handleAbsoluteSymbol(symbolName, symbol, -1); + this->_absoluteAtoms._atoms.push_back(*newAtom); + return *newAtom; } /// \brief add an undefined atom virtual Atom *addUndefinedAtom(StringRef symbolName) { assert(!symbolName.empty() && "UndefinedAtoms must have a name"); - Elf_Sym *symbol = new (_allocator) Elf_Sym; + Elf_Sym *symbol = new (this->_readerStorage) Elf_Sym; symbol->st_name = 0; symbol->st_value = 0; symbol->st_shndx = llvm::ELF::SHN_UNDEF; symbol->st_other = llvm::ELF::STV_DEFAULT; symbol->st_size = 0; - auto *newAtom = - new (_allocator) ELFUndefinedAtom<ELFT>(*this, symbolName, symbol); - this->_undefinedAtoms._atoms.push_back(newAtom); - return newAtom; + auto newAtom = this->handleUndefinedSymbol(symbolName, symbol); + this->_undefinedAtoms._atoms.push_back(*newAtom); + return *newAtom; } // cannot add atoms to C Runtime file virtual void addAtom(const Atom &) { llvm_unreachable("cannot add atoms to Runtime files"); } - -protected: - llvm::BumpPtrAllocator _allocator; }; template <class ELFT> ErrorOr<std::unique_ptr<ELFFile<ELFT>>> -ELFFile<ELFT>::create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings, - TargetHandlerBase *handler) { +ELFFile<ELFT>::create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) { error_code ec; std::unique_ptr<ELFFile<ELFT>> file( new ELFFile<ELFT>(mb->getBufferIdentifier(), atomizeStrings)); - file->setTargetHandler(handler); - file->_objFile.reset(new llvm::object::ELFFile<ELFT>(mb.release(), ec)); if (ec) @@ -426,11 +513,11 @@ template <class ELFT> error_code ELFFile<ELFT>::createMergeableAtoms() { // b) Create a separate section chunk to write mergeable atoms std::vector<MergeString *> tokens; for (const Elf_Shdr *msi : _mergeStringSections) { - auto sectionName = _objFile->getSectionName(msi); + auto sectionName = getSectionName(msi); if (error_code ec = sectionName.getError()) return ec; - auto sectionContents = _objFile->getSectionContents(msi); + auto sectionContents = getSectionContents(msi); if (error_code ec = sectionContents.getError()) return ec; @@ -451,14 +538,11 @@ template <class ELFT> error_code ELFFile<ELFT>::createMergeableAtoms() { for (const MergeString *tai : tokens) { ArrayRef<uint8_t> content((const uint8_t *)tai->_string.data(), tai->_string.size()); - ELFMergeAtom<ELFT> *mergeAtom = new (_readerStorage) ELFMergeAtom<ELFT>( - *this, tai->_sectionName, tai->_shdr, content, tai->_offset); - const MergeSectionKey mergedSectionKey(tai->_shdr, tai->_offset); - if (_mergedSectionMap.find(mergedSectionKey) == _mergedSectionMap.end()) - _mergedSectionMap.insert(std::make_pair(mergedSectionKey, mergeAtom)); - mergeAtom->setOrdinal(++_ordinal); - _definedAtoms._atoms.push_back(mergeAtom); - _mergeAtoms.push_back(mergeAtom); + ErrorOr<ELFMergeAtom<ELFT> *> mergeAtom = + handleMergeString(tai->_sectionName, tai->_shdr, content, tai->_offset); + (*mergeAtom)->setOrdinal(++_ordinal); + _definedAtoms._atoms.push_back(*mergeAtom); + _mergeAtoms.push_back(*mergeAtom); } return error_code::success(); } @@ -480,50 +564,41 @@ error_code ELFFile<ELFT>::createSymbolsFromAtomizableSections() { if (error_code ec = symbolName.getError()) return ec; - if (SymI->st_shndx == llvm::ELF::SHN_ABS) { - // Create an absolute atom. - auto *newAtom = new (_readerStorage) - ELFAbsoluteAtom<ELFT>(*this, *symbolName, &*SymI, SymI->st_value); - - _absoluteAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom)); - } else if (SymI->st_shndx == llvm::ELF::SHN_UNDEF) { - // Create an undefined atom. - auto *newAtom = new (_readerStorage) - ELFUndefinedAtom<ELFT>(*this, *symbolName, &*SymI); - - _undefinedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom)); + if (isAbsoluteSymbol(&*SymI)) { + ErrorOr<ELFAbsoluteAtom<ELFT> *> absAtom = + handleAbsoluteSymbol(*symbolName, &*SymI, SymI->st_value); + _absoluteAtoms._atoms.push_back(*absAtom); + _symbolToAtomMapping.insert(std::make_pair(&*SymI, *absAtom)); + } else if (isUndefinedSymbol(&*SymI)) { + ErrorOr<ELFUndefinedAtom<ELFT> *> undefAtom = + handleUndefinedSymbol(*symbolName, &*SymI); + _undefinedAtoms._atoms.push_back(*undefAtom); + _symbolToAtomMapping.insert(std::make_pair(&*SymI, *undefAtom)); } else if (isCommonSymbol(&*SymI)) { - auto *newAtom = - new (_readerStorage) ELFCommonAtom<ELFT>(*this, *symbolName, &*SymI); - newAtom->setOrdinal(++_ordinal); - _definedAtoms._atoms.push_back(newAtom); - _symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom)); + ErrorOr<ELFCommonAtom<ELFT> *> commonAtom = + handleCommonSymbol(*symbolName, &*SymI); + (*commonAtom)->setOrdinal(++_ordinal); + _definedAtoms._atoms.push_back(*commonAtom); + _symbolToAtomMapping.insert(std::make_pair(&*SymI, *commonAtom)); + } else if (isDefinedSymbol(&*SymI)) { + _sectionSymbols[section].push_back(SymI); } else { - assert(section && "Symbol not defined in a section!"); - // This is actually a defined symbol. Add it to its section's list of - // symbols. - if (SymI->getType() == llvm::ELF::STT_NOTYPE || - SymI->getType() == llvm::ELF::STT_OBJECT || - SymI->getType() == llvm::ELF::STT_FUNC || - SymI->getType() == llvm::ELF::STT_GNU_IFUNC || - SymI->getType() == llvm::ELF::STT_SECTION || - SymI->getType() == llvm::ELF::STT_FILE || - SymI->getType() == llvm::ELF::STT_TLS) { - _sectionSymbols[section].push_back(SymI); - } else { - llvm::errs() << "Unable to create atom for: " << *symbolName << "\n"; - return llvm::object::object_error::parse_failed; - } + llvm::errs() << "Unable to create atom for: " << *symbolName << "\n"; + return llvm::object::object_error::parse_failed; } } + return error_code::success(); } template <class ELFT> error_code ELFFile<ELFT>::createAtoms() { for (auto &i : _sectionSymbols) { const Elf_Shdr *section = i.first; + + // Check if need to create atoms for this section ? + if ((ignoreCreateAtomsForSection(section))) + continue; + std::vector<Elf_Sym_Iter> &symbols = i.second; // Sort symbols by position. @@ -531,25 +606,18 @@ template <class ELFT> error_code ELFFile<ELFT>::createAtoms() { [](Elf_Sym_Iter A, Elf_Sym_Iter B) { return A->st_value < B->st_value; }); - auto sectionName = - section ? _objFile->getSectionName(section) : StringRef(); + ErrorOr<StringRef> sectionName = this->getSectionName(section); if (error_code ec = sectionName.getError()) return ec; - auto sectionContents = - (section && section->sh_type != llvm::ELF::SHT_NOBITS) - ? _objFile->getSectionContents(section) - : ArrayRef<uint8_t>(); - + auto sectionContents = getSectionContents(section); if (error_code ec = sectionContents.getError()) return ec; StringRef secCont(reinterpret_cast<const char *>(sectionContents->begin()), sectionContents->size()); - // If the section has no symbols, create a custom atom for it. - if (section && section->sh_type == llvm::ELF::SHT_PROGBITS && - symbols.empty()) { + if (handleSectionWithNoSymbols(section, symbols)) { ELFDefinedAtom<ELFT> *newAtom = createSectionAtom(section, *sectionName, secCont); _definedAtoms._atoms.push_back(newAtom); @@ -597,11 +665,11 @@ template <class ELFT> error_code ELFFile<ELFT>::createAtoms() { // resolution if (isMergeableStringSection(section)) { if (symbol->getBinding() == llvm::ELF::STB_GLOBAL) { - auto definedMergeAtom = new (_readerStorage) ELFDefinedAtom<ELFT>( - *this, symbolName, *sectionName, &**si, section, symbolData, + auto definedMergeAtom = handleDefinedSymbol( + symbolName, *sectionName, &**si, section, symbolData, _references.size(), _references.size(), _references); - _definedAtoms._atoms.push_back(definedMergeAtom); - definedMergeAtom->setOrdinal(++_ordinal); + _definedAtoms._atoms.push_back(*definedMergeAtom); + (*definedMergeAtom)->setOrdinal(++_ordinal); } continue; } @@ -711,17 +779,16 @@ ELFDefinedAtom<ELFT> *ELFFile<ELFT>::createDefinedAtomAndAssignRelocations( } // 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); + return *handleDefinedSymbol(symbolName, sectionName, symbol, section, content, + referenceStart, _references.size(), _references); } -template <class ELFT> void ELFFile<ELFT>::updateReferences() { - /// cached value of target relocation handler - assert(_targetHandler); - const TargetRelocationHandler<ELFT> &targetRelocationHandler = - _targetHandler->getRelocationHandler(); +template <class ELFT> +int64_t ELFFile<ELFT>::defaultRelocAddend(const Reference &) const { + return 0; +} +template <class ELFT> void ELFFile<ELFT>::updateReferences() { for (auto &ri : _references) { if (ri->kindNamespace() == lld::Reference::KindNamespace::ELF) { const Elf_Sym *symbol = _objFile->getSymbol(ri->targetSymbolIndex()); @@ -737,8 +804,7 @@ template <class ELFT> void ELFFile<ELFT>::updateReferences() { // If the target atom is mergeable string atom, the atom might have been // merged with other atom having the same contents. Try to find the // merged one if that's the case. - int64_t relocAddend = targetRelocationHandler.relocAddend(*ri); - uint64_t addend = ri->addend() + relocAddend; + uint64_t addend = ri->addend() + defaultRelocAddend(*ri); const MergeSectionKey ms(shdr, addend); auto msec = _mergedSectionMap.find(ms); if (msec != _mergedSectionMap.end()) { @@ -816,20 +882,6 @@ ELFFile<ELFT>::createSectionAtom(const Elf_Shdr *section, StringRef sectionName, } template <class ELFT> -bool ELFFile<ELFT>::isCommonSymbol(const Elf_Sym *symbol) { - // This method handles only architecture independent stuffs, and don't know - // whether an architecture dependent section is for common symbols or - // not. Let the TargetHandler to make a decision if that's the case. - if (isTargetSpecificAtom(nullptr, symbol)) { - assert(_targetHandler); - TargetAtomHandler<ELFT> &atomHandler = _targetHandler->targetAtomHandler(); - return atomHandler.getType(symbol) == llvm::ELF::STT_COMMON; - } - return symbol->getType() == llvm::ELF::STT_COMMON || - symbol->st_shndx == llvm::ELF::SHN_COMMON; -} - -template <class ELFT> uint64_t ELFFile<ELFT>::symbolContentSize(const Elf_Shdr *section, const Elf_Sym *symbol, const Elf_Sym *nextSymbol) { diff --git a/lld/lib/ReaderWriter/ELF/ELFReader.h b/lld/lib/ReaderWriter/ELF/ELFReader.h index cdd7a54d04c..6fe2e7ac1be 100644 --- a/lld/lib/ReaderWriter/ELF/ELFReader.h +++ b/lld/lib/ReaderWriter/ELF/ELFReader.h @@ -34,16 +34,14 @@ struct ELFFileCreateELFTraits { template <class ELFT> static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, - bool atomizeStrings, TargetHandlerBase *handler) { - return lld::elf::ELFFile<ELFT>::create(std::move(mb), atomizeStrings, - handler); + bool atomizeStrings) { + return lld::elf::ELFFile<ELFT>::create(std::move(mb), atomizeStrings); } }; class ELFObjectReader : public Reader { public: - ELFObjectReader(bool atomizeStrings, TargetHandlerBase *handler) - : _atomizeStrings(atomizeStrings), _handler(handler) {} + ELFObjectReader(bool atomizeStrings) : _atomizeStrings(atomizeStrings) {} virtual bool canParse(file_magic magic, StringRef, const MemoryBuffer &) const { @@ -57,16 +55,15 @@ public: 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); auto f = createELF<ELFFileCreateELFTraits>( llvm::object::getElfArchType(&*mb), maxAlignment, std::move(mb), - _atomizeStrings, _handler); + _atomizeStrings); if (error_code ec = f.getError()) return ec; result.push_back(std::move(*f)); return error_code::success(); } -private: +protected: bool _atomizeStrings; - TargetHandlerBase *_handler; }; class ELFDSOReader : public Reader { @@ -92,7 +89,7 @@ public: return error_code::success(); } -private: +protected: bool _useUndefines; }; diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h new file mode 100644 index 00000000000..3ebc93aae1a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h @@ -0,0 +1,203 @@ +//===- lib/ReaderWriter/ELF/HexagonELFFile.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_ELF_FILE_H +#define LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H + +#include "ELFReader.h" +#include "HexagonLinkingContext.h" + +namespace lld { +namespace elf { + +template <class ELFT> class HexagonELFFile; + +template <class ELFT> +class HexagonELFDefinedAtom : public ELFDefinedAtom<ELFT> { + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; + +public: + HexagonELFDefinedAtom(const HexagonELFFile<ELFT> &file, StringRef symbolName, + StringRef sectionName, const Elf_Sym *symbol, + const Elf_Shdr *section, ArrayRef<uint8_t> contentData, + unsigned int referenceStart, unsigned int referenceEnd, + std::vector<ELFReference<ELFT> *> &referenceList) + : ELFDefinedAtom<ELFT>(file, symbolName, sectionName, symbol, section, + contentData, referenceStart, referenceEnd, + referenceList) {} + + virtual DefinedAtom::ContentType contentType() const { + if (this->_contentType != DefinedAtom::typeUnknown) + return this->_contentType; + else if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) { + if (this->_section->sh_type == llvm::ELF::SHT_NOBITS) + return (this->_contentType = DefinedAtom::typeZeroFillFast); + else + return (this->_contentType = DefinedAtom::typeDataFast); + } + return ELFDefinedAtom<ELFT>::contentType(); + } + + virtual DefinedAtom::ContentPermissions permissions() const { + if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) + return DefinedAtom::permRW_; + return ELFDefinedAtom<ELFT>::permissions(); + } +}; + +template <class ELFT> class HexagonELFCommonAtom : public ELFCommonAtom<ELFT> { + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; + +public: + HexagonELFCommonAtom(const HexagonELFFile<ELFT> &file, StringRef symbolName, + const Elf_Sym *symbol) + : ELFCommonAtom<ELFT>(file, symbolName, symbol) {} + + virtual bool isSmallCommonSymbol() const { + switch (this->_symbol->st_shndx) { + // Common symbols + case llvm::ELF::SHN_HEXAGON_SCOMMON: + case llvm::ELF::SHN_HEXAGON_SCOMMON_1: + case llvm::ELF::SHN_HEXAGON_SCOMMON_2: + case llvm::ELF::SHN_HEXAGON_SCOMMON_4: + case llvm::ELF::SHN_HEXAGON_SCOMMON_8: + return true; + default: + break; + } + return false; + } + + virtual uint64_t size() const { + if (isSmallCommonSymbol()) + return this->_symbol->st_size; + return ELFCommonAtom<ELFT>::size(); + } + + virtual DefinedAtom::Merge merge() const { + if (this->_symbol->getBinding() == llvm::ELF::STB_WEAK) + return DefinedAtom::mergeAsWeak; + if (isSmallCommonSymbol()) + return DefinedAtom::mergeAsTentative; + return ELFCommonAtom<ELFT>::merge(); + } + + virtual DefinedAtom::ContentType contentType() const { + if (isSmallCommonSymbol()) + return DefinedAtom::typeZeroFillFast; + return ELFCommonAtom<ELFT>::contentType(); + } + + virtual DefinedAtom::Alignment alignment() const { + if (isSmallCommonSymbol()) + return DefinedAtom::Alignment(llvm::Log2_64(this->_symbol->st_value)); + return ELFCommonAtom<ELFT>::alignment(); + } + + virtual DefinedAtom::ContentPermissions permissions() const { + if (isSmallCommonSymbol()) + return DefinedAtom::permRW_; + return ELFCommonAtom<ELFT>::permissions(); + } +}; + +template <class ELFT> class HexagonELFFile : public ELFFile<ELFT> { + typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; + +public: + HexagonELFFile(StringRef name, bool atomizeStrings) + : ELFFile<ELFT>(name, atomizeStrings) {} + + HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings, + error_code &ec) + : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec) {} + + static ErrorOr<std::unique_ptr<HexagonELFFile>> + create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) { + error_code ec; + std::unique_ptr<HexagonELFFile<ELFT>> file( + new HexagonELFFile<ELFT>(mb->getBufferIdentifier(), atomizeStrings)); + + file->_objFile.reset(new llvm::object::ELFFile<ELFT>(mb.release(), ec)); + + if (ec) + return ec; + + // Read input sections from the input file that need to be converted to + // atoms + if ((ec = file->createAtomizableSections())) + return ec; + + // For mergeable strings, we would need to split the section into various + // atoms + if ((ec = file->createMergeableAtoms())) + return ec; + + // Create the necessary symbols that are part of the section that we + // created in createAtomizableSections function + if ((ec = file->createSymbolsFromAtomizableSections())) + return ec; + + // Create the appropriate atoms from the file + if ((ec = file->createAtoms())) + return ec; + + return std::move(file); + } + + virtual bool isCommonSymbol(const Elf_Sym *symbol) const { + switch (symbol->st_shndx) { + // Common symbols + case llvm::ELF::SHN_HEXAGON_SCOMMON: + case llvm::ELF::SHN_HEXAGON_SCOMMON_1: + case llvm::ELF::SHN_HEXAGON_SCOMMON_2: + case llvm::ELF::SHN_HEXAGON_SCOMMON_4: + case llvm::ELF::SHN_HEXAGON_SCOMMON_8: + return llvm::ELF::STT_COMMON; + + default: + break; + } + return ELFFile<ELFT>::isCommonSymbol(symbol); + } + + /// Process the Defined symbol and create an atom for it. + virtual ErrorOr<ELFDefinedAtom<ELFT> *> + handleDefinedSymbol(StringRef symName, StringRef sectionName, + const Elf_Sym *sym, const Elf_Shdr *sectionHdr, + ArrayRef<uint8_t> contentData, + unsigned int referenceStart, unsigned int referenceEnd, + std::vector<ELFReference<ELFT> *> &referenceList) { + return new (this->_readerStorage) HexagonELFDefinedAtom<ELFT>( + *this, symName, sectionName, sym, sectionHdr, contentData, + referenceStart, referenceEnd, referenceList); + } + + /// Process the Common symbol and create an atom for it. + virtual ErrorOr<ELFCommonAtom<ELFT> *> + handleCommonSymbol(StringRef symName, const Elf_Sym *sym) { + return new (this->_readerStorage) + HexagonELFCommonAtom<ELFT>(*this, symName, sym); + } +}; + +template <class ELFT> class HexagonDynamicFile : public DynamicFile<ELFT> { +public: + HexagonDynamicFile(const HexagonLinkingContext &context, StringRef name) + : DynamicFile<ELFT>(context, name) {} +}; + +} // elf +} // lld + +#endif // LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h new file mode 100644 index 00000000000..3585996683d --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h @@ -0,0 +1,84 @@ +//===- lib/ReaderWriter/ELF/HexagonELFReader.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_HEXAGON_ELF_READER_H +#define LLD_READER_WRITER_HEXAGON_ELF_READER_H + +#include "ELFReader.h" +#include "HexagonELFFile.h" + +namespace lld { +namespace elf { + +struct HexagonDynamicFileCreateELFTraits { + typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type; + + template <class ELFT> + static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, + bool useUndefines) { + return lld::elf::HexagonDynamicFile<ELFT>::create(std::move(mb), + useUndefines); + } +}; + +struct HexagonELFFileCreateELFTraits { + typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type; + + template <class ELFT> + static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, + bool atomizeStrings) { + return lld::elf::HexagonELFFile<ELFT>::create(std::move(mb), + atomizeStrings); + } +}; + +class HexagonELFObjectReader : public ELFObjectReader { +public: + HexagonELFObjectReader(bool atomizeStrings) + : ELFObjectReader(atomizeStrings) {} + + virtual error_code + parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &, + std::vector<std::unique_ptr<File>> &result) const { + std::size_t maxAlignment = + 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); + auto f = createELF<HexagonELFFileCreateELFTraits>( + llvm::object::getElfArchType(&*mb), maxAlignment, std::move(mb), + _atomizeStrings); + if (error_code ec = f.getError()) + return ec; + result.push_back(std::move(*f)); + return error_code::success(); + } +}; + +class HexagonELFDSOReader : public ELFDSOReader { +public: + HexagonELFDSOReader(bool useUndefines) : ELFDSOReader(useUndefines) {} + + virtual error_code + parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &, + std::vector<std::unique_ptr<File>> &result) const { + std::size_t maxAlignment = + 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); + auto f = createELF<HexagonDynamicFileCreateELFTraits>( + llvm::object::getElfArchType(&*mb), maxAlignment, std::move(mb), + _useUndefines); + if (error_code ec = f.getError()) + return ec; + result.push_back(std::move(*f)); + return error_code::success(); + } +}; + +} // namespace elf +} // namespace lld + +#endif // LLD_READER_WRITER_ELF_READER_H diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp index 9f539a8da87..ceab5d3c031 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp @@ -9,6 +9,7 @@ #include "Atoms.h" #include "HexagonLinkingContext.h" +#include "HexagonTargetHandler.h" #include "lld/Core/File.h" #include "lld/Core/Pass.h" @@ -101,3 +102,7 @@ void elf::HexagonLinkingContext::createInternalFiles( initFiniFile->addFiniFunction(ai); result.push_back(std::move(initFiniFile)); } + +HexagonLinkingContext::HexagonLinkingContext(llvm::Triple triple) + : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>( + new HexagonTargetHandler(*this))) {} diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h index c2bf5fea1e9..6eb619675d9 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h @@ -10,8 +10,6 @@ #ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_LINKING_CONTEXT_H #define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_LINKING_CONTEXT_H -#include "HexagonTargetHandler.h" - #include "lld/ReaderWriter/ELFLinkingContext.h" #include "llvm/Object/ELF.h" @@ -22,9 +20,7 @@ namespace elf { class HexagonLinkingContext LLVM_FINAL : public ELFLinkingContext { public: - HexagonLinkingContext(llvm::Triple triple) - : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>( - new HexagonTargetHandler(*this))) {} + HexagonLinkingContext(llvm::Triple triple); virtual void addPasses(PassManager &); diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h index f10a3000ef9..4052bed4d9a 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h @@ -15,68 +15,13 @@ #include "HexagonRelocationHandler.h" #include "HexagonSectionChunks.h" #include "TargetLayout.h" +#include "HexagonELFReader.h" namespace lld { namespace elf { typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType; class HexagonLinkingContext; -/// \brief Handle Hexagon specific Atoms -template <class HexagonELFType> -class HexagonTargetAtomHandler LLVM_FINAL : - public TargetAtomHandler<HexagonELFType> { - typedef llvm::object::Elf_Sym_Impl<HexagonELFType> Elf_Sym; - typedef llvm::object::Elf_Shdr_Impl<HexagonELFType> Elf_Shdr; -public: - - virtual DefinedAtom::ContentType - contentType(const ELFDefinedAtom<HexagonELFType> *atom) const { - return contentType(atom->section(), atom->symbol()); - } - - virtual DefinedAtom::ContentType - contentType(const Elf_Shdr *section, const Elf_Sym *sym) const { - switch (sym->st_shndx) { - // Common symbols - case llvm::ELF::SHN_HEXAGON_SCOMMON: - case llvm::ELF::SHN_HEXAGON_SCOMMON_1: - case llvm::ELF::SHN_HEXAGON_SCOMMON_2: - case llvm::ELF::SHN_HEXAGON_SCOMMON_4: - case llvm::ELF::SHN_HEXAGON_SCOMMON_8: - return DefinedAtom::typeZeroFillFast; - - default: - if (section->sh_type == llvm::ELF::SHT_NOBITS) - return DefinedAtom::typeZeroFillFast; - else if (section->sh_flags & llvm::ELF::SHF_HEX_GPREL) - return DefinedAtom::typeDataFast; - else - llvm_unreachable("unknown symbol type"); - } - } - - virtual DefinedAtom::ContentPermissions - contentPermissions(const ELFDefinedAtom<HexagonELFType> *atom) const { - // All of the hexagon specific symbols belong in the data segment - return DefinedAtom::permRW_; - } - - virtual int64_t getType(const Elf_Sym *sym) const { - switch (sym->st_shndx) { - // Common symbols - case llvm::ELF::SHN_HEXAGON_SCOMMON: - case llvm::ELF::SHN_HEXAGON_SCOMMON_1: - case llvm::ELF::SHN_HEXAGON_SCOMMON_2: - case llvm::ELF::SHN_HEXAGON_SCOMMON_4: - case llvm::ELF::SHN_HEXAGON_SCOMMON_8: - return llvm::ELF::STT_COMMON; - - default: - return sym->getType(); - } - } -}; - /// \brief TargetLayout for Hexagon template <class HexagonELFType> class HexagonTargetLayout LLVM_FINAL : public TargetLayout<HexagonELFType> { @@ -165,10 +110,6 @@ public: return _targetLayout; } - virtual HexagonTargetAtomHandler<HexagonELFType> &targetAtomHandler() { - return _targetAtomHandler; - } - virtual const HexagonTargetRelocationHandler &getRelocationHandler() const { return _relocationHandler; } @@ -216,12 +157,19 @@ public: return _gotSymAtom->_virtualAddr; } + virtual std::unique_ptr<Reader> getObjReader(bool atomizeStrings) { + return std::unique_ptr<Reader>(new HexagonELFObjectReader(atomizeStrings)); + } + + virtual std::unique_ptr<Reader> getDSOReader(bool useShlibUndefines) { + return std::unique_ptr<Reader>(new HexagonELFDSOReader(useShlibUndefines)); + } + private: static const Registry::KindStrings kindStrings[]; HexagonTargetLayout<HexagonELFType> _targetLayout; HexagonTargetRelocationHandler _relocationHandler; - HexagonTargetAtomHandler<HexagonELFType> _targetAtomHandler; std::unique_ptr<HexagonRuntimeFile<HexagonELFType> > _hexagonRuntimeFile; AtomLayout *_gotSymAtom; }; diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h b/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h index b242fad5070..799123ee275 100644 --- a/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.h @@ -19,6 +19,7 @@ namespace lld { namespace elf { + class PPCLinkingContext LLVM_FINAL : public ELFLinkingContext { public: PPCLinkingContext(llvm::Triple triple) diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h index 8f1de5c3349..5468874fb65 100644 --- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.h @@ -44,7 +44,7 @@ public: private: static const Registry::KindStrings kindStrings[]; - + PPCTargetRelocationHandler _relocationHandler; TargetLayout<PPCELFType> _targetLayout; }; diff --git a/lld/lib/ReaderWriter/ELF/Reader.cpp b/lld/lib/ReaderWriter/ELF/Reader.cpp index 17bc546459b..96eb4b05d36 100644 --- a/lld/lib/ReaderWriter/ELF/Reader.cpp +++ b/lld/lib/ReaderWriter/ELF/Reader.cpp @@ -39,16 +39,14 @@ struct ELFFileCreateELFTraits { template <class ELFT> static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, - bool atomizeStrings, TargetHandlerBase *handler) { - return lld::elf::ELFFile<ELFT>::create(std::move(mb), atomizeStrings, - handler); + bool atomizeStrings) { + return lld::elf::ELFFile<ELFT>::create(std::move(mb), atomizeStrings); } }; class ELFObjectReader : public Reader { public: - ELFObjectReader(bool atomizeStrings, TargetHandlerBase *handler) - : _atomizeStrings(atomizeStrings), _handler(handler) {} + ELFObjectReader(bool atomizeStrings) : _atomizeStrings(atomizeStrings) {} virtual bool canParse(file_magic magic, StringRef, const MemoryBuffer &) const { @@ -61,9 +59,8 @@ public: error_code ec; std::size_t maxAlignment = 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart())); - auto f = createELF<ELFFileCreateELFTraits>(getElfArchType(&*mb), - maxAlignment, std::move(mb), - _atomizeStrings, _handler); + auto f = createELF<ELFFileCreateELFTraits>( + getElfArchType(&*mb), maxAlignment, std::move(mb), _atomizeStrings); if (error_code ec = f.getError()) return ec; result.push_back(std::move(*f)); @@ -72,7 +69,6 @@ public: private: bool _atomizeStrings; - TargetHandlerBase *_handler; }; class ELFDSOReader : public Reader { @@ -111,15 +107,16 @@ void Registry::addSupportELFObjects(bool atomizeStrings, TargetHandlerBase *handler) { // Tell registry about the ELF object file parser. - add(std::unique_ptr<Reader>( - new elf::ELFObjectReader(atomizeStrings, handler))); + add(std::move(handler->getObjReader(atomizeStrings))); // Tell registry about the relocation name to number mapping for this arch. handler->registerRelocationNames(*this); } -void Registry::addSupportELFDynamicSharedObjects(bool useShlibUndefines) { - add(std::unique_ptr<Reader>(new elf::ELFDSOReader(useShlibUndefines))); +void Registry::addSupportELFDynamicSharedObjects(bool useShlibUndefines, + TargetHandlerBase *handler) { + // Tell registry about the ELF dynamic shared library file parser. + add(handler->getDSOReader(useShlibUndefines)); } } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/TargetHandler.h b/lld/lib/ReaderWriter/ELF/TargetHandler.h index c2c30de165c..eb5c0de7091 100644 --- a/lld/lib/ReaderWriter/ELF/TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/TargetHandler.h @@ -40,44 +40,12 @@ template <class ELFT> class ELFHeader; template <class ELFT> class Section; template <class ELFT> class TargetLayout; -/// \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 -template <class ELFT> class TargetAtomHandler { -public: - typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; - typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym; - - virtual DefinedAtom::ContentType - contentType(const ELFDefinedAtom<ELFT> *atom) const { - return atom->contentType(); - } - - virtual DefinedAtom::ContentType - contentType(const Elf_Shdr *shdr, const Elf_Sym *sym) const { - return DefinedAtom::typeZeroFill; - } - - virtual DefinedAtom::ContentPermissions - contentPermissions(const ELFDefinedAtom<ELFT> *atom) const { - return atom->permissions(); - } - - virtual int64_t getType(const Elf_Sym *sym) const { - return llvm::ELF::STT_NOTYPE; - } - - virtual ~TargetAtomHandler() {} -}; - template <class ELFT> class TargetRelocationHandler { public: virtual error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, const Reference &) const = 0; - virtual int64_t relocAddend(const Reference &)const { return 0; } - virtual ~TargetRelocationHandler() {} }; @@ -99,9 +67,6 @@ public: /// TargetLayout virtual TargetLayout<ELFT> &targetLayout() = 0; - /// TargetAtomHandler - virtual TargetAtomHandler<ELFT> &targetAtomHandler() = 0; - virtual const TargetRelocationHandler<ELFT> &getRelocationHandler() const = 0; /// Create a set of Default target sections that a target might needj @@ -127,6 +92,10 @@ public: virtual LLD_UNIQUE_BUMP_PTR(DynamicSymbolTable<ELFT>) createDynamicSymbolTable() = 0; + virtual std::unique_ptr<Reader> getObjReader(bool) = 0; + + virtual std::unique_ptr<Reader> getDSOReader(bool) = 0; + protected: ELFLinkingContext &_context; }; |

