blob: db4f631d54cc3fe5a777091a7a54672f1603fd05 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
//===- 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 {
class MipsLinkingContext;
template <class ELFType> class MipsTargetLayout;
template <class MipsELFType>
class MipsDynamicTable : public DynamicTable<MipsELFType> {
public:
MipsDynamicTable(MipsLinkingContext &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
|