| //===- 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 <typename ELFT> class MipsTargetLayout; |
| class MipsLinkingContext; |
| |
| /// \brief Handle Mips .reginfo section |
| template <class ELFT> class MipsReginfoSection : public Section<ELFT> { |
| public: |
| typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo; |
| |
| MipsReginfoSection(const ELFLinkingContext &ctx, |
| MipsTargetLayout<ELFT> &targetLayout, |
| const Elf_Mips_RegInfo ®info); |
| |
| StringRef segmentKindToStr() const override { return "REGINFO"; } |
| bool hasOutputSegment() const override { return true; } |
| |
| void write(ELFWriter *writer, TargetLayout<ELFT> &layout, |
| llvm::FileOutputBuffer &buffer) override; |
| void finalize() override; |
| |
| private: |
| Elf_Mips_RegInfo _reginfo; |
| MipsTargetLayout<ELFT> &_targetLayout; |
| }; |
| |
| /// \brief Handle .MIPS.options section |
| template <class ELFT> class MipsOptionsSection : public Section<ELFT> { |
| public: |
| typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options; |
| typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo; |
| |
| MipsOptionsSection(const ELFLinkingContext &ctx, |
| MipsTargetLayout<ELFT> &targetLayout, |
| const Elf_Mips_RegInfo ®info); |
| |
| bool hasOutputSegment() const override { return true; } |
| |
| void write(ELFWriter *writer, TargetLayout<ELFT> &layout, |
| llvm::FileOutputBuffer &buffer) override; |
| void finalize() override; |
| |
| private: |
| Elf_Mips_Options _header; |
| Elf_Mips_RegInfo _reginfo; |
| MipsTargetLayout<ELFT> &_targetLayout; |
| }; |
| |
| /// \brief Handle .MIPS.abiflags section |
| template <class ELFT> class MipsAbiFlagsSection : public Section<ELFT> { |
| public: |
| typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags; |
| |
| MipsAbiFlagsSection(const ELFLinkingContext &ctx, |
| MipsTargetLayout<ELFT> &targetLayout, |
| const Elf_Mips_ABIFlags &abiFlags); |
| |
| bool hasOutputSegment() const override { return true; } |
| |
| void write(ELFWriter *writer, TargetLayout<ELFT> &layout, |
| llvm::FileOutputBuffer &buffer) override; |
| void finalize() override; |
| |
| private: |
| Elf_Mips_ABIFlags _abiFlags; |
| MipsTargetLayout<ELFT> &_targetLayout; |
| }; |
| |
| /// \brief Handle Mips GOT section |
| template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> { |
| 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<const Atom *, std::size_t> _tlsMap; |
| |
| /// \brief Map Atoms to their GOT entry index. |
| llvm::DenseMap<const Atom *, std::size_t> _posMap; |
| }; |
| |
| /// \brief Handle Mips PLT section |
| template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> { |
| 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<const Atom *, const AtomLayout *> _pltLayoutMap; |
| }; |
| |
| template <class ELFT> class MipsRelocationTable : public RelocationTable<ELFT> { |
| typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; |
| typedef llvm::object::Elf_Rel_Impl<ELFT, true> 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 |