diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h')
| -rw-r--r-- | lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h | 174 |
1 files changed, 77 insertions, 97 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h index de9390f2b3074..e545f65dc419a 100644 --- a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h +++ b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h @@ -9,23 +9,81 @@ #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 ELFType> class MipsGOTSection : public AtomSection<ELFType> { +template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> { public: - MipsGOTSection(const MipsLinkingContext &ctx) - : AtomSection<ELFType>(ctx, ".got", DefinedAtom::typeGOT, - DefinedAtom::permRW_, - MipsTargetLayout<ELFType>::ORDER_GOT), - _hasNonLocal(false), _localCount(0) { - this->_flags |= SHF_MIPS_GPREL; - this->_alignment = 4; - } + MipsGOTSection(const MipsLinkingContext &ctx); /// \brief Number of local GOT entries. std::size_t getLocalCount() const { return _localCount; } @@ -39,47 +97,9 @@ public: } /// \brief Compare two atoms accordingly theirs positions in the GOT. - bool compare(const Atom *a, const Atom *b) const { - auto ia = _posMap.find(a); - auto ib = _posMap.find(b); + bool compare(const Atom *a, const Atom *b) const; - if (ia != _posMap.end() && ib != _posMap.end()) - return ia->second < ib->second; - - return ia == _posMap.end() && ib != _posMap.end(); - } - - const lld::AtomLayout *appendAtom(const Atom *atom) override { - const DefinedAtom *da = dyn_cast<DefinedAtom>(atom); - - for (const auto &r : *da) { - if (r->kindNamespace() != lld::Reference::KindNamespace::ELF) - continue; - assert(r->kindArch() == Reference::KindArch::Mips); - switch (r->kindValue()) { - case LLD_R_MIPS_GLOBAL_GOT: - _hasNonLocal = true; - _posMap[r->target()] = _posMap.size(); - return AtomSection<ELFType>::appendAtom(atom); - case R_MIPS_TLS_TPREL32: - case R_MIPS_TLS_DTPREL32: - case R_MIPS_TLS_TPREL64: - case R_MIPS_TLS_DTPREL64: - _hasNonLocal = true; - _tlsMap[r->target()] = _tlsMap.size(); - return AtomSection<ELFType>::appendAtom(atom); - case R_MIPS_TLS_DTPMOD32: - case R_MIPS_TLS_DTPMOD64: - _hasNonLocal = true; - break; - } - } - - if (!_hasNonLocal) - ++_localCount; - - return AtomSection<ELFType>::appendAtom(atom); - } + const AtomLayout *appendAtom(const Atom *atom) override; private: /// \brief True if the GOT contains non-local entries. @@ -96,35 +116,13 @@ private: }; /// \brief Handle Mips PLT section -template <class ELFType> class MipsPLTSection : public AtomSection<ELFType> { +template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> { public: - MipsPLTSection(const MipsLinkingContext &ctx) - : AtomSection<ELFType>(ctx, ".plt", DefinedAtom::typeGOT, - DefinedAtom::permR_X, - MipsTargetLayout<ELFType>::ORDER_PLT) {} - - const AtomLayout *findPLTLayout(const Atom *plt) const { - auto it = _pltLayoutMap.find(plt); - return it != _pltLayoutMap.end() ? it->second : nullptr; - } - - const lld::AtomLayout *appendAtom(const Atom *atom) override { - const auto *layout = AtomSection<ELFType>::appendAtom(atom); - - const DefinedAtom *da = cast<DefinedAtom>(atom); + MipsPLTSection(const MipsLinkingContext &ctx); - for (const auto &r : *da) { - if (r->kindNamespace() != lld::Reference::KindNamespace::ELF) - continue; - assert(r->kindArch() == Reference::KindArch::Mips); - if (r->kindValue() == LLD_R_MIPS_STO_PLT) { - _pltLayoutMap[r->target()] = layout; - break; - } - } + const AtomLayout *findPLTLayout(const Atom *plt) const; - return layout; - } + const AtomLayout *appendAtom(const Atom *atom) override; private: /// \brief Map PLT Atoms to their layouts. @@ -135,33 +133,15 @@ 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; - static const bool _isMips64EL = - ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; - public: - MipsRelocationTable(const ELFLinkingContext &context, StringRef str, - int32_t order) - : RelocationTable<ELFT>(context, str, order) {} + MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str, + int32_t order); protected: void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, - const Reference &ref) override { - uint32_t rType = ref.kindValue() | (ref.tag() << 8); - r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL); - r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); - // The addend is used only by relative relocations - if (this->_context.isRelativeReloc(ref)) - r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend(); - else - r.r_addend = 0; - } - + const Reference &ref) override; void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, - const Reference &ref) override { - uint32_t rType = ref.kindValue() | (ref.tag() << 8); - r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL); - r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); - } + const Reference &ref) override; }; } // elf |
