/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/ELF/InputSection.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- InputSection.cpp ---------------------------------------------------===// |
2 | | // |
3 | | // The LLVM Linker |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "InputSection.h" |
11 | | #include "Config.h" |
12 | | #include "EhFrame.h" |
13 | | #include "Error.h" |
14 | | #include "InputFiles.h" |
15 | | #include "LinkerScript.h" |
16 | | #include "Memory.h" |
17 | | #include "OutputSections.h" |
18 | | #include "Relocations.h" |
19 | | #include "SyntheticSections.h" |
20 | | #include "Target.h" |
21 | | #include "Thunks.h" |
22 | | #include "llvm/Object/Decompressor.h" |
23 | | #include "llvm/Support/Compiler.h" |
24 | | #include "llvm/Support/Compression.h" |
25 | | #include "llvm/Support/Endian.h" |
26 | | #include "llvm/Support/Path.h" |
27 | | #include "llvm/Support/Threading.h" |
28 | | #include <mutex> |
29 | | |
30 | | using namespace llvm; |
31 | | using namespace llvm::ELF; |
32 | | using namespace llvm::object; |
33 | | using namespace llvm::support; |
34 | | using namespace llvm::support::endian; |
35 | | using namespace llvm::sys; |
36 | | |
37 | | using namespace lld; |
38 | | using namespace lld::elf; |
39 | | |
40 | | std::vector<InputSectionBase *> elf::InputSections; |
41 | | |
42 | | // Returns a string to construct an error message. |
43 | 135k | std::string lld::toString(const InputSectionBase *Sec) { |
44 | 135k | return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); |
45 | 135k | } |
46 | | |
47 | 6 | DenseMap<SectionBase *, int> elf::buildSectionOrder() { |
48 | 6 | // Build a map from symbols to their priorities. Symbols that didn't |
49 | 6 | // appear in the symbol ordering file have the lowest priority 0. |
50 | 6 | // All explicitly mentioned symbols have negative (higher) priorities. |
51 | 6 | DenseMap<StringRef, int> SymbolOrder; |
52 | 6 | int Priority = -Config->SymbolOrderingFile.size(); |
53 | 6 | for (StringRef S : Config->SymbolOrderingFile) |
54 | 17 | SymbolOrder.insert({S, Priority++}); |
55 | 6 | |
56 | 6 | // Build a map from sections to their priorities. |
57 | 6 | DenseMap<SectionBase *, int> SectionOrder; |
58 | 8 | for (InputFile *File : ObjectFiles) { |
59 | 33 | for (SymbolBody *Body : File->getSymbols()) { |
60 | 33 | auto *D = dyn_cast<DefinedRegular>(Body); |
61 | 33 | if (!D || 33 !D->Section25 ) |
62 | 10 | continue; |
63 | 23 | int &Priority = SectionOrder[D->Section]; |
64 | 23 | Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); |
65 | 23 | } |
66 | 8 | } |
67 | 6 | return SectionOrder; |
68 | 6 | } |
69 | | |
70 | | template <class ELFT> |
71 | | static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> *File, |
72 | 201k | const typename ELFT::Shdr *Hdr) { |
73 | 201k | if (!File || 201k Hdr->sh_type == SHT_NOBITS200k ) |
74 | 1.84k | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); |
75 | 200k | return check(File->getObj().getSectionContents(Hdr)); |
76 | 200k | } InputSection.cpp:llvm::ArrayRef<unsigned char> getSectionContents<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Shdr const*) Line | Count | Source | 72 | 279 | const typename ELFT::Shdr *Hdr) { | 73 | 279 | if (!File || 279 Hdr->sh_type == SHT_NOBITS236 ) | 74 | 77 | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); | 75 | 202 | return check(File->getObj().getSectionContents(Hdr)); | 76 | 202 | } |
InputSection.cpp:llvm::ArrayRef<unsigned char> getSectionContents<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Shdr const*) Line | Count | Source | 72 | 729 | const typename ELFT::Shdr *Hdr) { | 73 | 729 | if (!File || 729 Hdr->sh_type == SHT_NOBITS542 ) | 74 | 228 | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); | 75 | 501 | return check(File->getObj().getSectionContents(Hdr)); | 76 | 501 | } |
InputSection.cpp:llvm::ArrayRef<unsigned char> getSectionContents<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Shdr const*) Line | Count | Source | 72 | 766 | const typename ELFT::Shdr *Hdr) { | 73 | 766 | if (!File || 766 Hdr->sh_type == SHT_NOBITS679 ) | 74 | 211 | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); | 75 | 555 | return check(File->getObj().getSectionContents(Hdr)); | 76 | 555 | } |
InputSection.cpp:llvm::ArrayRef<unsigned char> getSectionContents<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Shdr const*) Line | Count | Source | 72 | 200k | const typename ELFT::Shdr *Hdr) { | 73 | 200k | if (!File || 200k Hdr->sh_type == SHT_NOBITS198k ) | 74 | 1.32k | return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); | 75 | 198k | return check(File->getObj().getSectionContents(Hdr)); | 76 | 198k | } |
|
77 | | |
78 | | // Return true if a section with given section flags is live (will never be |
79 | | // GCed) by default. If a section can be GCed, this function returns false. |
80 | 232k | static bool isLiveByDefault(uint64_t Flags, uint32_t Type) { |
81 | 232k | // If GC is enabled, all memory-mapped sections are subject of GC. |
82 | 232k | if (!Config->GcSections) |
83 | 231k | return true; |
84 | 1.38k | if (1.38k Flags & SHF_ALLOC1.38k ) |
85 | 1.06k | return false; |
86 | 315 | |
87 | 315 | // Besides that, relocation sections can also be GCed because their |
88 | 315 | // relocation target sections may be GCed. This doesn't really matter |
89 | 315 | // in most cases because the linker usually consumes relocation |
90 | 315 | // sections instead of emitting them, but -emit-reloc needs this. |
91 | 315 | return Type != SHT_REL && 315 Type != SHT_RELA315 ; |
92 | 232k | } |
93 | | |
94 | | InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, |
95 | | uint32_t Type, uint64_t Entsize, |
96 | | uint32_t Link, uint32_t Info, |
97 | | uint32_t Alignment, ArrayRef<uint8_t> Data, |
98 | | StringRef Name, Kind SectionKind) |
99 | | : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, |
100 | | Link), |
101 | 232k | File(File), Data(Data), Repl(this) { |
102 | 232k | Live = isLiveByDefault(Flags, Type); |
103 | 232k | Assigned = false; |
104 | 232k | NumRelocations = 0; |
105 | 232k | AreRelocsRela = false; |
106 | 232k | |
107 | 232k | // The ELF spec states that a value of 0 means the section has |
108 | 232k | // no alignment constraits. |
109 | 232k | uint32_t V = std::max<uint64_t>(Alignment, 1); |
110 | 232k | if (!isPowerOf2_64(V)) |
111 | 0 | fatal(toString(File) + ": section sh_addralign is not a power of 2"); |
112 | 232k | this->Alignment = V; |
113 | 232k | } |
114 | | |
115 | | // Drop SHF_GROUP bit unless we are producing a re-linkable object file. |
116 | | // SHF_GROUP is a marker that a section belongs to some comdat group. |
117 | | // That flag doesn't make sense in an executable. |
118 | 201k | static uint64_t getFlags(uint64_t Flags) { |
119 | 201k | Flags &= ~(uint64_t)SHF_INFO_LINK; |
120 | 201k | if (!Config->Relocatable) |
121 | 201k | Flags &= ~(uint64_t)SHF_GROUP; |
122 | 201k | return Flags; |
123 | 201k | } |
124 | | |
125 | | // GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of |
126 | | // March 2017) fail to infer section types for sections starting with |
127 | | // ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of |
128 | | // SHF_INIT_ARRAY. As a result, the following assembler directive |
129 | | // creates ".init_array.100" with SHT_PROGBITS, for example. |
130 | | // |
131 | | // .section .init_array.100, "aw" |
132 | | // |
133 | | // This function forces SHT_{INIT,FINI}_ARRAY so that we can handle |
134 | | // incorrect inputs as if they were correct from the beginning. |
135 | 201k | static uint64_t getType(uint64_t Type, StringRef Name) { |
136 | 201k | if (Type == SHT_PROGBITS && 201k Name.startswith(".init_array.")201k ) |
137 | 1 | return SHT_INIT_ARRAY; |
138 | 201k | if (201k Type == SHT_PROGBITS && 201k Name.startswith(".fini_array.")201k ) |
139 | 1 | return SHT_FINI_ARRAY; |
140 | 201k | return Type; |
141 | 201k | } |
142 | | |
143 | | template <class ELFT> |
144 | | InputSectionBase::InputSectionBase(ObjFile<ELFT> *File, |
145 | | const typename ELFT::Shdr *Hdr, |
146 | | StringRef Name, Kind SectionKind) |
147 | | : InputSectionBase(File, getFlags(Hdr->sh_flags), |
148 | | getType(Hdr->sh_type, Name), Hdr->sh_entsize, |
149 | | Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, |
150 | 201k | getSectionContents(File, Hdr), Name, SectionKind) { |
151 | 201k | // We reject object files having insanely large alignments even though |
152 | 201k | // they are allowed by the spec. I think 4GB is a reasonable limitation. |
153 | 201k | // We might want to relax this in the future. |
154 | 201k | if (Hdr->sh_addralign > UINT32_MAX) |
155 | 0 | fatal(toString(File) + ": section sh_addralign is too large"); |
156 | 201k | } lld::elf::InputSectionBase::InputSectionBase<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Shdr const*, llvm::StringRef, lld::elf::SectionBase::Kind) Line | Count | Source | 150 | 729 | getSectionContents(File, Hdr), Name, SectionKind) { | 151 | 729 | // We reject object files having insanely large alignments even though | 152 | 729 | // they are allowed by the spec. I think 4GB is a reasonable limitation. | 153 | 729 | // We might want to relax this in the future. | 154 | 729 | if (Hdr->sh_addralign > UINT32_MAX) | 155 | 0 | fatal(toString(File) + ": section sh_addralign is too large"); | 156 | 729 | } |
lld::elf::InputSectionBase::InputSectionBase<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Shdr const*, llvm::StringRef, lld::elf::SectionBase::Kind) Line | Count | Source | 150 | 766 | getSectionContents(File, Hdr), Name, SectionKind) { | 151 | 766 | // We reject object files having insanely large alignments even though | 152 | 766 | // they are allowed by the spec. I think 4GB is a reasonable limitation. | 153 | 766 | // We might want to relax this in the future. | 154 | 766 | if (Hdr->sh_addralign > UINT32_MAX) | 155 | 0 | fatal(toString(File) + ": section sh_addralign is too large"); | 156 | 766 | } |
lld::elf::InputSectionBase::InputSectionBase<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Shdr const*, llvm::StringRef, lld::elf::SectionBase::Kind) Line | Count | Source | 150 | 200k | getSectionContents(File, Hdr), Name, SectionKind) { | 151 | 200k | // We reject object files having insanely large alignments even though | 152 | 200k | // they are allowed by the spec. I think 4GB is a reasonable limitation. | 153 | 200k | // We might want to relax this in the future. | 154 | 200k | if (Hdr->sh_addralign > UINT32_MAX) | 155 | 0 | fatal(toString(File) + ": section sh_addralign is too large"); | 156 | 200k | } |
lld::elf::InputSectionBase::InputSectionBase<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Shdr const*, llvm::StringRef, lld::elf::SectionBase::Kind) Line | Count | Source | 150 | 279 | getSectionContents(File, Hdr), Name, SectionKind) { | 151 | 279 | // We reject object files having insanely large alignments even though | 152 | 279 | // they are allowed by the spec. I think 4GB is a reasonable limitation. | 153 | 279 | // We might want to relax this in the future. | 154 | 279 | if (Hdr->sh_addralign > UINT32_MAX) | 155 | 0 | fatal(toString(File) + ": section sh_addralign is too large"); | 156 | 279 | } |
|
157 | | |
158 | 656k | size_t InputSectionBase::getSize() const { |
159 | 656k | if (auto *S = dyn_cast<SyntheticSection>(this)) |
160 | 53.5k | return S->getSize(); |
161 | 603k | |
162 | 603k | return Data.size(); |
163 | 603k | } |
164 | | |
165 | 196 | uint64_t InputSectionBase::getOffsetInFile() const { |
166 | 196 | const uint8_t *FileStart = (const uint8_t *)File->MB.getBufferStart(); |
167 | 196 | const uint8_t *SecStart = Data.begin(); |
168 | 196 | return SecStart - FileStart; |
169 | 196 | } |
170 | | |
171 | 10.1k | uint64_t SectionBase::getOffset(uint64_t Offset) const { |
172 | 10.1k | switch (kind()) { |
173 | 667 | case Output: { |
174 | 667 | auto *OS = cast<OutputSection>(this); |
175 | 667 | // For output sections we treat offset -1 as the end of the section. |
176 | 667 | return Offset == uint64_t(-1) ? OS->Size50 : Offset617 ; |
177 | 10.1k | } |
178 | 7.83k | case Regular: |
179 | 7.83k | return cast<InputSection>(this)->OutSecOff + Offset; |
180 | 1.48k | case Synthetic: { |
181 | 1.48k | auto *IS = cast<InputSection>(this); |
182 | 1.48k | // For synthetic sections we treat offset -1 as the end of the section. |
183 | 1.48k | return IS->OutSecOff + (Offset == uint64_t(-1) ? IS->getSize()24 : Offset1.46k ); |
184 | 10.1k | } |
185 | 119 | case EHFrame: |
186 | 119 | // The file crtbeginT.o has relocations pointing to the start of an empty |
187 | 119 | // .eh_frame that is known to be the first in the link. It does that to |
188 | 119 | // identify the start of the output .eh_frame. |
189 | 119 | return Offset; |
190 | 66 | case Merge: |
191 | 66 | const MergeInputSection *MS = cast<MergeInputSection>(this); |
192 | 66 | if (InputSection *IS = MS->getParent()) |
193 | 65 | return IS->OutSecOff + MS->getOffset(Offset); |
194 | 1 | return MS->getOffset(Offset); |
195 | 0 | } |
196 | 0 | llvm_unreachable0 ("invalid section kind"); |
197 | 0 | } |
198 | | |
199 | 15.5k | OutputSection *SectionBase::getOutputSection() { |
200 | 15.5k | InputSection *Sec; |
201 | 15.5k | if (auto *IS = dyn_cast<InputSection>(this)) |
202 | 14.3k | Sec = cast<InputSection>(IS->Repl); |
203 | 1.15k | else if (auto *1.15k MS1.15k = dyn_cast<MergeInputSection>(this)) |
204 | 87 | Sec = MS->getParent(); |
205 | 1.06k | else if (auto *1.06k EH1.06k = dyn_cast<EhInputSection>(this)) |
206 | 121 | Sec = EH->getParent(); |
207 | 1.06k | else |
208 | 944 | return cast<OutputSection>(this); |
209 | 14.5k | return Sec ? 14.5k Sec->getParent()14.5k : nullptr1 ; |
210 | 15.5k | } |
211 | | |
212 | | // Uncompress section contents. Note that this function is called |
213 | | // from parallelForEach, so it must be thread-safe. |
214 | 3 | void InputSectionBase::uncompress() { |
215 | 3 | Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data), |
216 | 3 | Config->IsLE, Config->Is64)); |
217 | 3 | |
218 | 3 | size_t Size = Dec.getDecompressedSize(); |
219 | 3 | UncompressBuf.reset(new char[Size]()); |
220 | 3 | if (Error E = Dec.decompress({UncompressBuf.get(), Size})) |
221 | 0 | fatal(toString(this) + |
222 | 0 | ": decompress failed: " + llvm::toString(std::move(E))); |
223 | 3 | |
224 | 3 | this->Data = makeArrayRef((uint8_t *)UncompressBuf.get(), Size); |
225 | 3 | this->Flags &= ~(uint64_t)SHF_COMPRESSED; |
226 | 3 | } |
227 | | |
228 | 0 | uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { |
229 | 0 | return getOffset(Sym.Value); |
230 | 0 | } |
231 | | |
232 | 112 | InputSection *InputSectionBase::getLinkOrderDep() const { |
233 | 112 | if ((Flags & SHF_LINK_ORDER) && 112 Link != 0112 ) { |
234 | 112 | InputSectionBase *L = File->getSections()[Link]; |
235 | 112 | if (auto *IS = dyn_cast<InputSection>(L)) |
236 | 111 | return IS; |
237 | 1 | error("a section with SHF_LINK_ORDER should not refer a non-regular " |
238 | 1 | "section: " + |
239 | 1 | toString(L)); |
240 | 1 | } |
241 | 1 | return nullptr; |
242 | 112 | } |
243 | | |
244 | | // Returns a source location string. Used to construct an error message. |
245 | | template <class ELFT> |
246 | 40 | std::string InputSectionBase::getLocation(uint64_t Offset) { |
247 | 40 | // We don't have file for synthetic sections. |
248 | 40 | if (getFile<ELFT>() == nullptr) |
249 | 1 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") |
250 | 1 | .str(); |
251 | 39 | |
252 | 39 | // First check if we can get desired values from debugging information. |
253 | 39 | std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); |
254 | 39 | if (!LineInfo.empty()) |
255 | 0 | return LineInfo; |
256 | 39 | |
257 | 39 | // File->SourceFile contains STT_FILE symbol that contains a |
258 | 39 | // source file name. If it's missing, we use an object file name. |
259 | 39 | std::string SrcFile = getFile<ELFT>()->SourceFile; |
260 | 39 | if (SrcFile.empty()) |
261 | 39 | SrcFile = toString(File); |
262 | 39 | |
263 | 39 | // Find a function symbol that encloses a given location. |
264 | 39 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) |
265 | 161 | if (auto *161 D161 = dyn_cast<DefinedRegular>(B)) |
266 | 121 | if (121 D->Section == this && 121 D->Type == STT_FUNC43 ) |
267 | 10 | if (10 D->Value <= Offset && 10 Offset < D->Value + D->Size9 ) |
268 | 0 | return SrcFile + ":(function " + toString(*D) + ")"; |
269 | 39 | |
270 | 39 | // If there's no symbol, print out the offset in the section. |
271 | 39 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); |
272 | 39 | } std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getLocation<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned long long) Line | Count | Source | 246 | 10 | std::string InputSectionBase::getLocation(uint64_t Offset) { | 247 | 10 | // We don't have file for synthetic sections. | 248 | 10 | if (getFile<ELFT>() == nullptr) | 249 | 0 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") | 250 | 0 | .str(); | 251 | 10 | | 252 | 10 | // First check if we can get desired values from debugging information. | 253 | 10 | std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); | 254 | 10 | if (!LineInfo.empty()) | 255 | 0 | return LineInfo; | 256 | 10 | | 257 | 10 | // File->SourceFile contains STT_FILE symbol that contains a | 258 | 10 | // source file name. If it's missing, we use an object file name. | 259 | 10 | std::string SrcFile = getFile<ELFT>()->SourceFile; | 260 | 10 | if (SrcFile.empty()) | 261 | 10 | SrcFile = toString(File); | 262 | 10 | | 263 | 10 | // Find a function symbol that encloses a given location. | 264 | 10 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 265 | 45 | if (auto *45 D45 = dyn_cast<DefinedRegular>(B)) | 266 | 35 | if (35 D->Section == this && 35 D->Type == STT_FUNC13 ) | 267 | 6 | if (6 D->Value <= Offset && 6 Offset < D->Value + D->Size5 ) | 268 | 0 | return SrcFile + ":(function " + toString(*D) + ")"; | 269 | 10 | | 270 | 10 | // If there's no symbol, print out the offset in the section. | 271 | 10 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | 272 | 10 | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getLocation<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned long long) Line | Count | Source | 246 | 1 | std::string InputSectionBase::getLocation(uint64_t Offset) { | 247 | 1 | // We don't have file for synthetic sections. | 248 | 1 | if (getFile<ELFT>() == nullptr) | 249 | 0 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") | 250 | 0 | .str(); | 251 | 1 | | 252 | 1 | // First check if we can get desired values from debugging information. | 253 | 1 | std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); | 254 | 1 | if (!LineInfo.empty()) | 255 | 0 | return LineInfo; | 256 | 1 | | 257 | 1 | // File->SourceFile contains STT_FILE symbol that contains a | 258 | 1 | // source file name. If it's missing, we use an object file name. | 259 | 1 | std::string SrcFile = getFile<ELFT>()->SourceFile; | 260 | 1 | if (SrcFile.empty()) | 261 | 1 | SrcFile = toString(File); | 262 | 1 | | 263 | 1 | // Find a function symbol that encloses a given location. | 264 | 1 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 265 | 3 | if (auto *3 D3 = dyn_cast<DefinedRegular>(B)) | 266 | 2 | if (2 D->Section == this && 2 D->Type == STT_FUNC1 ) | 267 | 0 | if (0 D->Value <= Offset && 0 Offset < D->Value + D->Size0 ) | 268 | 0 | return SrcFile + ":(function " + toString(*D) + ")"; | 269 | 1 | | 270 | 1 | // If there's no symbol, print out the offset in the section. | 271 | 1 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | 272 | 1 | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getLocation<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned long long) Line | Count | Source | 246 | 28 | std::string InputSectionBase::getLocation(uint64_t Offset) { | 247 | 28 | // We don't have file for synthetic sections. | 248 | 28 | if (getFile<ELFT>() == nullptr) | 249 | 1 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") | 250 | 1 | .str(); | 251 | 27 | | 252 | 27 | // First check if we can get desired values from debugging information. | 253 | 27 | std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); | 254 | 27 | if (!LineInfo.empty()) | 255 | 0 | return LineInfo; | 256 | 27 | | 257 | 27 | // File->SourceFile contains STT_FILE symbol that contains a | 258 | 27 | // source file name. If it's missing, we use an object file name. | 259 | 27 | std::string SrcFile = getFile<ELFT>()->SourceFile; | 260 | 27 | if (SrcFile.empty()) | 261 | 27 | SrcFile = toString(File); | 262 | 27 | | 263 | 27 | // Find a function symbol that encloses a given location. | 264 | 27 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 265 | 111 | if (auto *111 D111 = dyn_cast<DefinedRegular>(B)) | 266 | 83 | if (83 D->Section == this && 83 D->Type == STT_FUNC29 ) | 267 | 4 | if (4 D->Value <= Offset && 4 Offset < D->Value + D->Size4 ) | 268 | 0 | return SrcFile + ":(function " + toString(*D) + ")"; | 269 | 27 | | 270 | 27 | // If there's no symbol, print out the offset in the section. | 271 | 27 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | 272 | 27 | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getLocation<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned long long) Line | Count | Source | 246 | 1 | std::string InputSectionBase::getLocation(uint64_t Offset) { | 247 | 1 | // We don't have file for synthetic sections. | 248 | 1 | if (getFile<ELFT>() == nullptr) | 249 | 0 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") | 250 | 0 | .str(); | 251 | 1 | | 252 | 1 | // First check if we can get desired values from debugging information. | 253 | 1 | std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); | 254 | 1 | if (!LineInfo.empty()) | 255 | 0 | return LineInfo; | 256 | 1 | | 257 | 1 | // File->SourceFile contains STT_FILE symbol that contains a | 258 | 1 | // source file name. If it's missing, we use an object file name. | 259 | 1 | std::string SrcFile = getFile<ELFT>()->SourceFile; | 260 | 1 | if (SrcFile.empty()) | 261 | 1 | SrcFile = toString(File); | 262 | 1 | | 263 | 1 | // Find a function symbol that encloses a given location. | 264 | 1 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 265 | 2 | if (auto *2 D2 = dyn_cast<DefinedRegular>(B)) | 266 | 1 | if (1 D->Section == this && 1 D->Type == STT_FUNC0 ) | 267 | 0 | if (0 D->Value <= Offset && 0 Offset < D->Value + D->Size0 ) | 268 | 0 | return SrcFile + ":(function " + toString(*D) + ")"; | 269 | 1 | | 270 | 1 | // If there's no symbol, print out the offset in the section. | 271 | 1 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | 272 | 1 | } |
|
273 | | |
274 | | // Returns a source location string. This function is intended to be |
275 | | // used for constructing an error message. The returned message looks |
276 | | // like this: |
277 | | // |
278 | | // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) |
279 | | // |
280 | | // Returns an empty string if there's no way to get line info. |
281 | 130 | template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { |
282 | 130 | // Synthetic sections don't have input files. |
283 | 130 | ObjFile<ELFT> *File = getFile<ELFT>(); |
284 | 130 | if (!File) |
285 | 2 | return ""; |
286 | 128 | |
287 | 128 | Optional<DILineInfo> Info = File->getDILineInfo(this, Offset); |
288 | 128 | |
289 | 128 | // File->SourceFile contains STT_FILE symbol, and that is a last resort. |
290 | 128 | if (!Info) |
291 | 117 | return File->SourceFile; |
292 | 11 | |
293 | 11 | std::string Path = Info->FileName; |
294 | 11 | std::string Filename = path::filename(Path); |
295 | 11 | std::string Lineno = ":" + std::to_string(Info->Line); |
296 | 11 | if (Filename == Path) |
297 | 2 | return Filename + Lineno; |
298 | 9 | return Filename + Lineno + " (" + Path + Lineno + ")"; |
299 | 9 | } std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getSrcMsg<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned long long) Line | Count | Source | 281 | 5 | template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { | 282 | 5 | // Synthetic sections don't have input files. | 283 | 5 | ObjFile<ELFT> *File = getFile<ELFT>(); | 284 | 5 | if (!File) | 285 | 0 | return ""; | 286 | 5 | | 287 | 5 | Optional<DILineInfo> Info = File->getDILineInfo(this, Offset); | 288 | 5 | | 289 | 5 | // File->SourceFile contains STT_FILE symbol, and that is a last resort. | 290 | 5 | if (!Info) | 291 | 5 | return File->SourceFile; | 292 | 0 |
| 293 | 0 | std::string Path = Info->FileName; | 294 | 0 | std::string Filename = path::filename(Path); | 295 | 0 | std::string Lineno = ":" + std::to_string(Info->Line); | 296 | 0 | if (Filename == Path) | 297 | 0 | return Filename + Lineno; | 298 | 0 | return Filename + Lineno + " (" + Path + Lineno + ")"; | 299 | 0 | } |
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getSrcMsg<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned long long) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getSrcMsg<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned long long) std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getSrcMsg<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned long long) Line | Count | Source | 281 | 125 | template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { | 282 | 125 | // Synthetic sections don't have input files. | 283 | 125 | ObjFile<ELFT> *File = getFile<ELFT>(); | 284 | 125 | if (!File) | 285 | 2 | return ""; | 286 | 123 | | 287 | 123 | Optional<DILineInfo> Info = File->getDILineInfo(this, Offset); | 288 | 123 | | 289 | 123 | // File->SourceFile contains STT_FILE symbol, and that is a last resort. | 290 | 123 | if (!Info) | 291 | 112 | return File->SourceFile; | 292 | 11 | | 293 | 11 | std::string Path = Info->FileName; | 294 | 11 | std::string Filename = path::filename(Path); | 295 | 11 | std::string Lineno = ":" + std::to_string(Info->Line); | 296 | 11 | if (Filename == Path) | 297 | 2 | return Filename + Lineno; | 298 | 9 | return Filename + Lineno + " (" + Path + Lineno + ")"; | 299 | 9 | } |
|
300 | | |
301 | | // Returns a filename string along with an optional section name. This |
302 | | // function is intended to be used for constructing an error |
303 | | // message. The returned message looks like this: |
304 | | // |
305 | | // path/to/foo.o:(function bar) |
306 | | // |
307 | | // or |
308 | | // |
309 | | // path/to/foo.o:(function bar) in archive path/to/bar.a |
310 | 130 | template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { |
311 | 130 | // Synthetic sections don't have input files. |
312 | 130 | ObjFile<ELFT> *File = getFile<ELFT>(); |
313 | 130 | if (!File) |
314 | 2 | return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str(); |
315 | 128 | std::string Filename = File->getName(); |
316 | 128 | |
317 | 128 | std::string Archive; |
318 | 128 | if (!File->ArchiveName.empty()) |
319 | 6 | Archive = (" in archive " + File->ArchiveName).str(); |
320 | 128 | |
321 | 128 | // Find a symbol that encloses a given location. |
322 | 128 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) |
323 | 468 | if (auto *468 D468 = dyn_cast<DefinedRegular>(B)) |
324 | 199 | if (199 D->Section == this && 199 D->Value <= Off128 && Off < D->Value + D->Size119 ) |
325 | 7 | return Filename + ":(" + toString(*D) + ")" + Archive; |
326 | 121 | |
327 | 121 | // If there's no symbol, print out the offset in the section. |
328 | 121 | return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive) |
329 | 121 | .str(); |
330 | 121 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getObjMsg<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned long long) Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getObjMsg<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned long long) std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getObjMsg<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned long long) Line | Count | Source | 310 | 125 | template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { | 311 | 125 | // Synthetic sections don't have input files. | 312 | 125 | ObjFile<ELFT> *File = getFile<ELFT>(); | 313 | 125 | if (!File) | 314 | 2 | return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str(); | 315 | 123 | std::string Filename = File->getName(); | 316 | 123 | | 317 | 123 | std::string Archive; | 318 | 123 | if (!File->ArchiveName.empty()) | 319 | 6 | Archive = (" in archive " + File->ArchiveName).str(); | 320 | 123 | | 321 | 123 | // Find a symbol that encloses a given location. | 322 | 123 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 323 | 443 | if (auto *443 D443 = dyn_cast<DefinedRegular>(B)) | 324 | 179 | if (179 D->Section == this && 179 D->Value <= Off114 && Off < D->Value + D->Size109 ) | 325 | 7 | return Filename + ":(" + toString(*D) + ")" + Archive; | 326 | 116 | | 327 | 116 | // If there's no symbol, print out the offset in the section. | 328 | 116 | return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive) | 329 | 116 | .str(); | 330 | 116 | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > lld::elf::InputSectionBase::getObjMsg<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned long long) Line | Count | Source | 310 | 5 | template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { | 311 | 5 | // Synthetic sections don't have input files. | 312 | 5 | ObjFile<ELFT> *File = getFile<ELFT>(); | 313 | 5 | if (!File) | 314 | 0 | return ("(internal):(" + Name + "+0x" + utohexstr(Off) + ")").str(); | 315 | 5 | std::string Filename = File->getName(); | 316 | 5 | | 317 | 5 | std::string Archive; | 318 | 5 | if (!File->ArchiveName.empty()) | 319 | 0 | Archive = (" in archive " + File->ArchiveName).str(); | 320 | 5 | | 321 | 5 | // Find a symbol that encloses a given location. | 322 | 5 | for (SymbolBody *B : getFile<ELFT>()->getSymbols()) | 323 | 25 | if (auto *25 D25 = dyn_cast<DefinedRegular>(B)) | 324 | 20 | if (20 D->Section == this && 20 D->Value <= Off14 && Off < D->Value + D->Size10 ) | 325 | 0 | return Filename + ":(" + toString(*D) + ")" + Archive; | 326 | 5 | | 327 | 5 | // If there's no symbol, print out the offset in the section. | 328 | 5 | return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive) | 329 | 5 | .str(); | 330 | 5 | } |
|
331 | | |
332 | | InputSectionBase InputSectionBase::Discarded; |
333 | | |
334 | | InputSection::InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, |
335 | | ArrayRef<uint8_t> Data, StringRef Name, Kind K) |
336 | | : InputSectionBase(nullptr, Flags, Type, |
337 | | /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data, |
338 | 30.8k | Name, K) {} |
339 | | |
340 | | template <class ELFT> |
341 | | InputSection::InputSection(ObjFile<ELFT> *F, const typename ELFT::Shdr *Header, |
342 | | StringRef Name) |
343 | 200k | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} lld::elf::InputSection::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 343 | 535 | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} |
lld::elf::InputSection::InputSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 343 | 677 | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} |
lld::elf::InputSection::InputSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 343 | 198k | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} |
lld::elf::InputSection::InputSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 343 | 233 | : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} |
|
344 | | |
345 | 243k | bool InputSection::classof(const SectionBase *S) { |
346 | 243k | return S->kind() == SectionBase::Regular || |
347 | 31.3k | S->kind() == SectionBase::Synthetic; |
348 | 243k | } |
349 | | |
350 | 12.0k | bool InputSectionBase::classof(const SectionBase *S) { |
351 | 12.0k | return S->kind() != Output; |
352 | 12.0k | } |
353 | | |
354 | 105k | OutputSection *InputSection::getParent() const { |
355 | 105k | return cast_or_null<OutputSection>(Parent); |
356 | 105k | } |
357 | | |
358 | | // Copy SHT_GROUP section contents. Used only for the -r option. |
359 | 8 | template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) { |
360 | 8 | // ELFT::Word is the 32-bit integral type in the target endianness. |
361 | 8 | typedef typename ELFT::Word u32; |
362 | 8 | ArrayRef<u32> From = getDataAs<u32>(); |
363 | 8 | auto *To = reinterpret_cast<u32 *>(Buf); |
364 | 8 | |
365 | 8 | // The first entry is not a section number but a flag. |
366 | 8 | *To++ = From[0]; |
367 | 8 | |
368 | 8 | // Adjust section numbers because section numbers in an input object |
369 | 8 | // files are different in the output. |
370 | 8 | ArrayRef<InputSectionBase *> Sections = this->File->getSections(); |
371 | 8 | for (uint32_t Idx : From.slice(1)) |
372 | 11 | *To++ = Sections[Idx]->getOutputSection()->SectionIndex; |
373 | 8 | } Unexecuted instantiation: void lld::elf::InputSection::copyShtGroup<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*) Unexecuted instantiation: void lld::elf::InputSection::copyShtGroup<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*) void lld::elf::InputSection::copyShtGroup<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*) Line | Count | Source | 359 | 8 | template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) { | 360 | 8 | // ELFT::Word is the 32-bit integral type in the target endianness. | 361 | 8 | typedef typename ELFT::Word u32; | 362 | 8 | ArrayRef<u32> From = getDataAs<u32>(); | 363 | 8 | auto *To = reinterpret_cast<u32 *>(Buf); | 364 | 8 | | 365 | 8 | // The first entry is not a section number but a flag. | 366 | 8 | *To++ = From[0]; | 367 | 8 | | 368 | 8 | // Adjust section numbers because section numbers in an input object | 369 | 8 | // files are different in the output. | 370 | 8 | ArrayRef<InputSectionBase *> Sections = this->File->getSections(); | 371 | 8 | for (uint32_t Idx : From.slice(1)) | 372 | 11 | *To++ = Sections[Idx]->getOutputSection()->SectionIndex; | 373 | 8 | } |
Unexecuted instantiation: void lld::elf::InputSection::copyShtGroup<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*) |
374 | | |
375 | 181 | InputSectionBase *InputSection::getRelocatedSection() { |
376 | 181 | assert(this->Type == SHT_RELA || this->Type == SHT_REL); |
377 | 181 | ArrayRef<InputSectionBase *> Sections = this->File->getSections(); |
378 | 181 | return Sections[this->Info]; |
379 | 181 | } |
380 | | |
381 | | // This is used for -r and --emit-relocs. We can't use memcpy to copy |
382 | | // relocations because we need to update symbol table offset and section index |
383 | | // for each relocation. So we copy relocations one by one. |
384 | | template <class ELFT, class RelTy> |
385 | 65 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
386 | 65 | InputSectionBase *RelocatedSection = getRelocatedSection(); |
387 | 100 | for (const RelTy &Rel : Rels) { |
388 | 100 | uint32_t Type = Rel.getType(Config->IsMips64EL); |
389 | 100 | SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); |
390 | 100 | |
391 | 100 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); |
392 | 100 | Buf += sizeof(RelTy); |
393 | 100 | |
394 | 100 | if (Config->IsRela) |
395 | 76 | P->r_addend = getAddend<ELFT>(Rel); |
396 | 100 | |
397 | 100 | // Output section VA is zero for -r, so r_offset is an offset within the |
398 | 100 | // section, but for --emit-relocs it is an virtual address. |
399 | 100 | P->r_offset = RelocatedSection->getOutputSection()->Addr + |
400 | 100 | RelocatedSection->getOffset(Rel.r_offset); |
401 | 100 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, |
402 | 100 | Config->IsMips64EL); |
403 | 100 | |
404 | 100 | if (Body.Type == STT_SECTION100 ) { |
405 | 47 | // We combine multiple section symbols into only one per |
406 | 47 | // section. This means we have to update the addend. That is |
407 | 47 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the |
408 | 47 | // section data. We do that by adding to the Relocation vector. |
409 | 47 | |
410 | 47 | // .eh_frame is horribly special and can reference discarded sections. To |
411 | 47 | // avoid having to parse and recreate .eh_frame, we just replace any |
412 | 47 | // relocation in it pointing to discarded sections with R_*_NONE, which |
413 | 47 | // hopefully creates a frame that is ignored at runtime. |
414 | 47 | SectionBase *Section = cast<DefinedRegular>(Body).Section; |
415 | 47 | if (Section == &InputSection::Discarded47 ) { |
416 | 2 | P->setSymbolAndType(0, 0, false); |
417 | 2 | continue; |
418 | 2 | } |
419 | 45 | |
420 | 45 | if (45 Config->IsRela45 ) { |
421 | 25 | P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; |
422 | 45 | } else if (20 Config->Relocatable20 ) { |
423 | 20 | const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; |
424 | 20 | RelocatedSection->Relocations.push_back( |
425 | 20 | {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), |
426 | 20 | &Body}); |
427 | 20 | } |
428 | 47 | } |
429 | 100 | |
430 | 100 | } |
431 | 65 | } Unexecuted instantiation: void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 385 | 12 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 386 | 12 | InputSectionBase *RelocatedSection = getRelocatedSection(); | 387 | 15 | for (const RelTy &Rel : Rels) { | 388 | 15 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 389 | 15 | SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 390 | 15 | | 391 | 15 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); | 392 | 15 | Buf += sizeof(RelTy); | 393 | 15 | | 394 | 15 | if (Config->IsRela) | 395 | 0 | P->r_addend = getAddend<ELFT>(Rel); | 396 | 15 | | 397 | 15 | // Output section VA is zero for -r, so r_offset is an offset within the | 398 | 15 | // section, but for --emit-relocs it is an virtual address. | 399 | 15 | P->r_offset = RelocatedSection->getOutputSection()->Addr + | 400 | 15 | RelocatedSection->getOffset(Rel.r_offset); | 401 | 15 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, | 402 | 15 | Config->IsMips64EL); | 403 | 15 | | 404 | 15 | if (Body.Type == STT_SECTION15 ) { | 405 | 13 | // We combine multiple section symbols into only one per | 406 | 13 | // section. This means we have to update the addend. That is | 407 | 13 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the | 408 | 13 | // section data. We do that by adding to the Relocation vector. | 409 | 13 | | 410 | 13 | // .eh_frame is horribly special and can reference discarded sections. To | 411 | 13 | // avoid having to parse and recreate .eh_frame, we just replace any | 412 | 13 | // relocation in it pointing to discarded sections with R_*_NONE, which | 413 | 13 | // hopefully creates a frame that is ignored at runtime. | 414 | 13 | SectionBase *Section = cast<DefinedRegular>(Body).Section; | 415 | 13 | if (Section == &InputSection::Discarded13 ) { | 416 | 0 | P->setSymbolAndType(0, 0, false); | 417 | 0 | continue; | 418 | 0 | } | 419 | 13 | | 420 | 13 | if (13 Config->IsRela13 ) { | 421 | 0 | P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; | 422 | 13 | } else if (13 Config->Relocatable13 ) { | 423 | 13 | const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; | 424 | 13 | RelocatedSection->Relocations.push_back( | 425 | 13 | {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), | 426 | 13 | &Body}); | 427 | 13 | } | 428 | 13 | } | 429 | 15 | | 430 | 15 | } | 431 | 12 | } |
Unexecuted instantiation: void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) Line | Count | Source | 385 | 6 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 386 | 6 | InputSectionBase *RelocatedSection = getRelocatedSection(); | 387 | 9 | for (const RelTy &Rel : Rels) { | 388 | 9 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 389 | 9 | SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 390 | 9 | | 391 | 9 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); | 392 | 9 | Buf += sizeof(RelTy); | 393 | 9 | | 394 | 9 | if (Config->IsRela) | 395 | 0 | P->r_addend = getAddend<ELFT>(Rel); | 396 | 9 | | 397 | 9 | // Output section VA is zero for -r, so r_offset is an offset within the | 398 | 9 | // section, but for --emit-relocs it is an virtual address. | 399 | 9 | P->r_offset = RelocatedSection->getOutputSection()->Addr + | 400 | 9 | RelocatedSection->getOffset(Rel.r_offset); | 401 | 9 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, | 402 | 9 | Config->IsMips64EL); | 403 | 9 | | 404 | 9 | if (Body.Type == STT_SECTION9 ) { | 405 | 7 | // We combine multiple section symbols into only one per | 406 | 7 | // section. This means we have to update the addend. That is | 407 | 7 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the | 408 | 7 | // section data. We do that by adding to the Relocation vector. | 409 | 7 | | 410 | 7 | // .eh_frame is horribly special and can reference discarded sections. To | 411 | 7 | // avoid having to parse and recreate .eh_frame, we just replace any | 412 | 7 | // relocation in it pointing to discarded sections with R_*_NONE, which | 413 | 7 | // hopefully creates a frame that is ignored at runtime. | 414 | 7 | SectionBase *Section = cast<DefinedRegular>(Body).Section; | 415 | 7 | if (Section == &InputSection::Discarded7 ) { | 416 | 0 | P->setSymbolAndType(0, 0, false); | 417 | 0 | continue; | 418 | 0 | } | 419 | 7 | | 420 | 7 | if (7 Config->IsRela7 ) { | 421 | 0 | P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; | 422 | 7 | } else if (7 Config->Relocatable7 ) { | 423 | 7 | const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; | 424 | 7 | RelocatedSection->Relocations.push_back( | 425 | 7 | {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), | 426 | 7 | &Body}); | 427 | 7 | } | 428 | 7 | } | 429 | 9 | | 430 | 9 | } | 431 | 6 | } |
Unexecuted instantiation: void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) Unexecuted instantiation: void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) Unexecuted instantiation: void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) void lld::elf::InputSection::copyRelocations<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 385 | 47 | void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 386 | 47 | InputSectionBase *RelocatedSection = getRelocatedSection(); | 387 | 76 | for (const RelTy &Rel : Rels) { | 388 | 76 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 389 | 76 | SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 390 | 76 | | 391 | 76 | auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); | 392 | 76 | Buf += sizeof(RelTy); | 393 | 76 | | 394 | 76 | if (Config->IsRela) | 395 | 76 | P->r_addend = getAddend<ELFT>(Rel); | 396 | 76 | | 397 | 76 | // Output section VA is zero for -r, so r_offset is an offset within the | 398 | 76 | // section, but for --emit-relocs it is an virtual address. | 399 | 76 | P->r_offset = RelocatedSection->getOutputSection()->Addr + | 400 | 76 | RelocatedSection->getOffset(Rel.r_offset); | 401 | 76 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Body), Type, | 402 | 76 | Config->IsMips64EL); | 403 | 76 | | 404 | 76 | if (Body.Type == STT_SECTION76 ) { | 405 | 27 | // We combine multiple section symbols into only one per | 406 | 27 | // section. This means we have to update the addend. That is | 407 | 27 | // trivial for Elf_Rela, but for Elf_Rel we have to write to the | 408 | 27 | // section data. We do that by adding to the Relocation vector. | 409 | 27 | | 410 | 27 | // .eh_frame is horribly special and can reference discarded sections. To | 411 | 27 | // avoid having to parse and recreate .eh_frame, we just replace any | 412 | 27 | // relocation in it pointing to discarded sections with R_*_NONE, which | 413 | 27 | // hopefully creates a frame that is ignored at runtime. | 414 | 27 | SectionBase *Section = cast<DefinedRegular>(Body).Section; | 415 | 27 | if (Section == &InputSection::Discarded27 ) { | 416 | 2 | P->setSymbolAndType(0, 0, false); | 417 | 2 | continue; | 418 | 2 | } | 419 | 25 | | 420 | 25 | if (25 Config->IsRela25 ) { | 421 | 25 | P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; | 422 | 25 | } else if (0 Config->Relocatable0 ) { | 423 | 0 | const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; | 424 | 0 | RelocatedSection->Relocations.push_back( | 425 | 0 | {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), | 426 | 0 | &Body}); | 427 | 0 | } | 428 | 27 | } | 429 | 76 | | 430 | 76 | } | 431 | 47 | } |
|
432 | | |
433 | | // The ARM and AArch64 ABI handle pc-relative relocations to undefined weak |
434 | | // references specially. The general rule is that the value of the symbol in |
435 | | // this context is the address of the place P. A further special case is that |
436 | | // branch relocations to an undefined weak reference resolve to the next |
437 | | // instruction. |
438 | | static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, |
439 | 15 | uint32_t P) { |
440 | 15 | switch (Type) { |
441 | 15 | // Unresolved branch relocations to weak references resolve to next |
442 | 15 | // instruction, this will be either 2 or 4 bytes on from P. |
443 | 0 | case R_ARM_THM_JUMP11: |
444 | 0 | return P + 2 + A; |
445 | 7 | case R_ARM_CALL: |
446 | 7 | case R_ARM_JUMP24: |
447 | 7 | case R_ARM_PC24: |
448 | 7 | case R_ARM_PLT32: |
449 | 7 | case R_ARM_PREL31: |
450 | 7 | case R_ARM_THM_JUMP19: |
451 | 7 | case R_ARM_THM_JUMP24: |
452 | 7 | return P + 4 + A; |
453 | 3 | case R_ARM_THM_CALL: |
454 | 3 | // We don't want an interworking BLX to ARM |
455 | 3 | return P + 5 + A; |
456 | 7 | // Unresolved non branch pc-relative relocations |
457 | 7 | // R_ARM_TARGET2 which can be resolved relatively is not present as it never |
458 | 7 | // targets a weak-reference. |
459 | 5 | case R_ARM_MOVW_PREL_NC: |
460 | 5 | case R_ARM_MOVT_PREL: |
461 | 5 | case R_ARM_REL32: |
462 | 5 | case R_ARM_THM_MOVW_PREL_NC: |
463 | 5 | case R_ARM_THM_MOVT_PREL: |
464 | 5 | return P + A; |
465 | 0 | } |
466 | 0 | llvm_unreachable0 ("ARM pc-relative relocation expected\n"); |
467 | 0 | } |
468 | | |
469 | | // The comment above getARMUndefinedRelativeWeakVA applies to this function. |
470 | | static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, |
471 | 9 | uint64_t P) { |
472 | 9 | switch (Type) { |
473 | 9 | // Unresolved branch relocations to weak references resolve to next |
474 | 9 | // instruction, this is 4 bytes on from P. |
475 | 4 | case R_AARCH64_CALL26: |
476 | 4 | case R_AARCH64_CONDBR19: |
477 | 4 | case R_AARCH64_JUMP26: |
478 | 4 | case R_AARCH64_TSTBR14: |
479 | 4 | return P + 4 + A; |
480 | 4 | // Unresolved non branch pc-relative relocations |
481 | 5 | case R_AARCH64_PREL16: |
482 | 5 | case R_AARCH64_PREL32: |
483 | 5 | case R_AARCH64_PREL64: |
484 | 5 | case R_AARCH64_ADR_PREL_LO21: |
485 | 5 | case R_AARCH64_LD_PREL_LO19: |
486 | 5 | return P + A; |
487 | 0 | } |
488 | 0 | llvm_unreachable0 ("AArch64 pc-relative relocation expected\n"); |
489 | 0 | } |
490 | | |
491 | | // ARM SBREL relocations are of the form S + A - B where B is the static base |
492 | | // The ARM ABI defines base to be "addressing origin of the output segment |
493 | | // defining the symbol S". We defined the "addressing origin"/static base to be |
494 | | // the base of the PT_LOAD segment containing the Body. |
495 | | // The procedure call standard only defines a Read Write Position Independent |
496 | | // RWPI variant so in practice we should expect the static base to be the base |
497 | | // of the RW segment. |
498 | 4 | static uint64_t getARMStaticBase(const SymbolBody &Body) { |
499 | 4 | OutputSection *OS = Body.getOutputSection(); |
500 | 4 | if (!OS || 4 !OS->PtLoad4 || !OS->PtLoad->FirstSec4 ) |
501 | 0 | fatal("SBREL relocation to " + Body.getName() + " without static base"); |
502 | 4 | return OS->PtLoad->FirstSec->Addr; |
503 | 4 | } |
504 | | |
505 | | static uint64_t getRelocTargetVA(uint32_t Type, int64_t A, uint64_t P, |
506 | 1.86k | const SymbolBody &Body, RelExpr Expr) { |
507 | 1.86k | switch (Expr) { |
508 | 524 | case R_ABS: |
509 | 524 | case R_RELAX_GOT_PC_NOPIC: |
510 | 524 | return Body.getVA(A); |
511 | 4 | case R_ARM_SBREL: |
512 | 4 | return Body.getVA(A) - getARMStaticBase(Body); |
513 | 24 | case R_GOT: |
514 | 24 | case R_RELAX_TLS_GD_TO_IE_ABS: |
515 | 24 | return Body.getGotVA() + A; |
516 | 0 | case R_GOTONLY_PC: |
517 | 0 | return InX::Got->getVA() + A - P; |
518 | 6 | case R_GOTONLY_PC_FROM_END: |
519 | 6 | return InX::Got->getVA() + A - P + InX::Got->getSize(); |
520 | 7 | case R_GOTREL: |
521 | 7 | return Body.getVA(A) - InX::Got->getVA(); |
522 | 4 | case R_GOTREL_FROM_END: |
523 | 4 | return Body.getVA(A) - InX::Got->getVA() - InX::Got->getSize(); |
524 | 25 | case R_GOT_FROM_END: |
525 | 25 | case R_RELAX_TLS_GD_TO_IE_END: |
526 | 25 | return Body.getGotOffset() + A - InX::Got->getSize(); |
527 | 5 | case R_GOT_OFF: |
528 | 5 | return Body.getGotOffset() + A; |
529 | 8 | case R_GOT_PAGE_PC: |
530 | 8 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: |
531 | 8 | return getAArch64Page(Body.getGotVA() + A) - getAArch64Page(P); |
532 | 97 | case R_GOT_PC: |
533 | 97 | case R_RELAX_TLS_GD_TO_IE: |
534 | 97 | return Body.getGotVA() + A - P; |
535 | 0 | case R_HINT: |
536 | 0 | case R_NONE: |
537 | 0 | case R_TLSDESC_CALL: |
538 | 0 | llvm_unreachable("cannot relocate hint relocs"); |
539 | 19 | case R_MIPS_GOTREL: |
540 | 19 | return Body.getVA(A) - InX::MipsGot->getGp(); |
541 | 2 | case R_MIPS_GOT_GP: |
542 | 2 | return InX::MipsGot->getGp() + A; |
543 | 20 | case R_MIPS_GOT_GP_PC: { |
544 | 20 | // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target |
545 | 20 | // is _gp_disp symbol. In that case we should use the following |
546 | 20 | // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at |
547 | 20 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
548 | 20 | uint64_t V = InX::MipsGot->getGp() + A - P; |
549 | 20 | if (Type == R_MIPS_LO16 || 20 Type == R_MICROMIPS_LO1612 ) |
550 | 10 | V += 4; |
551 | 20 | return V; |
552 | 0 | } |
553 | 18 | case R_MIPS_GOT_LOCAL_PAGE: |
554 | 18 | // If relocation against MIPS local symbol requires GOT entry, this entry |
555 | 18 | // should be initialized by 'page address'. This address is high 16-bits |
556 | 18 | // of sum the symbol's value and the addend. |
557 | 18 | return InX::MipsGot->getVA() + InX::MipsGot->getPageEntryOffset(Body, A) - |
558 | 18 | InX::MipsGot->getGp(); |
559 | 74 | case R_MIPS_GOT_OFF: |
560 | 74 | case R_MIPS_GOT_OFF32: |
561 | 74 | // In case of MIPS if a GOT relocation has non-zero addend this addend |
562 | 74 | // should be applied to the GOT entry content not to the GOT entry offset. |
563 | 74 | // That is why we use separate expression type. |
564 | 74 | return InX::MipsGot->getVA() + InX::MipsGot->getBodyEntryOffset(Body, A) - |
565 | 74 | InX::MipsGot->getGp(); |
566 | 9 | case R_MIPS_TLSGD: |
567 | 9 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + |
568 | 9 | InX::MipsGot->getGlobalDynOffset(Body) - InX::MipsGot->getGp(); |
569 | 5 | case R_MIPS_TLSLD: |
570 | 5 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsOffset() + |
571 | 5 | InX::MipsGot->getTlsIndexOff() - InX::MipsGot->getGp(); |
572 | 6 | case R_PAGE_PC: |
573 | 6 | case R_PLT_PAGE_PC: { |
574 | 6 | uint64_t Dest; |
575 | 6 | if (Body.isUndefWeak()) |
576 | 1 | Dest = getAArch64Page(A); |
577 | 6 | else |
578 | 5 | Dest = getAArch64Page(Body.getVA(A)); |
579 | 6 | return Dest - getAArch64Page(P); |
580 | 6 | } |
581 | 585 | case R_PC: { |
582 | 585 | uint64_t Dest; |
583 | 585 | if (Body.isUndefWeak()585 ) { |
584 | 28 | // On ARM and AArch64 a branch to an undefined weak resolves to the |
585 | 28 | // next instruction, otherwise the place. |
586 | 28 | if (Config->EMachine == EM_ARM) |
587 | 15 | Dest = getARMUndefinedRelativeWeakVA(Type, A, P); |
588 | 13 | else if (13 Config->EMachine == EM_AARCH6413 ) |
589 | 9 | Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); |
590 | 13 | else |
591 | 4 | Dest = Body.getVA(A); |
592 | 585 | } else { |
593 | 557 | Dest = Body.getVA(A); |
594 | 557 | } |
595 | 585 | return Dest - P; |
596 | 6 | } |
597 | 25 | case R_PLT: |
598 | 25 | return Body.getPltVA() + A; |
599 | 216 | case R_PLT_PC: |
600 | 216 | case R_PPC_PLT_OPD: |
601 | 216 | return Body.getPltVA() + A - P; |
602 | 3 | case R_PPC_OPD: { |
603 | 3 | uint64_t SymVA = Body.getVA(A); |
604 | 3 | // If we have an undefined weak symbol, we might get here with a symbol |
605 | 3 | // address of zero. That could overflow, but the code must be unreachable, |
606 | 3 | // so don't bother doing anything at all. |
607 | 3 | if (!SymVA) |
608 | 1 | return 0; |
609 | 2 | if (2 Out::Opd2 ) { |
610 | 2 | // If this is a local call, and we currently have the address of a |
611 | 2 | // function-descriptor, get the underlying code address instead. |
612 | 2 | uint64_t OpdStart = Out::Opd->Addr; |
613 | 2 | uint64_t OpdEnd = OpdStart + Out::Opd->Size; |
614 | 1 | bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd; |
615 | 2 | if (InOpd) |
616 | 1 | SymVA = read64be(&Out::OpdBuf[SymVA - OpdStart]); |
617 | 2 | } |
618 | 2 | return SymVA - P; |
619 | 2 | } |
620 | 5 | case R_PPC_TOC: |
621 | 5 | return getPPC64TocBase() + A; |
622 | 21 | case R_RELAX_GOT_PC: |
623 | 21 | return Body.getVA(A) - P; |
624 | 86 | case R_RELAX_TLS_GD_TO_LE: |
625 | 86 | case R_RELAX_TLS_IE_TO_LE: |
626 | 86 | case R_RELAX_TLS_LD_TO_LE: |
627 | 86 | case R_TLS: |
628 | 86 | // A weak undefined TLS symbol resolves to the base of the TLS |
629 | 86 | // block, i.e. gets a value of zero. If we pass --gc-sections to |
630 | 86 | // lld and .tbss is not referenced, it gets reclaimed and we don't |
631 | 86 | // create a TLS program header. Therefore, we resolve this |
632 | 86 | // statically to zero. |
633 | 86 | if (Body.isTls() && 86 (Body.isLazy() || 86 Body.isUndefined()84 ) && |
634 | 3 | Body.symbol()->isWeak()) |
635 | 3 | return 0; |
636 | 83 | if (83 Target->TcbSize83 ) |
637 | 21 | return Body.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); |
638 | 62 | return Body.getVA(A) - Out::TlsPhdr->p_memsz; |
639 | 4 | case R_RELAX_TLS_GD_TO_LE_NEG: |
640 | 4 | case R_NEG_TLS: |
641 | 4 | return Out::TlsPhdr->p_memsz - Body.getVA(A); |
642 | 24 | case R_SIZE: |
643 | 24 | return A; // Body.getSize was already folded into the addend. |
644 | 8 | case R_TLSDESC: |
645 | 8 | return InX::Got->getGlobalDynAddr(Body) + A; |
646 | 4 | case R_TLSDESC_PAGE: |
647 | 4 | return getAArch64Page(InX::Got->getGlobalDynAddr(Body) + A) - |
648 | 4 | getAArch64Page(P); |
649 | 2 | case R_TLSGD: |
650 | 2 | return InX::Got->getGlobalDynOffset(Body) + A - InX::Got->getSize(); |
651 | 18 | case R_TLSGD_PC: |
652 | 18 | return InX::Got->getGlobalDynAddr(Body) + A - P; |
653 | 2 | case R_TLSLD: |
654 | 2 | return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); |
655 | 4 | case R_TLSLD_PC: |
656 | 4 | return InX::Got->getTlsIndexVA() + A - P; |
657 | 0 | } |
658 | 0 | llvm_unreachable0 ("Invalid expression"); |
659 | 0 | } |
660 | | |
661 | | // This function applies relocations to sections without SHF_ALLOC bit. |
662 | | // Such sections are never mapped to memory at runtime. Debug sections are |
663 | | // an example. Relocations in non-alloc sections are much easier to |
664 | | // handle than in allocated sections because it will never need complex |
665 | | // treatement such as GOT or PLT (because at runtime no one refers them). |
666 | | // So, we handle relocations for non-alloc sections directly in this |
667 | | // function as a performance optimization. |
668 | | template <class ELFT, class RelTy> |
669 | 130k | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
670 | 77 | for (const RelTy &Rel : Rels) { |
671 | 77 | uint32_t Type = Rel.getType(Config->IsMips64EL); |
672 | 77 | uint64_t Offset = getOffset(Rel.r_offset); |
673 | 77 | uint8_t *BufLoc = Buf + Offset; |
674 | 77 | int64_t Addend = getAddend<ELFT>(Rel); |
675 | 77 | if (!RelTy::IsRela) |
676 | 3 | Addend += Target->getImplicitAddend(BufLoc, Type); |
677 | 77 | |
678 | 77 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); |
679 | 77 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); |
680 | 77 | if (Expr == R_NONE) |
681 | 1 | continue; |
682 | 76 | if (76 Expr != R_ABS76 ) { |
683 | 2 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); |
684 | 2 | return; |
685 | 2 | } |
686 | 74 | |
687 | 74 | uint64_t AddrLoc = getParent()->Addr + Offset; |
688 | 74 | uint64_t SymVA = 0; |
689 | 74 | if (!Sym.isTls() || 74 Out::TlsPhdr3 ) |
690 | 72 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( |
691 | 72 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); |
692 | 77 | Target->relocateOne(BufLoc, Type, SymVA); |
693 | 77 | } |
694 | 130k | } void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 669 | 30 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 670 | 74 | for (const RelTy &Rel : Rels) { | 671 | 74 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 672 | 74 | uint64_t Offset = getOffset(Rel.r_offset); | 673 | 74 | uint8_t *BufLoc = Buf + Offset; | 674 | 74 | int64_t Addend = getAddend<ELFT>(Rel); | 675 | 74 | if (!RelTy::IsRela) | 676 | 0 | Addend += Target->getImplicitAddend(BufLoc, Type); | 677 | 74 | | 678 | 74 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 679 | 74 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); | 680 | 74 | if (Expr == R_NONE) | 681 | 1 | continue; | 682 | 73 | if (73 Expr != R_ABS73 ) { | 683 | 1 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 684 | 1 | return; | 685 | 1 | } | 686 | 72 | | 687 | 72 | uint64_t AddrLoc = getParent()->Addr + Offset; | 688 | 72 | uint64_t SymVA = 0; | 689 | 72 | if (!Sym.isTls() || 72 Out::TlsPhdr3 ) | 690 | 71 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 691 | 71 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | 692 | 74 | Target->relocateOne(BufLoc, Type, SymVA); | 693 | 74 | } | 694 | 30 | } |
void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) Line | Count | Source | 669 | 130k | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 670 | 0 | for (const RelTy &Rel : Rels) { | 671 | 0 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 672 | 0 | uint64_t Offset = getOffset(Rel.r_offset); | 673 | 0 | uint8_t *BufLoc = Buf + Offset; | 674 | 0 | int64_t Addend = getAddend<ELFT>(Rel); | 675 | 0 | if (!RelTy::IsRela) | 676 | 0 | Addend += Target->getImplicitAddend(BufLoc, Type); | 677 | 0 |
| 678 | 0 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 679 | 0 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); | 680 | 0 | if (Expr == R_NONE) | 681 | 0 | continue; | 682 | 0 | if (0 Expr != R_ABS0 ) { | 683 | 0 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 684 | 0 | return; | 685 | 0 | } | 686 | 0 |
| 687 | 0 | uint64_t AddrLoc = getParent()->Addr + Offset; | 688 | 0 | uint64_t SymVA = 0; | 689 | 0 | if (!Sym.isTls() || 0 Out::TlsPhdr0 ) | 690 | 0 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 691 | 0 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | 692 | 0 | Target->relocateOne(BufLoc, Type, SymVA); | 693 | 0 | } | 694 | 130k | } |
Unexecuted instantiation: void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) Line | Count | Source | 669 | 2 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 670 | 0 | for (const RelTy &Rel : Rels) { | 671 | 0 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 672 | 0 | uint64_t Offset = getOffset(Rel.r_offset); | 673 | 0 | uint8_t *BufLoc = Buf + Offset; | 674 | 0 | int64_t Addend = getAddend<ELFT>(Rel); | 675 | 0 | if (!RelTy::IsRela) | 676 | 0 | Addend += Target->getImplicitAddend(BufLoc, Type); | 677 | 0 |
| 678 | 0 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 679 | 0 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); | 680 | 0 | if (Expr == R_NONE) | 681 | 0 | continue; | 682 | 0 | if (0 Expr != R_ABS0 ) { | 683 | 0 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 684 | 0 | return; | 685 | 0 | } | 686 | 0 |
| 687 | 0 | uint64_t AddrLoc = getParent()->Addr + Offset; | 688 | 0 | uint64_t SymVA = 0; | 689 | 0 | if (!Sym.isTls() || 0 Out::TlsPhdr0 ) | 690 | 0 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 691 | 0 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | 692 | 0 | Target->relocateOne(BufLoc, Type, SymVA); | 693 | 0 | } | 694 | 2 | } |
void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) Line | Count | Source | 669 | 4 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 670 | 2 | for (const RelTy &Rel : Rels) { | 671 | 2 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 672 | 2 | uint64_t Offset = getOffset(Rel.r_offset); | 673 | 2 | uint8_t *BufLoc = Buf + Offset; | 674 | 2 | int64_t Addend = getAddend<ELFT>(Rel); | 675 | 2 | if (!RelTy::IsRela) | 676 | 2 | Addend += Target->getImplicitAddend(BufLoc, Type); | 677 | 2 | | 678 | 2 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 679 | 2 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); | 680 | 2 | if (Expr == R_NONE) | 681 | 0 | continue; | 682 | 2 | if (2 Expr != R_ABS2 ) { | 683 | 0 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 684 | 0 | return; | 685 | 0 | } | 686 | 2 | | 687 | 2 | uint64_t AddrLoc = getParent()->Addr + Offset; | 688 | 2 | uint64_t SymVA = 0; | 689 | 2 | if (!Sym.isTls() || 2 Out::TlsPhdr0 ) | 690 | 1 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 691 | 1 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | 692 | 2 | Target->relocateOne(BufLoc, Type, SymVA); | 693 | 2 | } | 694 | 4 | } |
Unexecuted instantiation: void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 669 | 7 | void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { | 670 | 1 | for (const RelTy &Rel : Rels) { | 671 | 1 | uint32_t Type = Rel.getType(Config->IsMips64EL); | 672 | 1 | uint64_t Offset = getOffset(Rel.r_offset); | 673 | 1 | uint8_t *BufLoc = Buf + Offset; | 674 | 1 | int64_t Addend = getAddend<ELFT>(Rel); | 675 | 1 | if (!RelTy::IsRela) | 676 | 1 | Addend += Target->getImplicitAddend(BufLoc, Type); | 677 | 1 | | 678 | 1 | SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); | 679 | 1 | RelExpr Expr = Target->getRelExpr(Type, Sym, *File, BufLoc); | 680 | 1 | if (Expr == R_NONE) | 681 | 0 | continue; | 682 | 1 | if (1 Expr != R_ABS1 ) { | 683 | 1 | error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); | 684 | 1 | return; | 685 | 1 | } | 686 | 0 |
| 687 | 0 | uint64_t AddrLoc = getParent()->Addr + Offset; | 688 | 0 | uint64_t SymVA = 0; | 689 | 0 | if (!Sym.isTls() || 0 Out::TlsPhdr0 ) | 690 | 0 | SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( | 691 | 0 | getRelocTargetVA(Type, Addend, AddrLoc, Sym, R_ABS)); | 692 | 1 | Target->relocateOne(BufLoc, Type, SymVA); | 693 | 1 | } | 694 | 7 | } |
Unexecuted instantiation: void lld::elf::InputSection::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(unsigned char*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) |
695 | | |
696 | 3.41k | template <class ELFT> ObjFile<ELFT> *InputSectionBase::getFile() const { |
697 | 3.41k | return cast_or_null<ObjFile<ELFT>>(File); |
698 | 3.41k | } lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >* lld::elf::InputSectionBase::getFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >() const Line | Count | Source | 696 | 628 | template <class ELFT> ObjFile<ELFT> *InputSectionBase::getFile() const { | 697 | 628 | return cast_or_null<ObjFile<ELFT>>(File); | 698 | 628 | } |
lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >* lld::elf::InputSectionBase::getFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >() const Line | Count | Source | 696 | 206 | template <class ELFT> ObjFile<ELFT> *InputSectionBase::getFile() const { | 697 | 206 | return cast_or_null<ObjFile<ELFT>>(File); | 698 | 206 | } |
lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >* lld::elf::InputSectionBase::getFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >() const Line | Count | Source | 696 | 560 | template <class ELFT> ObjFile<ELFT> *InputSectionBase::getFile() const { | 697 | 560 | return cast_or_null<ObjFile<ELFT>>(File); | 698 | 560 | } |
lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >* lld::elf::InputSectionBase::getFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >() const Line | Count | Source | 696 | 2.01k | template <class ELFT> ObjFile<ELFT> *InputSectionBase::getFile() const { | 697 | 2.01k | return cast_or_null<ObjFile<ELFT>>(File); | 698 | 2.01k | } |
|
699 | | |
700 | | template <class ELFT> |
701 | 199k | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { |
702 | 199k | if (Flags & SHF_ALLOC) |
703 | 68.6k | relocateAlloc(Buf, BufEnd); |
704 | 199k | else |
705 | 130k | relocateNonAlloc<ELFT>(Buf, BufEnd); |
706 | 199k | } void lld::elf::InputSectionBase::relocate<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*, unsigned char*) Line | Count | Source | 701 | 198k | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { | 702 | 198k | if (Flags & SHF_ALLOC) | 703 | 67.7k | relocateAlloc(Buf, BufEnd); | 704 | 198k | else | 705 | 130k | relocateNonAlloc<ELFT>(Buf, BufEnd); | 706 | 198k | } |
void lld::elf::InputSectionBase::relocate<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*, unsigned char*) Line | Count | Source | 701 | 432 | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { | 702 | 432 | if (Flags & SHF_ALLOC) | 703 | 425 | relocateAlloc(Buf, BufEnd); | 704 | 432 | else | 705 | 7 | relocateNonAlloc<ELFT>(Buf, BufEnd); | 706 | 432 | } |
void lld::elf::InputSectionBase::relocate<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*, unsigned char*) Line | Count | Source | 701 | 287 | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { | 702 | 287 | if (Flags & SHF_ALLOC) | 703 | 283 | relocateAlloc(Buf, BufEnd); | 704 | 287 | else | 705 | 4 | relocateNonAlloc<ELFT>(Buf, BufEnd); | 706 | 287 | } |
void lld::elf::InputSectionBase::relocate<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*, unsigned char*) Line | Count | Source | 701 | 131 | void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { | 702 | 131 | if (Flags & SHF_ALLOC) | 703 | 129 | relocateAlloc(Buf, BufEnd); | 704 | 131 | else | 705 | 2 | relocateNonAlloc<ELFT>(Buf, BufEnd); | 706 | 131 | } |
|
707 | | |
708 | | template <class ELFT> |
709 | 130k | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { |
710 | 130k | // scanReloc function in Writer.cpp constructs Relocations |
711 | 130k | // vector only for SHF_ALLOC'ed sections. For other sections, |
712 | 130k | // we handle relocations directly here. |
713 | 130k | auto *IS = cast<InputSection>(this); |
714 | 130k | assert(!(IS->Flags & SHF_ALLOC)); |
715 | 130k | if (IS->AreRelocsRela) |
716 | 30 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); |
717 | 130k | else |
718 | 130k | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); |
719 | 130k | } void lld::elf::InputSectionBase::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*, unsigned char*) Line | Count | Source | 709 | 7 | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 710 | 7 | // scanReloc function in Writer.cpp constructs Relocations | 711 | 7 | // vector only for SHF_ALLOC'ed sections. For other sections, | 712 | 7 | // we handle relocations directly here. | 713 | 7 | auto *IS = cast<InputSection>(this); | 714 | 7 | assert(!(IS->Flags & SHF_ALLOC)); | 715 | 7 | if (IS->AreRelocsRela) | 716 | 0 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); | 717 | 7 | else | 718 | 7 | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); | 719 | 7 | } |
void lld::elf::InputSectionBase::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*, unsigned char*) Line | Count | Source | 709 | 2 | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 710 | 2 | // scanReloc function in Writer.cpp constructs Relocations | 711 | 2 | // vector only for SHF_ALLOC'ed sections. For other sections, | 712 | 2 | // we handle relocations directly here. | 713 | 2 | auto *IS = cast<InputSection>(this); | 714 | 2 | assert(!(IS->Flags & SHF_ALLOC)); | 715 | 2 | if (IS->AreRelocsRela) | 716 | 0 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); | 717 | 2 | else | 718 | 2 | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); | 719 | 2 | } |
void lld::elf::InputSectionBase::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*, unsigned char*) Line | Count | Source | 709 | 130k | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 710 | 130k | // scanReloc function in Writer.cpp constructs Relocations | 711 | 130k | // vector only for SHF_ALLOC'ed sections. For other sections, | 712 | 130k | // we handle relocations directly here. | 713 | 130k | auto *IS = cast<InputSection>(this); | 714 | 130k | assert(!(IS->Flags & SHF_ALLOC)); | 715 | 130k | if (IS->AreRelocsRela) | 716 | 30 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); | 717 | 130k | else | 718 | 130k | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); | 719 | 130k | } |
void lld::elf::InputSectionBase::relocateNonAlloc<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*, unsigned char*) Line | Count | Source | 709 | 4 | void InputSectionBase::relocateNonAlloc(uint8_t *Buf, uint8_t *BufEnd) { | 710 | 4 | // scanReloc function in Writer.cpp constructs Relocations | 711 | 4 | // vector only for SHF_ALLOC'ed sections. For other sections, | 712 | 4 | // we handle relocations directly here. | 713 | 4 | auto *IS = cast<InputSection>(this); | 714 | 4 | assert(!(IS->Flags & SHF_ALLOC)); | 715 | 4 | if (IS->AreRelocsRela) | 716 | 0 | IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); | 717 | 4 | else | 718 | 4 | IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); | 719 | 4 | } |
|
720 | | |
721 | 68.8k | void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { |
722 | 68.8k | assert(Flags & SHF_ALLOC); |
723 | 68.8k | const unsigned Bits = Config->Wordsize * 8; |
724 | 1.79k | for (const Relocation &Rel : Relocations) { |
725 | 1.79k | uint64_t Offset = getOffset(Rel.Offset); |
726 | 1.79k | uint8_t *BufLoc = Buf + Offset; |
727 | 1.79k | uint32_t Type = Rel.Type; |
728 | 1.79k | |
729 | 1.79k | uint64_t AddrLoc = getOutputSection()->Addr + Offset; |
730 | 1.79k | RelExpr Expr = Rel.Expr; |
731 | 1.79k | uint64_t TargetVA = SignExtend64( |
732 | 1.79k | getRelocTargetVA(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr), Bits); |
733 | 1.79k | |
734 | 1.79k | switch (Expr) { |
735 | 30 | case R_RELAX_GOT_PC: |
736 | 30 | case R_RELAX_GOT_PC_NOPIC: |
737 | 30 | Target->relaxGot(BufLoc, TargetVA); |
738 | 30 | break; |
739 | 48 | case R_RELAX_TLS_IE_TO_LE: |
740 | 48 | Target->relaxTlsIeToLe(BufLoc, Type, TargetVA); |
741 | 48 | break; |
742 | 12 | case R_RELAX_TLS_LD_TO_LE: |
743 | 12 | Target->relaxTlsLdToLe(BufLoc, Type, TargetVA); |
744 | 12 | break; |
745 | 10 | case R_RELAX_TLS_GD_TO_LE: |
746 | 10 | case R_RELAX_TLS_GD_TO_LE_NEG: |
747 | 10 | Target->relaxTlsGdToLe(BufLoc, Type, TargetVA); |
748 | 10 | break; |
749 | 10 | case R_RELAX_TLS_GD_TO_IE: |
750 | 10 | case R_RELAX_TLS_GD_TO_IE_ABS: |
751 | 10 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: |
752 | 10 | case R_RELAX_TLS_GD_TO_IE_END: |
753 | 10 | Target->relaxTlsGdToIe(BufLoc, Type, TargetVA); |
754 | 10 | break; |
755 | 6 | case R_PPC_PLT_OPD: |
756 | 6 | // Patch a nop (0x60000000) to a ld. |
757 | 6 | if (BufLoc + 8 <= BufEnd && 6 read32be(BufLoc + 4) == 0x600000005 ) |
758 | 2 | write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) |
759 | 6 | LLVM_FALLTHROUGH; |
760 | 1.68k | default: |
761 | 1.68k | Target->relocateOne(BufLoc, Type, TargetVA); |
762 | 1.68k | break; |
763 | 68.8k | } |
764 | 68.8k | } |
765 | 68.8k | } |
766 | | |
767 | 209k | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
768 | 209k | if (this->Type == SHT_NOBITS) |
769 | 1 | return; |
770 | 209k | |
771 | 209k | if (auto *209k S209k = dyn_cast<SyntheticSection>(this)) { |
772 | 10.4k | S->writeTo(Buf + OutSecOff); |
773 | 10.4k | return; |
774 | 10.4k | } |
775 | 199k | |
776 | 199k | // If -r or --emit-relocs is given, then an InputSection |
777 | 199k | // may be a relocation section. |
778 | 199k | if (199k this->Type == SHT_RELA199k ) { |
779 | 48 | copyRelocations<ELFT>(Buf + OutSecOff, |
780 | 48 | this->template getDataAs<typename ELFT::Rela>()); |
781 | 48 | return; |
782 | 48 | } |
783 | 199k | if (199k this->Type == SHT_REL199k ) { |
784 | 18 | copyRelocations<ELFT>(Buf + OutSecOff, |
785 | 18 | this->template getDataAs<typename ELFT::Rel>()); |
786 | 18 | return; |
787 | 18 | } |
788 | 199k | |
789 | 199k | // If -r is given, we may have a SHT_GROUP section. |
790 | 199k | if (199k this->Type == SHT_GROUP199k ) { |
791 | 8 | copyShtGroup<ELFT>(Buf + OutSecOff); |
792 | 8 | return; |
793 | 8 | } |
794 | 199k | |
795 | 199k | // Copy section contents from source object file to output file |
796 | 199k | // and then apply relocations. |
797 | 199k | memcpy(Buf + OutSecOff, Data.data(), Data.size()); |
798 | 199k | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); |
799 | 199k | this->relocate<ELFT>(Buf, BufEnd); |
800 | 199k | } void lld::elf::InputSection::writeTo<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*) Line | Count | Source | 767 | 206k | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | 768 | 206k | if (this->Type == SHT_NOBITS) | 769 | 1 | return; | 770 | 206k | | 771 | 206k | if (auto *206k S206k = dyn_cast<SyntheticSection>(this)) { | 772 | 7.73k | S->writeTo(Buf + OutSecOff); | 773 | 7.73k | return; | 774 | 7.73k | } | 775 | 198k | | 776 | 198k | // If -r or --emit-relocs is given, then an InputSection | 777 | 198k | // may be a relocation section. | 778 | 198k | if (198k this->Type == SHT_RELA198k ) { | 779 | 48 | copyRelocations<ELFT>(Buf + OutSecOff, | 780 | 48 | this->template getDataAs<typename ELFT::Rela>()); | 781 | 48 | return; | 782 | 48 | } | 783 | 198k | if (198k this->Type == SHT_REL198k ) { | 784 | 0 | copyRelocations<ELFT>(Buf + OutSecOff, | 785 | 0 | this->template getDataAs<typename ELFT::Rel>()); | 786 | 0 | return; | 787 | 0 | } | 788 | 198k | | 789 | 198k | // If -r is given, we may have a SHT_GROUP section. | 790 | 198k | if (198k this->Type == SHT_GROUP198k ) { | 791 | 8 | copyShtGroup<ELFT>(Buf + OutSecOff); | 792 | 8 | return; | 793 | 8 | } | 794 | 198k | | 795 | 198k | // Copy section contents from source object file to output file | 796 | 198k | // and then apply relocations. | 797 | 198k | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 798 | 198k | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | 799 | 198k | this->relocate<ELFT>(Buf, BufEnd); | 800 | 198k | } |
void lld::elf::InputSection::writeTo<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*) Line | Count | Source | 767 | 1.19k | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | 768 | 1.19k | if (this->Type == SHT_NOBITS) | 769 | 0 | return; | 770 | 1.19k | | 771 | 1.19k | if (auto *1.19k S1.19k = dyn_cast<SyntheticSection>(this)) { | 772 | 906 | S->writeTo(Buf + OutSecOff); | 773 | 906 | return; | 774 | 906 | } | 775 | 293 | | 776 | 293 | // If -r or --emit-relocs is given, then an InputSection | 777 | 293 | // may be a relocation section. | 778 | 293 | if (293 this->Type == SHT_RELA293 ) { | 779 | 0 | copyRelocations<ELFT>(Buf + OutSecOff, | 780 | 0 | this->template getDataAs<typename ELFT::Rela>()); | 781 | 0 | return; | 782 | 0 | } | 783 | 293 | if (293 this->Type == SHT_REL293 ) { | 784 | 6 | copyRelocations<ELFT>(Buf + OutSecOff, | 785 | 6 | this->template getDataAs<typename ELFT::Rel>()); | 786 | 6 | return; | 787 | 6 | } | 788 | 287 | | 789 | 287 | // If -r is given, we may have a SHT_GROUP section. | 790 | 287 | if (287 this->Type == SHT_GROUP287 ) { | 791 | 0 | copyShtGroup<ELFT>(Buf + OutSecOff); | 792 | 0 | return; | 793 | 0 | } | 794 | 287 | | 795 | 287 | // Copy section contents from source object file to output file | 796 | 287 | // and then apply relocations. | 797 | 287 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 798 | 287 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | 799 | 287 | this->relocate<ELFT>(Buf, BufEnd); | 800 | 287 | } |
void lld::elf::InputSection::writeTo<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*) Line | Count | Source | 767 | 1.84k | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | 768 | 1.84k | if (this->Type == SHT_NOBITS) | 769 | 0 | return; | 770 | 1.84k | | 771 | 1.84k | if (auto *1.84k S1.84k = dyn_cast<SyntheticSection>(this)) { | 772 | 1.40k | S->writeTo(Buf + OutSecOff); | 773 | 1.40k | return; | 774 | 1.40k | } | 775 | 444 | | 776 | 444 | // If -r or --emit-relocs is given, then an InputSection | 777 | 444 | // may be a relocation section. | 778 | 444 | if (444 this->Type == SHT_RELA444 ) { | 779 | 0 | copyRelocations<ELFT>(Buf + OutSecOff, | 780 | 0 | this->template getDataAs<typename ELFT::Rela>()); | 781 | 0 | return; | 782 | 0 | } | 783 | 444 | if (444 this->Type == SHT_REL444 ) { | 784 | 12 | copyRelocations<ELFT>(Buf + OutSecOff, | 785 | 12 | this->template getDataAs<typename ELFT::Rel>()); | 786 | 12 | return; | 787 | 12 | } | 788 | 432 | | 789 | 432 | // If -r is given, we may have a SHT_GROUP section. | 790 | 432 | if (432 this->Type == SHT_GROUP432 ) { | 791 | 0 | copyShtGroup<ELFT>(Buf + OutSecOff); | 792 | 0 | return; | 793 | 0 | } | 794 | 432 | | 795 | 432 | // Copy section contents from source object file to output file | 796 | 432 | // and then apply relocations. | 797 | 432 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 798 | 432 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | 799 | 432 | this->relocate<ELFT>(Buf, BufEnd); | 800 | 432 | } |
void lld::elf::InputSection::writeTo<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*) Line | Count | Source | 767 | 523 | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { | 768 | 523 | if (this->Type == SHT_NOBITS) | 769 | 0 | return; | 770 | 523 | | 771 | 523 | if (auto *523 S523 = dyn_cast<SyntheticSection>(this)) { | 772 | 392 | S->writeTo(Buf + OutSecOff); | 773 | 392 | return; | 774 | 392 | } | 775 | 131 | | 776 | 131 | // If -r or --emit-relocs is given, then an InputSection | 777 | 131 | // may be a relocation section. | 778 | 131 | if (131 this->Type == SHT_RELA131 ) { | 779 | 0 | copyRelocations<ELFT>(Buf + OutSecOff, | 780 | 0 | this->template getDataAs<typename ELFT::Rela>()); | 781 | 0 | return; | 782 | 0 | } | 783 | 131 | if (131 this->Type == SHT_REL131 ) { | 784 | 0 | copyRelocations<ELFT>(Buf + OutSecOff, | 785 | 0 | this->template getDataAs<typename ELFT::Rel>()); | 786 | 0 | return; | 787 | 0 | } | 788 | 131 | | 789 | 131 | // If -r is given, we may have a SHT_GROUP section. | 790 | 131 | if (131 this->Type == SHT_GROUP131 ) { | 791 | 0 | copyShtGroup<ELFT>(Buf + OutSecOff); | 792 | 0 | return; | 793 | 0 | } | 794 | 131 | | 795 | 131 | // Copy section contents from source object file to output file | 796 | 131 | // and then apply relocations. | 797 | 131 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | 798 | 131 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | 799 | 131 | this->relocate<ELFT>(Buf, BufEnd); | 800 | 131 | } |
|
801 | | |
802 | 17 | void InputSection::replace(InputSection *Other) { |
803 | 17 | this->Alignment = std::max(this->Alignment, Other->Alignment); |
804 | 17 | Other->Repl = this->Repl; |
805 | 17 | Other->Live = false; |
806 | 17 | } |
807 | | |
808 | | template <class ELFT> |
809 | | EhInputSection::EhInputSection(ObjFile<ELFT> *F, |
810 | | const typename ELFT::Shdr *Header, |
811 | | StringRef Name) |
812 | 95 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { |
813 | 95 | // Mark .eh_frame sections as live by default because there are |
814 | 95 | // usually no relocations that point to .eh_frames. Otherwise, |
815 | 95 | // the garbage collector would drop all .eh_frame sections. |
816 | 95 | this->Live = true; |
817 | 95 | } lld::elf::EhInputSection::EhInputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 812 | 4 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { | 813 | 4 | // Mark .eh_frame sections as live by default because there are | 814 | 4 | // usually no relocations that point to .eh_frames. Otherwise, | 815 | 4 | // the garbage collector would drop all .eh_frame sections. | 816 | 4 | this->Live = true; | 817 | 4 | } |
lld::elf::EhInputSection::EhInputSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 812 | 1 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { | 813 | 1 | // Mark .eh_frame sections as live by default because there are | 814 | 1 | // usually no relocations that point to .eh_frames. Otherwise, | 815 | 1 | // the garbage collector would drop all .eh_frame sections. | 816 | 1 | this->Live = true; | 817 | 1 | } |
lld::elf::EhInputSection::EhInputSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 812 | 87 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { | 813 | 87 | // Mark .eh_frame sections as live by default because there are | 814 | 87 | // usually no relocations that point to .eh_frames. Otherwise, | 815 | 87 | // the garbage collector would drop all .eh_frame sections. | 816 | 87 | this->Live = true; | 817 | 87 | } |
lld::elf::EhInputSection::EhInputSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 812 | 3 | : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { | 813 | 3 | // Mark .eh_frame sections as live by default because there are | 814 | 3 | // usually no relocations that point to .eh_frames. Otherwise, | 815 | 3 | // the garbage collector would drop all .eh_frame sections. | 816 | 3 | this->Live = true; | 817 | 3 | } |
|
818 | | |
819 | 121 | SyntheticSection *EhInputSection::getParent() const { |
820 | 121 | return cast_or_null<SyntheticSection>(Parent); |
821 | 121 | } |
822 | | |
823 | 319k | bool EhInputSection::classof(const SectionBase *S) { |
824 | 319k | return S->kind() == InputSectionBase::EHFrame; |
825 | 319k | } |
826 | | |
827 | | // Returns the index of the first relocation that points to a region between |
828 | | // Begin and Begin+Size. |
829 | | template <class IntTy, class RelTy> |
830 | | static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels, |
831 | 210 | unsigned &RelocI) { |
832 | 210 | // Start search from RelocI for fast access. That works because the |
833 | 210 | // relocations are sorted in .eh_frame. |
834 | 249 | for (unsigned N = Rels.size(); RelocI < N249 ; ++RelocI39 ) { |
835 | 241 | const RelTy &Rel = Rels[RelocI]; |
836 | 241 | if (Rel.r_offset < Begin) |
837 | 39 | continue; |
838 | 202 | |
839 | 202 | if (202 Rel.r_offset < Begin + Size202 ) |
840 | 124 | return RelocI; |
841 | 78 | return -1; |
842 | 78 | } |
843 | 8 | return -1; |
844 | 210 | } Unexecuted instantiation: InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> > const&, unsigned int&) InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> > const&, unsigned int&) Line | Count | Source | 831 | 8 | unsigned &RelocI) { | 832 | 8 | // Start search from RelocI for fast access. That works because the | 833 | 8 | // relocations are sorted in .eh_frame. | 834 | 10 | for (unsigned N = Rels.size(); RelocI < N10 ; ++RelocI2 ) { | 835 | 10 | const RelTy &Rel = Rels[RelocI]; | 836 | 10 | if (Rel.r_offset < Begin) | 837 | 2 | continue; | 838 | 8 | | 839 | 8 | if (8 Rel.r_offset < Begin + Size8 ) | 840 | 6 | return RelocI; | 841 | 2 | return -1; | 842 | 2 | } | 843 | 0 | return -1; | 844 | 8 | } |
Unexecuted instantiation: InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> > const&, unsigned int&) InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> > const&, unsigned int&) Line | Count | Source | 831 | 2 | unsigned &RelocI) { | 832 | 2 | // Start search from RelocI for fast access. That works because the | 833 | 2 | // relocations are sorted in .eh_frame. | 834 | 2 | for (unsigned N = Rels.size(); RelocI < N2 ; ++RelocI0 ) { | 835 | 2 | const RelTy &Rel = Rels[RelocI]; | 836 | 2 | if (Rel.r_offset < Begin) | 837 | 0 | continue; | 838 | 2 | | 839 | 2 | if (2 Rel.r_offset < Begin + Size2 ) | 840 | 1 | return RelocI; | 841 | 1 | return -1; | 842 | 1 | } | 843 | 0 | return -1; | 844 | 2 | } |
InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> > const&, unsigned int&) Line | Count | Source | 831 | 195 | unsigned &RelocI) { | 832 | 195 | // Start search from RelocI for fast access. That works because the | 833 | 195 | // relocations are sorted in .eh_frame. | 834 | 232 | for (unsigned N = Rels.size(); RelocI < N232 ; ++RelocI37 ) { | 835 | 225 | const RelTy &Rel = Rels[RelocI]; | 836 | 225 | if (Rel.r_offset < Begin) | 837 | 37 | continue; | 838 | 188 | | 839 | 188 | if (188 Rel.r_offset < Begin + Size188 ) | 840 | 115 | return RelocI; | 841 | 73 | return -1; | 842 | 73 | } | 843 | 7 | return -1; | 844 | 195 | } |
Unexecuted instantiation: InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> > const&, unsigned int&) InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> > const&, unsigned int&) Line | Count | Source | 831 | 5 | unsigned &RelocI) { | 832 | 5 | // Start search from RelocI for fast access. That works because the | 833 | 5 | // relocations are sorted in .eh_frame. | 834 | 5 | for (unsigned N = Rels.size(); RelocI < N5 ; ++RelocI0 ) { | 835 | 4 | const RelTy &Rel = Rels[RelocI]; | 836 | 4 | if (Rel.r_offset < Begin) | 837 | 0 | continue; | 838 | 4 | | 839 | 4 | if (4 Rel.r_offset < Begin + Size4 ) | 840 | 2 | return RelocI; | 841 | 2 | return -1; | 842 | 2 | } | 843 | 1 | return -1; | 844 | 5 | } |
Unexecuted instantiation: InputSection.cpp:unsigned int getReloc<unsigned long, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(unsigned long, unsigned long, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> > const&, unsigned int&) |
845 | | |
846 | | // .eh_frame is a sequence of CIE or FDE records. |
847 | | // This function splits an input section into records and returns them. |
848 | 100 | template <class ELFT> void EhInputSection::split() { |
849 | 100 | // Early exit if already split. |
850 | 100 | if (!this->Pieces.empty()) |
851 | 5 | return; |
852 | 95 | |
853 | 95 | if (95 this->NumRelocations95 ) { |
854 | 85 | if (this->AreRelocsRela) |
855 | 80 | split<ELFT>(this->relas<ELFT>()); |
856 | 85 | else |
857 | 5 | split<ELFT>(this->rels<ELFT>()); |
858 | 85 | return; |
859 | 85 | } |
860 | 10 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); |
861 | 10 | } void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, false> >() Line | Count | Source | 848 | 6 | template <class ELFT> void EhInputSection::split() { | 849 | 6 | // Early exit if already split. | 850 | 6 | if (!this->Pieces.empty()) | 851 | 2 | return; | 852 | 4 | | 853 | 4 | if (4 this->NumRelocations4 ) { | 854 | 4 | if (this->AreRelocsRela) | 855 | 0 | split<ELFT>(this->relas<ELFT>()); | 856 | 4 | else | 857 | 4 | split<ELFT>(this->rels<ELFT>()); | 858 | 4 | return; | 859 | 4 | } | 860 | 0 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); | 861 | 0 | } |
void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, false> >() Line | Count | Source | 848 | 1 | template <class ELFT> void EhInputSection::split() { | 849 | 1 | // Early exit if already split. | 850 | 1 | if (!this->Pieces.empty()) | 851 | 0 | return; | 852 | 1 | | 853 | 1 | if (1 this->NumRelocations1 ) { | 854 | 1 | if (this->AreRelocsRela) | 855 | 0 | split<ELFT>(this->relas<ELFT>()); | 856 | 1 | else | 857 | 1 | split<ELFT>(this->rels<ELFT>()); | 858 | 1 | return; | 859 | 1 | } | 860 | 0 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); | 861 | 0 | } |
void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, true> >() Line | Count | Source | 848 | 90 | template <class ELFT> void EhInputSection::split() { | 849 | 90 | // Early exit if already split. | 850 | 90 | if (!this->Pieces.empty()) | 851 | 3 | return; | 852 | 87 | | 853 | 87 | if (87 this->NumRelocations87 ) { | 854 | 78 | if (this->AreRelocsRela) | 855 | 78 | split<ELFT>(this->relas<ELFT>()); | 856 | 78 | else | 857 | 0 | split<ELFT>(this->rels<ELFT>()); | 858 | 78 | return; | 859 | 78 | } | 860 | 9 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); | 861 | 9 | } |
void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, true> >() Line | Count | Source | 848 | 3 | template <class ELFT> void EhInputSection::split() { | 849 | 3 | // Early exit if already split. | 850 | 3 | if (!this->Pieces.empty()) | 851 | 0 | return; | 852 | 3 | | 853 | 3 | if (3 this->NumRelocations3 ) { | 854 | 2 | if (this->AreRelocsRela) | 855 | 2 | split<ELFT>(this->relas<ELFT>()); | 856 | 2 | else | 857 | 0 | split<ELFT>(this->rels<ELFT>()); | 858 | 2 | return; | 859 | 2 | } | 860 | 1 | split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); | 861 | 1 | } |
|
862 | | |
863 | | template <class ELFT, class RelTy> |
864 | 95 | void EhInputSection::split(ArrayRef<RelTy> Rels) { |
865 | 95 | ArrayRef<uint8_t> Data = this->Data; |
866 | 95 | unsigned RelI = 0; |
867 | 300 | for (size_t Off = 0, End = Data.size(); Off != End300 ;) { |
868 | 210 | size_t Size = readEhRecordSize<ELFT>(this, Off); |
869 | 210 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); |
870 | 210 | // The empty record is the end marker. |
871 | 210 | if (Size == 4) |
872 | 5 | break; |
873 | 205 | Off += Size; |
874 | 205 | } |
875 | 95 | } Unexecuted instantiation: void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) Unexecuted instantiation: void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) Line | Count | Source | 864 | 3 | void EhInputSection::split(ArrayRef<RelTy> Rels) { | 865 | 3 | ArrayRef<uint8_t> Data = this->Data; | 866 | 3 | unsigned RelI = 0; | 867 | 8 | for (size_t Off = 0, End = Data.size(); Off != End8 ;) { | 868 | 5 | size_t Size = readEhRecordSize<ELFT>(this, Off); | 869 | 5 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); | 870 | 5 | // The empty record is the end marker. | 871 | 5 | if (Size == 4) | 872 | 0 | break; | 873 | 5 | Off += Size; | 874 | 5 | } | 875 | 3 | } |
Unexecuted instantiation: void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 864 | 87 | void EhInputSection::split(ArrayRef<RelTy> Rels) { | 865 | 87 | ArrayRef<uint8_t> Data = this->Data; | 866 | 87 | unsigned RelI = 0; | 867 | 277 | for (size_t Off = 0, End = Data.size(); Off != End277 ;) { | 868 | 195 | size_t Size = readEhRecordSize<ELFT>(this, Off); | 869 | 195 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); | 870 | 195 | // The empty record is the end marker. | 871 | 195 | if (Size == 4) | 872 | 5 | break; | 873 | 190 | Off += Size; | 874 | 190 | } | 875 | 87 | } |
void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 864 | 4 | void EhInputSection::split(ArrayRef<RelTy> Rels) { | 865 | 4 | ArrayRef<uint8_t> Data = this->Data; | 866 | 4 | unsigned RelI = 0; | 867 | 12 | for (size_t Off = 0, End = Data.size(); Off != End12 ;) { | 868 | 8 | size_t Size = readEhRecordSize<ELFT>(this, Off); | 869 | 8 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); | 870 | 8 | // The empty record is the end marker. | 871 | 8 | if (Size == 4) | 872 | 0 | break; | 873 | 8 | Off += Size; | 874 | 8 | } | 875 | 4 | } |
Unexecuted instantiation: void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) void lld::elf::EhInputSection::split<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) Line | Count | Source | 864 | 1 | void EhInputSection::split(ArrayRef<RelTy> Rels) { | 865 | 1 | ArrayRef<uint8_t> Data = this->Data; | 866 | 1 | unsigned RelI = 0; | 867 | 3 | for (size_t Off = 0, End = Data.size(); Off != End3 ;) { | 868 | 2 | size_t Size = readEhRecordSize<ELFT>(this, Off); | 869 | 2 | this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); | 870 | 2 | // The empty record is the end marker. | 871 | 2 | if (Size == 4) | 872 | 0 | break; | 873 | 2 | Off += Size; | 874 | 2 | } | 875 | 1 | } |
|
876 | | |
877 | 1.63k | static size_t findNull(ArrayRef<uint8_t> A, size_t EntSize) { |
878 | 1.63k | // Optimize the common case. |
879 | 1.63k | StringRef S((const char *)A.data(), A.size()); |
880 | 1.63k | if (EntSize == 1) |
881 | 1.62k | return S.find(0); |
882 | 5 | |
883 | 7 | for (unsigned I = 0, N = S.size(); 5 I != N7 ; I += EntSize2 ) { |
884 | 7 | const char *B = S.begin() + I; |
885 | 30 | if (std::all_of(B, B + EntSize, [](char C) 7 { return C == 0; }30 )) |
886 | 5 | return I; |
887 | 7 | } |
888 | 0 | return StringRef::npos; |
889 | 1.63k | } |
890 | | |
891 | 161 | SyntheticSection *MergeInputSection::getParent() const { |
892 | 161 | return cast_or_null<SyntheticSection>(Parent); |
893 | 161 | } |
894 | | |
895 | | // Split SHF_STRINGS section. Such section is a sequence of |
896 | | // null-terminated strings. |
897 | 1.58k | void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) { |
898 | 1.58k | size_t Off = 0; |
899 | 1.58k | bool IsAlloc = this->Flags & SHF_ALLOC; |
900 | 3.21k | while (!Data.empty()3.21k ) { |
901 | 1.63k | size_t End = findNull(Data, EntSize); |
902 | 1.63k | if (End == StringRef::npos) |
903 | 0 | fatal(toString(this) + ": string is not null terminated"); |
904 | 1.63k | size_t Size = End + EntSize; |
905 | 1.63k | Pieces.emplace_back(Off, !IsAlloc); |
906 | 1.63k | Hashes.push_back(hash_value(toStringRef(Data.slice(0, Size)))); |
907 | 1.63k | Data = Data.slice(Size); |
908 | 1.63k | Off += Size; |
909 | 1.63k | } |
910 | 1.58k | } |
911 | | |
912 | | // Split non-SHF_STRINGS section. Such section is a sequence of |
913 | | // fixed size records. |
914 | | void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data, |
915 | 13 | size_t EntSize) { |
916 | 13 | size_t Size = Data.size(); |
917 | 13 | assert((Size % EntSize) == 0); |
918 | 13 | bool IsAlloc = this->Flags & SHF_ALLOC; |
919 | 32 | for (unsigned I = 0, N = Size; I != N32 ; I += EntSize19 ) { |
920 | 19 | Hashes.push_back(hash_value(toStringRef(Data.slice(I, EntSize)))); |
921 | 19 | Pieces.emplace_back(I, !IsAlloc); |
922 | 19 | } |
923 | 13 | } |
924 | | |
925 | | template <class ELFT> |
926 | | MergeInputSection::MergeInputSection(ObjFile<ELFT> *F, |
927 | | const typename ELFT::Shdr *Header, |
928 | | StringRef Name) |
929 | 1.60k | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} lld::elf::MergeInputSection::MergeInputSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, false> >*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 929 | 190 | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} |
lld::elf::MergeInputSection::MergeInputSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, true> >*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 929 | 43 | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} |
lld::elf::MergeInputSection::MergeInputSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)1, true> >*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Shdr const*, llvm::StringRef) Line | Count | Source | 929 | 1.28k | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} |
lld::elf::MergeInputSection::MergeInputSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::ObjFile<llvm::object::ELFType<(llvm::support::endianness)0, false> >*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Shdr const*, llvm::StringRef) Line | Count | Source | 929 | 88 | : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} |
|
930 | | |
931 | | // This function is called after we obtain a complete list of input sections |
932 | | // that need to be linked. This is responsible to split section contents |
933 | | // into small chunks for further processing. |
934 | | // |
935 | | // Note that this function is called from parallelForEach. This must be |
936 | | // thread-safe (i.e. no memory allocation from the pools). |
937 | 1.59k | void MergeInputSection::splitIntoPieces() { |
938 | 1.59k | assert(Pieces.empty()); |
939 | 1.59k | ArrayRef<uint8_t> Data = this->Data; |
940 | 1.59k | uint64_t EntSize = this->Entsize; |
941 | 1.59k | if (this->Flags & SHF_STRINGS) |
942 | 1.58k | splitStrings(Data, EntSize); |
943 | 1.59k | else |
944 | 13 | splitNonStrings(Data, EntSize); |
945 | 1.59k | |
946 | 1.59k | if (Config->GcSections && 1.59k (this->Flags & SHF_ALLOC)70 ) |
947 | 7 | for (uint64_t Off : LiveOffsets) |
948 | 8 | this->getSectionPiece(Off)->Live = true; |
949 | 1.59k | } |
950 | | |
951 | 410k | bool MergeInputSection::classof(const SectionBase *S) { |
952 | 410k | return S->kind() == InputSectionBase::Merge; |
953 | 410k | } |
954 | | |
955 | | // Do binary search to get a section piece at a given input offset. |
956 | 54 | SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) { |
957 | 54 | auto *This = static_cast<const MergeInputSection *>(this); |
958 | 54 | return const_cast<SectionPiece *>(This->getSectionPiece(Offset)); |
959 | 54 | } |
960 | | |
961 | | template <class It, class T, class Compare> |
962 | 59 | static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) { |
963 | 59 | size_t Size = std::distance(First, Last); |
964 | 59 | assert(Size != 0); |
965 | 134 | while (Size != 1134 ) { |
966 | 75 | size_t H = Size / 2; |
967 | 75 | const It MI = First + H; |
968 | 75 | Size -= H; |
969 | 75 | First = Comp(Value, *MI) ? First47 : First + H28 ; |
970 | 75 | } |
971 | 59 | return Comp(Value, *First) ? First0 : First + 159 ; |
972 | 59 | } |
973 | | |
974 | 59 | const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { |
975 | 59 | uint64_t Size = this->Data.size(); |
976 | 59 | if (Offset >= Size) |
977 | 0 | fatal(toString(this) + ": entry is past the end of the section"); |
978 | 59 | |
979 | 59 | // Find the element this offset points to. |
980 | 59 | auto I = fastUpperBound( |
981 | 59 | Pieces.begin(), Pieces.end(), Offset, |
982 | 134 | [](const uint64_t &A, const SectionPiece &B) { return A < B.InputOff; }); |
983 | 59 | --I; |
984 | 59 | return &*I; |
985 | 59 | } |
986 | | |
987 | | // Returns the offset in an output section for a given input offset. |
988 | | // Because contents of a mergeable section is not contiguous in output, |
989 | | // it is not just an addition to a base output offset. |
990 | 74 | uint64_t MergeInputSection::getOffset(uint64_t Offset) const { |
991 | 74 | // Initialize OffsetMap lazily. |
992 | 34 | llvm::call_once(InitOffsetMap, [&] { |
993 | 34 | OffsetMap.reserve(Pieces.size()); |
994 | 34 | for (const SectionPiece &Piece : Pieces) |
995 | 74 | OffsetMap[Piece.InputOff] = Piece.OutputOff; |
996 | 34 | }); |
997 | 74 | |
998 | 74 | // Find a string starting at a given offset. |
999 | 74 | auto It = OffsetMap.find(Offset); |
1000 | 74 | if (It != OffsetMap.end()) |
1001 | 68 | return It->second; |
1002 | 6 | |
1003 | 6 | if (6 !this->Live6 ) |
1004 | 1 | return 0; |
1005 | 5 | |
1006 | 5 | // If Offset is not at beginning of a section piece, it is not in the map. |
1007 | 5 | // In that case we need to search from the original section piece vector. |
1008 | 5 | const SectionPiece &Piece = *this->getSectionPiece(Offset); |
1009 | 5 | if (!Piece.Live) |
1010 | 0 | return 0; |
1011 | 5 | |
1012 | 5 | uint64_t Addend = Offset - Piece.InputOff; |
1013 | 5 | return Piece.OutputOff + Addend; |
1014 | 5 | } |
1015 | | |
1016 | | template InputSection::InputSection(ObjFile<ELF32LE> *, const ELF32LE::Shdr *, |
1017 | | StringRef); |
1018 | | template InputSection::InputSection(ObjFile<ELF32BE> *, const ELF32BE::Shdr *, |
1019 | | StringRef); |
1020 | | template InputSection::InputSection(ObjFile<ELF64LE> *, const ELF64LE::Shdr *, |
1021 | | StringRef); |
1022 | | template InputSection::InputSection(ObjFile<ELF64BE> *, const ELF64BE::Shdr *, |
1023 | | StringRef); |
1024 | | |
1025 | | template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t); |
1026 | | template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t); |
1027 | | template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t); |
1028 | | template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t); |
1029 | | |
1030 | | template std::string InputSectionBase::getSrcMsg<ELF32LE>(uint64_t); |
1031 | | template std::string InputSectionBase::getSrcMsg<ELF32BE>(uint64_t); |
1032 | | template std::string InputSectionBase::getSrcMsg<ELF64LE>(uint64_t); |
1033 | | template std::string InputSectionBase::getSrcMsg<ELF64BE>(uint64_t); |
1034 | | |
1035 | | template std::string InputSectionBase::getObjMsg<ELF32LE>(uint64_t); |
1036 | | template std::string InputSectionBase::getObjMsg<ELF32BE>(uint64_t); |
1037 | | template std::string InputSectionBase::getObjMsg<ELF64LE>(uint64_t); |
1038 | | template std::string InputSectionBase::getObjMsg<ELF64BE>(uint64_t); |
1039 | | |
1040 | | template void InputSection::writeTo<ELF32LE>(uint8_t *); |
1041 | | template void InputSection::writeTo<ELF32BE>(uint8_t *); |
1042 | | template void InputSection::writeTo<ELF64LE>(uint8_t *); |
1043 | | template void InputSection::writeTo<ELF64BE>(uint8_t *); |
1044 | | |
1045 | | template ObjFile<ELF32LE> *InputSectionBase::getFile<ELF32LE>() const; |
1046 | | template ObjFile<ELF32BE> *InputSectionBase::getFile<ELF32BE>() const; |
1047 | | template ObjFile<ELF64LE> *InputSectionBase::getFile<ELF64LE>() const; |
1048 | | template ObjFile<ELF64BE> *InputSectionBase::getFile<ELF64BE>() const; |
1049 | | |
1050 | | template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> *, |
1051 | | const ELF32LE::Shdr *, StringRef); |
1052 | | template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> *, |
1053 | | const ELF32BE::Shdr *, StringRef); |
1054 | | template MergeInputSection::MergeInputSection(ObjFile<ELF64LE> *, |
1055 | | const ELF64LE::Shdr *, StringRef); |
1056 | | template MergeInputSection::MergeInputSection(ObjFile<ELF64BE> *, |
1057 | | const ELF64BE::Shdr *, StringRef); |
1058 | | |
1059 | | template EhInputSection::EhInputSection(ObjFile<ELF32LE> *, |
1060 | | const ELF32LE::Shdr *, StringRef); |
1061 | | template EhInputSection::EhInputSection(ObjFile<ELF32BE> *, |
1062 | | const ELF32BE::Shdr *, StringRef); |
1063 | | template EhInputSection::EhInputSection(ObjFile<ELF64LE> *, |
1064 | | const ELF64LE::Shdr *, StringRef); |
1065 | | template EhInputSection::EhInputSection(ObjFile<ELF64BE> *, |
1066 | | const ELF64BE::Shdr *, StringRef); |
1067 | | |
1068 | | template void EhInputSection::split<ELF32LE>(); |
1069 | | template void EhInputSection::split<ELF32BE>(); |
1070 | | template void EhInputSection::split<ELF64LE>(); |
1071 | | template void EhInputSection::split<ELF64BE>(); |