//===- 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 { class HexagonELFFile; class HexagonELFDefinedAtom : public ELFDefinedAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; public: template HexagonELFDefinedAtom(T &&... args) : ELFDefinedAtom(std::forward(args)...) {} DefinedAtom::ContentType contentType() const override { if (_contentType != DefinedAtom::typeUnknown) return _contentType; if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) { if (_section->sh_type == llvm::ELF::SHT_NOBITS) return (_contentType = DefinedAtom::typeZeroFillFast); return (_contentType = DefinedAtom::typeDataFast); } return ELFDefinedAtom::contentType(); } DefinedAtom::ContentPermissions permissions() const override { if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) return DefinedAtom::permRW_; return ELFDefinedAtom::permissions(); } }; class HexagonELFCommonAtom : public ELFCommonAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; public: HexagonELFCommonAtom(const ELFFile &file, StringRef symbolName, const Elf_Sym *symbol) : ELFCommonAtom(file, symbolName, symbol) {} virtual bool isSmallCommonSymbol() 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 true; default: break; } return false; } uint64_t size() const override { if (isSmallCommonSymbol()) return _symbol->st_size; return ELFCommonAtom::size(); } DefinedAtom::Merge merge() const override { if (_symbol->getBinding() == llvm::ELF::STB_WEAK) return DefinedAtom::mergeAsWeak; if (isSmallCommonSymbol()) return DefinedAtom::mergeAsTentative; return ELFCommonAtom::merge(); } DefinedAtom::ContentType contentType() const override { if (isSmallCommonSymbol()) return DefinedAtom::typeZeroFillFast; return ELFCommonAtom::contentType(); } DefinedAtom::Alignment alignment() const override { if (isSmallCommonSymbol()) return DefinedAtom::Alignment(_symbol->st_value); return 1; } DefinedAtom::ContentPermissions permissions() const override { if (isSmallCommonSymbol()) return DefinedAtom::permRW_; return ELFCommonAtom::permissions(); } }; class HexagonELFFile : public ELFFile { typedef llvm::object::Elf_Sym_Impl Elf_Sym; typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; public: HexagonELFFile(std::unique_ptr mb, ELFLinkingContext &ctx) : ELFFile(std::move(mb), ctx) {} bool isCommonSymbol(const Elf_Sym *symbol) const override { 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 true; default: break; } return ELFFile::isCommonSymbol(symbol); } /// Process the Defined symbol and create an atom for it. ELFDefinedAtom *createDefinedAtom( StringRef symName, StringRef sectionName, const Elf_Sym *sym, const Elf_Shdr *sectionHdr, ArrayRef contentData, unsigned int referenceStart, unsigned int referenceEnd, std::vector *> &referenceList) override { return new (_readerStorage) HexagonELFDefinedAtom( *this, symName, sectionName, sym, sectionHdr, contentData, referenceStart, referenceEnd, referenceList); } /// Process the Common symbol and create an atom for it. ELFCommonAtom *createCommonAtom(StringRef symName, const Elf_Sym *sym) override { return new (_readerStorage) HexagonELFCommonAtom(*this, symName, sym); } }; } // elf } // lld #endif // LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H