//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.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_TARGET_HANDLER_H #define LLD_READER_WRITER_ELF_HEXAGON_TARGET_HANDLER_H #include "DefaultTargetHandler.h" #include "HexagonExecutableAtoms.h" #include "HexagonRelocationHandler.h" #include "HexagonSectionChunks.h" #include "TargetLayout.h" namespace lld { namespace elf { typedef llvm::object::ELFType HexagonELFType; class HexagonTargetInfo; /// \brief Handle Hexagon specific Atoms template class HexagonTargetAtomHandler LLVM_FINAL : public TargetAtomHandler { typedef llvm::object::Elf_Sym_Impl Elf_Sym; typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; public: virtual DefinedAtom::ContentType contentType(const ELFDefinedAtom *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_flags & llvm::ELF::SHF_HEX_GPREL) return DefinedAtom::typeDataFast; else llvm_unreachable("unknown symbol type"); } } virtual DefinedAtom::ContentPermissions contentPermissions(const ELFDefinedAtom *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 HexagonTargetLayout LLVM_FINAL : public TargetLayout { public: enum HexagonSectionOrder { ORDER_SDATA = 205 }; HexagonTargetLayout(const HexagonTargetInfo &hti) : TargetLayout(hti), _sdataSection(nullptr) { _sdataSection = new (_alloc) SDataSection(hti); } /// \brief Return the section order for a input section virtual Layout::SectionOrder getSectionOrder( StringRef name, int32_t contentType, int32_t contentPermissions) { if ((contentType == DefinedAtom::typeDataFast) || (contentType == DefinedAtom::typeZeroFillFast)) return ORDER_SDATA; return DefaultLayout::getSectionOrder(name, contentType, contentPermissions); } /// \brief This maps the input sections to the output section names virtual StringRef getSectionName(StringRef name, const int32_t contentType, const int32_t contentPermissions) { if ((contentType == DefinedAtom::typeDataFast) || (contentType == DefinedAtom::typeZeroFillFast)) return ".sdata"; return DefaultLayout::getSectionName(name, contentType, contentPermissions); } /// \brief Gets or creates a section. virtual AtomSection * createSection(StringRef name, int32_t contentType, DefinedAtom::ContentPermissions contentPermissions, Layout::SectionOrder sectionOrder) { if ((contentType == DefinedAtom::typeDataFast) || (contentType == DefinedAtom::typeZeroFillFast)) return _sdataSection; return DefaultLayout::createSection( name, contentType, contentPermissions, sectionOrder); } /// \brief get the segment type for the section thats defined by the target virtual Layout::SegmentType getSegmentType(Section *section) const { if (section->order() == ORDER_SDATA) return PT_LOAD; return DefaultLayout::getSegmentType(section); } Section *getSDataSection() const { return _sdataSection; } private: llvm::BumpPtrAllocator _alloc; SDataSection *_sdataSection; }; /// \brief TargetHandler for Hexagon class HexagonTargetHandler LLVM_FINAL : public DefaultTargetHandler { public: HexagonTargetHandler(HexagonTargetInfo &targetInfo); bool doesOverrideHeader() { return true; } void setHeaderInfo(Header *header) { header->e_ident(llvm::ELF::EI_VERSION, 1); header->e_ident(llvm::ELF::EI_OSABI, 0); header->e_version(1); header->e_flags(0x3); } virtual HexagonTargetLayout &targetLayout() { return _targetLayout; } virtual HexagonTargetAtomHandler &targetAtomHandler() { return _targetAtomHandler; } virtual const HexagonTargetRelocationHandler &getRelocationHandler() const { return _relocationHandler; } void addDefaultAtoms() { _hexagonRuntimeFile.addAbsoluteAtom("_SDA_BASE_"); } virtual void addFiles(InputFiles &inputFiles) { addDefaultAtoms(); inputFiles.prependFile(_hexagonRuntimeFile); } void finalizeSymbolValues() { auto sdabaseAtomIter = _targetLayout.findAbsoluteAtom("_SDA_BASE_"); (*sdabaseAtomIter)->_virtualAddr = _targetLayout.getSDataSection()->virtualAddr(); } private: HexagonTargetLayout _targetLayout; HexagonTargetRelocationHandler _relocationHandler; HexagonTargetAtomHandler _targetAtomHandler; HexagonRuntimeFile _hexagonRuntimeFile; }; } // end namespace elf } // end namespace lld #endif