//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.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_MIPS_MIPS_SECTION_CHUNKS_H #define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H #include "SectionChunks.h" namespace lld { namespace elf { template class MipsTargetLayout; class MipsLinkingContext; /// \brief Handle Mips .reginfo section template class MipsReginfoSection : public Section { public: typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; MipsReginfoSection(const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_RegInfo ®info); StringRef segmentKindToStr() const override { return "REGINFO"; } bool hasOutputSegment() const override { return true; } void write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) override; void finalize() override; private: Elf_Mips_RegInfo _reginfo; MipsTargetLayout &_targetLayout; }; /// \brief Handle .MIPS.options section template class MipsOptionsSection : public Section { public: typedef llvm::object::Elf_Mips_Options Elf_Mips_Options; typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; MipsOptionsSection(const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_RegInfo ®info); bool hasOutputSegment() const override { return true; } void write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) override; void finalize() override; private: Elf_Mips_Options _header; Elf_Mips_RegInfo _reginfo; MipsTargetLayout &_targetLayout; }; /// \brief Handle .MIPS.abiflags section template class MipsAbiFlagsSection : public Section { public: typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; MipsAbiFlagsSection(const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_ABIFlags &abiFlags); bool hasOutputSegment() const override { return true; } void write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) override; void finalize() override; private: Elf_Mips_ABIFlags _abiFlags; MipsTargetLayout &_targetLayout; }; /// \brief Handle Mips GOT section template class MipsGOTSection : public AtomSection { public: MipsGOTSection(const MipsLinkingContext &ctx); /// \brief Number of local GOT entries. std::size_t getLocalCount() const { return _localCount; } /// \brief Number of global GOT entries. std::size_t getGlobalCount() const { return _posMap.size(); } /// \brief Does the atom have a global GOT entry? bool hasGlobalGOTEntry(const Atom *a) const { return _posMap.count(a) || _tlsMap.count(a); } /// \brief Compare two atoms accordingly theirs positions in the GOT. bool compare(const Atom *a, const Atom *b) const; const AtomLayout *appendAtom(const Atom *atom) override; private: /// \brief True if the GOT contains non-local entries. bool _hasNonLocal; /// \brief Number of local GOT entries. std::size_t _localCount; /// \brief Map TLS Atoms to their GOT entry index. llvm::DenseMap _tlsMap; /// \brief Map Atoms to their GOT entry index. llvm::DenseMap _posMap; }; /// \brief Handle Mips PLT section template class MipsPLTSection : public AtomSection { public: MipsPLTSection(const MipsLinkingContext &ctx); const AtomLayout *findPLTLayout(const Atom *plt) const; const AtomLayout *appendAtom(const Atom *atom) override; private: /// \brief Map PLT Atoms to their layouts. std::unordered_map _pltLayoutMap; }; template class MipsRelocationTable : public RelocationTable { typedef llvm::object::Elf_Rel_Impl Elf_Rel; typedef llvm::object::Elf_Rel_Impl Elf_Rela; public: MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order); protected: void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, const Reference &ref) override; void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, const Reference &ref) override; }; } // elf } // lld #endif