diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h')
-rw-r--r-- | lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h b/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h new file mode 100644 index 000000000000..2b9562f42b57 --- /dev/null +++ b/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h @@ -0,0 +1,115 @@ +//===- lib/ReaderWriter/ELF/Mips/MipsDynamicTable.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_DYNAMIC_TABLE_H +#define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H + +#include "DefaultLayout.h" +#include "SectionChunks.h" + +namespace lld { +namespace elf { + +template <class ELFType> class MipsTargetLayout; + +template <class MipsELFType> +class MipsDynamicTable : public DynamicTable<MipsELFType> { +public: + MipsDynamicTable(const ELFLinkingContext &ctx, + MipsTargetLayout<MipsELFType> &layout) + : DynamicTable<MipsELFType>(ctx, layout, ".dynamic", + DefaultLayout<MipsELFType>::ORDER_DYNAMIC), + _mipsTargetLayout(layout) {} + + void createDefaultEntries() override { + DynamicTable<MipsELFType>::createDefaultEntries(); + + typename DynamicTable<MipsELFType>::Elf_Dyn dyn; + + // Version id for the Runtime Linker Interface. + dyn.d_un.d_val = 1; + dyn.d_tag = DT_MIPS_RLD_VERSION; + this->addEntry(dyn); + + // MIPS flags. + dyn.d_un.d_val = RHF_NOTPOT; + dyn.d_tag = DT_MIPS_FLAGS; + this->addEntry(dyn); + + // The base address of the segment. + dyn.d_un.d_ptr = 0; + dyn.d_tag = DT_MIPS_BASE_ADDRESS; + _dt_baseaddr = this->addEntry(dyn); + + // Number of local global offset table entries. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_LOCAL_GOTNO; + _dt_localgot = this->addEntry(dyn); + + // Number of entries in the .dynsym section. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_SYMTABNO; + _dt_symtabno = this->addEntry(dyn); + + // The index of the first dynamic symbol table entry that corresponds + // to an entry in the global offset table. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_MIPS_GOTSYM; + _dt_gotsym = this->addEntry(dyn); + + // Address of the .got section. + dyn.d_un.d_val = 0; + dyn.d_tag = DT_PLTGOT; + _dt_pltgot = this->addEntry(dyn); + } + + void updateDynamicTable() override { + DynamicTable<MipsELFType>::updateDynamicTable(); + + // Assign the minimum segment address to the DT_MIPS_BASE_ADDRESS tag. + auto baseAddr = std::numeric_limits<uint64_t>::max(); + for (auto si : _mipsTargetLayout.segments()) + if (si->segmentType() != llvm::ELF::PT_NULL) + baseAddr = std::min(baseAddr, si->virtualAddr()); + this->_entries[_dt_baseaddr].d_un.d_val = baseAddr; + + auto &got = _mipsTargetLayout.getGOTSection(); + + this->_entries[_dt_symtabno].d_un.d_val = this->getSymbolTable()->size(); + this->_entries[_dt_gotsym].d_un.d_val = + this-> getSymbolTable()->size() - got.getGlobalCount(); + this->_entries[_dt_localgot].d_un.d_val = got.getLocalCount(); + this->_entries[_dt_pltgot].d_un.d_ptr = + _mipsTargetLayout.findOutputSection(".got")->virtualAddr(); + } + + int64_t getGotPltTag() override { return DT_MIPS_PLTGOT; } + +protected: + /// \brief Adjust the symbol's value for microMIPS code. + uint64_t getAtomVirtualAddress(const AtomLayout *al) const override { + if (const auto *da = dyn_cast<DefinedAtom>(al->_atom)) + if (da->codeModel() == DefinedAtom::codeMipsMicro || + da->codeModel() == DefinedAtom::codeMipsMicroPIC) + return al->_virtualAddr | 1; + return al->_virtualAddr; + } + +private: + std::size_t _dt_symtabno; + std::size_t _dt_localgot; + std::size_t _dt_gotsym; + std::size_t _dt_pltgot; + std::size_t _dt_baseaddr; + MipsTargetLayout<MipsELFType> &_mipsTargetLayout; +}; + +} // end namespace elf +} // end namespace lld + +#endif |