//===- 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. // //===----------------------------------------------------------------------===// /// /// \file /// \brief These interfaces provide target specific hooks to change the linker's /// behaivor. /// //===----------------------------------------------------------------------===// #ifndef LLD_READER_WRITER_ELF_TARGETHANDLER_H #define LLD_READER_WRITER_ELF_TARGETHANDLER_H #include "lld/Core/InputFiles.h" #include "lld/Core/LinkerOptions.h" #include "lld/Core/LLVM.h" #include "lld/Core/TargetInfo.h" #include "lld/ReaderWriter/ELFTargetInfo.h" #include "llvm/ADT/Hashing.h" #include #include #include namespace lld { template class ELFDefinedAtom; namespace elf { template class ELFTargetLayout; template class ELFHeader; template class Section; /// \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 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 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) {} /// Register a Target, so that the target backend may choose on how to merge /// individual atoms within the section, this is a way to control output order /// of atoms that is determined by the target void registerTargetSection(StringRef name, DefinedAtom::ContentPermissions perm) { const TargetSectionKey targetSection(name, perm); if (_registeredTargetSections.find(targetSection) == _registeredTargetSections.end()) _registeredTargetSections.insert(std::make_pair(targetSection, true)); } /// Check if the section is registered given the section name and its /// contentType, if they are registered the target would need to /// create a section so that atoms insert, atom virtual address assignment /// could be overridden and controlled by the Target bool isSectionRegisteredByTarget(StringRef name, DefinedAtom::ContentPermissions perm) { const TargetSectionKey targetSection(name, perm); if (_registeredTargetSections.find(targetSection) == _registeredTargetSections.end()) return false; return true; } /// 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; private: struct TargetSectionKey { TargetSectionKey(StringRef name, DefinedAtom::ContentPermissions perm) : _name(name), _perm(perm) { } // Data members const StringRef _name; DefinedAtom::ContentPermissions _perm; }; struct TargetSectionKeyHash { int64_t operator()(const TargetSectionKey &k) const { return llvm::hash_combine(k._name, k._perm); } }; struct TargetSectionKeyEq { bool operator()(const TargetSectionKey &lhs, const TargetSectionKey &rhs) const { return ((lhs._name == rhs._name) && (lhs._perm == rhs._perm)); } }; typedef std::unordered_map RegisteredTargetSectionMapT; typedef typename RegisteredTargetSectionMapT::iterator RegisteredTargetSectionMapIterT; protected: const ELFTargetInfo &_targetInfo; RegisteredTargetSectionMapT _registeredTargetSections; }; } // elf } // lld #endif // LLD_READER_WRITER_ELF_TARGETHANDLER_H