aboutsummaryrefslogtreecommitdiff
path: root/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h')
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h115
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