//===- 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 namespace lld { namespace elf { template class MipsTargetLayout; class MipsLinkingContext; /// \brief Handle Mips GOT section template class MipsGOTSection : public AtomSection { public: MipsGOTSection(const MipsLinkingContext &context) : AtomSection(context, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_, MipsTargetLayout::ORDER_GOT), _globalCount(0) { this->_flags |= SHF_MIPS_GPREL; this->_align2 = 4; } /// \brief Number of local GOT entries. std::size_t getLocalCount() const { return this->_atoms.size() - _globalCount; } /// \brief Number of global GOT entries. std::size_t getGlobalCount() const { return _globalCount; } /// \brief Does the atom have a global GOT entry? bool hasGlobalGOTEntry(const Atom *a) const { return _posMap.count(a); } /// \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); 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(atom); const Atom *ta = nullptr; 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_GLOBAL_GOT) { ta = r->target(); break; } } if (ta) { _posMap[ta] = _posMap.size(); ++_globalCount; } return AtomSection::appendAtom(atom); } private: /// \brief Number of global GOT entries. std::size_t _globalCount; /// \brief Map Atoms to their GOT entry index. llvm::DenseMap _posMap; }; } // elf } // lld #endif