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
|
//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp ---------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MipsLinkingContext.h"
#include "MipsTargetLayout.h"
namespace lld {
namespace elf {
template <class ELFT>
MipsTargetLayout<ELFT>::MipsTargetLayout(MipsLinkingContext &ctx,
MipsAbiInfoHandler<ELFT> &abi)
: TargetLayout<ELFT>(ctx), _abiInfo(abi),
_gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
_pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
template <class ELFT>
AtomSection<ELFT> *MipsTargetLayout<ELFT>::createSection(
StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
typename TargetLayout<ELFT>::SectionOrder order) {
if (type == DefinedAtom::typeGOT && name == ".got")
return _gotSection;
if (type == DefinedAtom::typeStub && name == ".plt")
return _pltSection;
return TargetLayout<ELFT>::createSection(name, type, permissions, order);
}
template <class ELFT>
typename TargetLayout<ELFT>::SegmentType
MipsTargetLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
switch (section->order()) {
case ORDER_MIPS_REGINFO:
return _abiInfo.hasMipsAbiSection() ? llvm::ELF::PT_LOAD
: llvm::ELF::PT_MIPS_REGINFO;
case ORDER_MIPS_OPTIONS:
return llvm::ELF::PT_LOAD;
case ORDER_MIPS_ABI_FLAGS:
return llvm::ELF::PT_MIPS_ABIFLAGS;
default:
return TargetLayout<ELFT>::getSegmentType(section);
}
}
template <class ELFT> uint64_t MipsTargetLayout<ELFT>::getGPAddr() {
std::call_once(_gpOnce, [this]() {
if (AtomLayout *a = this->findAbsoluteAtom("_gp"))
_gpAddr = a->_virtualAddr;
});
return _gpAddr;
}
template <class ELFT>
typename TargetLayout<ELFT>::SectionOrder
MipsTargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions) {
if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
return TargetLayout<ELFT>::ORDER_TEXT;
return TargetLayout<ELFT>::getSectionOrder(name, contentType,
contentPermissions);
}
template <class ELFT>
unique_bump_ptr<RelocationTable<ELFT>>
MipsTargetLayout<ELFT>::createRelocationTable(StringRef name, int32_t order) {
return unique_bump_ptr<RelocationTable<ELFT>>(new (
this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order));
}
template <class ELFT>
uint64_t MipsTargetLayout<ELFT>::getLookupSectionFlags(
const OutputSection<ELFT> *os) const {
uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os);
return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP;
}
template <class ELFT> void MipsTargetLayout<ELFT>::sortSegments() {
using namespace llvm::ELF;
TargetLayout<ELFT>::sortSegments();
// Move PT_MIPS_ABIFLAGS or PT_MIPS_REGINFO right after PT_INTERP.
auto abiIt =
std::find_if(this->_segments.begin(), this->_segments.end(),
[](const Segment<ELFT> *s) {
auto typ = s->segmentType();
return typ == PT_MIPS_ABIFLAGS || typ == PT_MIPS_REGINFO;
});
if (abiIt == this->_segments.end())
return;
Segment<ELFT> *abiSeg = *abiIt;
this->_segments.erase(abiIt);
auto outIt = std::find_if(this->_segments.begin(), this->_segments.end(),
[](const Segment<ELFT> *s) {
auto typ = s->segmentType();
return typ != PT_PHDR && typ != PT_INTERP;
});
this->_segments.insert(outIt, abiSeg);
}
template class MipsTargetLayout<ELF32BE>;
template class MipsTargetLayout<ELF32LE>;
template class MipsTargetLayout<ELF64BE>;
template class MipsTargetLayout<ELF64LE>;
} // end namespace elf
} // end namespace lld
|