1 | //===- ELF.cpp - ELF object file implementation ---------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/Object/ELF.h" |
10 | #include "llvm/ADT/StringExtras.h" |
11 | #include "llvm/BinaryFormat/ELF.h" |
12 | #include "llvm/Object/Decompressor.h" |
13 | #include "llvm/Support/Compiler.h" |
14 | #include "llvm/Support/DataExtractor.h" |
15 | |
16 | using namespace llvm; |
17 | using namespace object; |
18 | |
19 | #define STRINGIFY_ENUM_CASE(ns, name) \ |
20 | case ns::name: \ |
21 | return #name; |
22 | |
23 | #define ELF_RELOC(name, value) STRINGIFY_ENUM_CASE(ELF, name) |
24 | |
25 | StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, |
26 | uint32_t Type) { |
27 | switch (Machine) { |
28 | case ELF::EM_68K: |
29 | switch (Type) { |
30 | #include "llvm/BinaryFormat/ELFRelocs/M68k.def" |
31 | default: |
32 | break; |
33 | } |
34 | break; |
35 | case ELF::EM_X86_64: |
36 | switch (Type) { |
37 | #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" |
38 | default: |
39 | break; |
40 | } |
41 | break; |
42 | case ELF::EM_386: |
43 | case ELF::EM_IAMCU: |
44 | switch (Type) { |
45 | #include "llvm/BinaryFormat/ELFRelocs/i386.def" |
46 | default: |
47 | break; |
48 | } |
49 | break; |
50 | case ELF::EM_MIPS: |
51 | switch (Type) { |
52 | #include "llvm/BinaryFormat/ELFRelocs/Mips.def" |
53 | default: |
54 | break; |
55 | } |
56 | break; |
57 | case ELF::EM_AARCH64: |
58 | switch (Type) { |
59 | #include "llvm/BinaryFormat/ELFRelocs/AArch64.def" |
60 | default: |
61 | break; |
62 | } |
63 | break; |
64 | case ELF::EM_ARM: |
65 | switch (Type) { |
66 | #include "llvm/BinaryFormat/ELFRelocs/ARM.def" |
67 | default: |
68 | break; |
69 | } |
70 | break; |
71 | case ELF::EM_ARC_COMPACT: |
72 | case ELF::EM_ARC_COMPACT2: |
73 | switch (Type) { |
74 | #include "llvm/BinaryFormat/ELFRelocs/ARC.def" |
75 | default: |
76 | break; |
77 | } |
78 | break; |
79 | case ELF::EM_AVR: |
80 | switch (Type) { |
81 | #include "llvm/BinaryFormat/ELFRelocs/AVR.def" |
82 | default: |
83 | break; |
84 | } |
85 | break; |
86 | case ELF::EM_HEXAGON: |
87 | switch (Type) { |
88 | #include "llvm/BinaryFormat/ELFRelocs/Hexagon.def" |
89 | default: |
90 | break; |
91 | } |
92 | break; |
93 | case ELF::EM_LANAI: |
94 | switch (Type) { |
95 | #include "llvm/BinaryFormat/ELFRelocs/Lanai.def" |
96 | default: |
97 | break; |
98 | } |
99 | break; |
100 | case ELF::EM_PPC: |
101 | switch (Type) { |
102 | #include "llvm/BinaryFormat/ELFRelocs/PowerPC.def" |
103 | default: |
104 | break; |
105 | } |
106 | break; |
107 | case ELF::EM_PPC64: |
108 | switch (Type) { |
109 | #include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def" |
110 | default: |
111 | break; |
112 | } |
113 | break; |
114 | case ELF::EM_RISCV: |
115 | switch (Type) { |
116 | #include "llvm/BinaryFormat/ELFRelocs/RISCV.def" |
117 | default: |
118 | break; |
119 | } |
120 | break; |
121 | case ELF::EM_S390: |
122 | switch (Type) { |
123 | #include "llvm/BinaryFormat/ELFRelocs/SystemZ.def" |
124 | default: |
125 | break; |
126 | } |
127 | break; |
128 | case ELF::EM_SPARC: |
129 | case ELF::EM_SPARC32PLUS: |
130 | case ELF::EM_SPARCV9: |
131 | switch (Type) { |
132 | #include "llvm/BinaryFormat/ELFRelocs/Sparc.def" |
133 | default: |
134 | break; |
135 | } |
136 | break; |
137 | case ELF::EM_AMDGPU: |
138 | switch (Type) { |
139 | #include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def" |
140 | default: |
141 | break; |
142 | } |
143 | break; |
144 | case ELF::EM_BPF: |
145 | switch (Type) { |
146 | #include "llvm/BinaryFormat/ELFRelocs/BPF.def" |
147 | default: |
148 | break; |
149 | } |
150 | break; |
151 | case ELF::EM_MSP430: |
152 | switch (Type) { |
153 | #include "llvm/BinaryFormat/ELFRelocs/MSP430.def" |
154 | default: |
155 | break; |
156 | } |
157 | break; |
158 | case ELF::EM_VE: |
159 | switch (Type) { |
160 | #include "llvm/BinaryFormat/ELFRelocs/VE.def" |
161 | default: |
162 | break; |
163 | } |
164 | break; |
165 | case ELF::EM_CSKY: |
166 | switch (Type) { |
167 | #include "llvm/BinaryFormat/ELFRelocs/CSKY.def" |
168 | default: |
169 | break; |
170 | } |
171 | break; |
172 | case ELF::EM_LOONGARCH: |
173 | switch (Type) { |
174 | #include "llvm/BinaryFormat/ELFRelocs/LoongArch.def" |
175 | default: |
176 | break; |
177 | } |
178 | break; |
179 | case ELF::EM_XTENSA: |
180 | switch (Type) { |
181 | #include "llvm/BinaryFormat/ELFRelocs/Xtensa.def" |
182 | default: |
183 | break; |
184 | } |
185 | break; |
186 | default: |
187 | break; |
188 | } |
189 | return "Unknown" ; |
190 | } |
191 | |
192 | #undef ELF_RELOC |
193 | |
194 | uint32_t llvm::object::getELFRelativeRelocationType(uint32_t Machine) { |
195 | switch (Machine) { |
196 | case ELF::EM_X86_64: |
197 | return ELF::R_X86_64_RELATIVE; |
198 | case ELF::EM_386: |
199 | case ELF::EM_IAMCU: |
200 | return ELF::R_386_RELATIVE; |
201 | case ELF::EM_MIPS: |
202 | break; |
203 | case ELF::EM_AARCH64: |
204 | return ELF::R_AARCH64_RELATIVE; |
205 | case ELF::EM_ARM: |
206 | return ELF::R_ARM_RELATIVE; |
207 | case ELF::EM_ARC_COMPACT: |
208 | case ELF::EM_ARC_COMPACT2: |
209 | return ELF::R_ARC_RELATIVE; |
210 | case ELF::EM_AVR: |
211 | break; |
212 | case ELF::EM_HEXAGON: |
213 | return ELF::R_HEX_RELATIVE; |
214 | case ELF::EM_LANAI: |
215 | break; |
216 | case ELF::EM_PPC: |
217 | break; |
218 | case ELF::EM_PPC64: |
219 | return ELF::R_PPC64_RELATIVE; |
220 | case ELF::EM_RISCV: |
221 | return ELF::R_RISCV_RELATIVE; |
222 | case ELF::EM_S390: |
223 | return ELF::R_390_RELATIVE; |
224 | case ELF::EM_SPARC: |
225 | case ELF::EM_SPARC32PLUS: |
226 | case ELF::EM_SPARCV9: |
227 | return ELF::R_SPARC_RELATIVE; |
228 | case ELF::EM_CSKY: |
229 | return ELF::R_CKCORE_RELATIVE; |
230 | case ELF::EM_VE: |
231 | return ELF::R_VE_RELATIVE; |
232 | case ELF::EM_AMDGPU: |
233 | break; |
234 | case ELF::EM_BPF: |
235 | break; |
236 | case ELF::EM_LOONGARCH: |
237 | return ELF::R_LARCH_RELATIVE; |
238 | default: |
239 | break; |
240 | } |
241 | return 0; |
242 | } |
243 | |
244 | StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { |
245 | switch (Machine) { |
246 | case ELF::EM_ARM: |
247 | switch (Type) { |
248 | STRINGIFY_ENUM_CASE(ELF, SHT_ARM_EXIDX); |
249 | STRINGIFY_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP); |
250 | STRINGIFY_ENUM_CASE(ELF, SHT_ARM_ATTRIBUTES); |
251 | STRINGIFY_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY); |
252 | STRINGIFY_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION); |
253 | } |
254 | break; |
255 | case ELF::EM_HEXAGON: |
256 | switch (Type) { |
257 | STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); |
258 | STRINGIFY_ENUM_CASE(ELF, SHT_HEXAGON_ATTRIBUTES); |
259 | } |
260 | break; |
261 | case ELF::EM_X86_64: |
262 | switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); } |
263 | break; |
264 | case ELF::EM_MIPS: |
265 | case ELF::EM_MIPS_RS3_LE: |
266 | switch (Type) { |
267 | STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_REGINFO); |
268 | STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_OPTIONS); |
269 | STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_DWARF); |
270 | STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS); |
271 | } |
272 | break; |
273 | case ELF::EM_MSP430: |
274 | switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_MSP430_ATTRIBUTES); } |
275 | break; |
276 | case ELF::EM_RISCV: |
277 | switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_RISCV_ATTRIBUTES); } |
278 | break; |
279 | case ELF::EM_AARCH64: |
280 | switch (Type) { |
281 | STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_AUTH_RELR); |
282 | STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC); |
283 | STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_STATIC); |
284 | } |
285 | default: |
286 | break; |
287 | } |
288 | |
289 | switch (Type) { |
290 | STRINGIFY_ENUM_CASE(ELF, SHT_NULL); |
291 | STRINGIFY_ENUM_CASE(ELF, SHT_PROGBITS); |
292 | STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB); |
293 | STRINGIFY_ENUM_CASE(ELF, SHT_STRTAB); |
294 | STRINGIFY_ENUM_CASE(ELF, SHT_RELA); |
295 | STRINGIFY_ENUM_CASE(ELF, SHT_HASH); |
296 | STRINGIFY_ENUM_CASE(ELF, SHT_DYNAMIC); |
297 | STRINGIFY_ENUM_CASE(ELF, SHT_NOTE); |
298 | STRINGIFY_ENUM_CASE(ELF, SHT_NOBITS); |
299 | STRINGIFY_ENUM_CASE(ELF, SHT_REL); |
300 | STRINGIFY_ENUM_CASE(ELF, SHT_SHLIB); |
301 | STRINGIFY_ENUM_CASE(ELF, SHT_DYNSYM); |
302 | STRINGIFY_ENUM_CASE(ELF, SHT_INIT_ARRAY); |
303 | STRINGIFY_ENUM_CASE(ELF, SHT_FINI_ARRAY); |
304 | STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY); |
305 | STRINGIFY_ENUM_CASE(ELF, SHT_GROUP); |
306 | STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX); |
307 | STRINGIFY_ENUM_CASE(ELF, SHT_RELR); |
308 | STRINGIFY_ENUM_CASE(ELF, SHT_CREL); |
309 | STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL); |
310 | STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA); |
311 | STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR); |
312 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB); |
313 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LINKER_OPTIONS); |
314 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE); |
315 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ADDRSIG); |
316 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_DEPENDENT_LIBRARIES); |
317 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_SYMPART); |
318 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_EHDR); |
319 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_PHDR); |
320 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP); |
321 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_OFFLOADING); |
322 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LTO); |
323 | STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_JT_SIZES) |
324 | STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); |
325 | STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); |
326 | STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); |
327 | STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verneed); |
328 | STRINGIFY_ENUM_CASE(ELF, SHT_GNU_versym); |
329 | default: |
330 | return "Unknown" ; |
331 | } |
332 | } |
333 | |
334 | template <class ELFT> |
335 | std::vector<typename ELFT::Rel> |
336 | ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const { |
337 | // This function decodes the contents of an SHT_RELR packed relocation |
338 | // section. |
339 | // |
340 | // Proposal for adding SHT_RELR sections to generic-abi is here: |
341 | // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg |
342 | // |
343 | // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks |
344 | // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] |
345 | // |
346 | // i.e. start with an address, followed by any number of bitmaps. The address |
347 | // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63 |
348 | // relocations each, at subsequent offsets following the last address entry. |
349 | // |
350 | // The bitmap entries must have 1 in the least significant bit. The assumption |
351 | // here is that an address cannot have 1 in lsb. Odd addresses are not |
352 | // supported. |
353 | // |
354 | // Excluding the least significant bit in the bitmap, each non-zero bit in |
355 | // the bitmap represents a relocation to be applied to a corresponding machine |
356 | // word that follows the base address word. The second least significant bit |
357 | // represents the machine word immediately following the initial address, and |
358 | // each bit that follows represents the next word, in linear order. As such, |
359 | // a single bitmap can encode up to 31 relocations in a 32-bit object, and |
360 | // 63 relocations in a 64-bit object. |
361 | // |
362 | // This encoding has a couple of interesting properties: |
363 | // 1. Looking at any entry, it is clear whether it's an address or a bitmap: |
364 | // even means address, odd means bitmap. |
365 | // 2. Just a simple list of addresses is a valid encoding. |
366 | |
367 | Elf_Rel Rel; |
368 | Rel.r_info = 0; |
369 | Rel.setType(getRelativeRelocationType(), false); |
370 | std::vector<Elf_Rel> Relocs; |
371 | |
372 | // Word type: uint32_t for Elf32, and uint64_t for Elf64. |
373 | using Addr = typename ELFT::uint; |
374 | |
375 | Addr Base = 0; |
376 | for (Elf_Relr R : relrs) { |
377 | typename ELFT::uint Entry = R; |
378 | if ((Entry & 1) == 0) { |
379 | // Even entry: encodes the offset for next relocation. |
380 | Rel.r_offset = Entry; |
381 | Relocs.push_back(Rel); |
382 | // Set base offset for subsequent bitmap entries. |
383 | Base = Entry + sizeof(Addr); |
384 | } else { |
385 | // Odd entry: encodes bitmap for relocations starting at base. |
386 | for (Addr Offset = Base; (Entry >>= 1) != 0; Offset += sizeof(Addr)) |
387 | if ((Entry & 1) != 0) { |
388 | Rel.r_offset = Offset; |
389 | Relocs.push_back(Rel); |
390 | } |
391 | Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(Addr); |
392 | } |
393 | } |
394 | |
395 | return Relocs; |
396 | } |
397 | |
398 | template <class ELFT> |
399 | Expected<uint64_t> |
400 | ELFFile<ELFT>::(ArrayRef<uint8_t> Content) const { |
401 | DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr)); |
402 | Error Err = Error::success(); |
403 | uint64_t Hdr = 0; |
404 | Hdr = Data.getULEB128(offset_ptr: &Hdr, Err: &Err); |
405 | if (Err) |
406 | return Err; |
407 | return Hdr; |
408 | } |
409 | |
410 | template <class ELFT> |
411 | Expected<typename ELFFile<ELFT>::RelsOrRelas> |
412 | ELFFile<ELFT>::decodeCrel(ArrayRef<uint8_t> Content) const { |
413 | std::vector<Elf_Rel> Rels; |
414 | std::vector<Elf_Rela> Relas; |
415 | size_t I = 0; |
416 | bool HasAddend; |
417 | Error Err = object::decodeCrel<ELFT::Is64Bits>( |
418 | Content, |
419 | [&](uint64_t Count, bool HasA) { |
420 | HasAddend = HasA; |
421 | if (HasAddend) |
422 | Relas.resize(Count); |
423 | else |
424 | Rels.resize(Count); |
425 | }, |
426 | [&](Elf_Crel Crel) { |
427 | if (HasAddend) { |
428 | Relas[I].r_offset = Crel.r_offset; |
429 | Relas[I].setSymbolAndType(Crel.r_symidx, Crel.r_type, false); |
430 | Relas[I++].r_addend = Crel.r_addend; |
431 | } else { |
432 | Rels[I].r_offset = Crel.r_offset; |
433 | Rels[I++].setSymbolAndType(Crel.r_symidx, Crel.r_type, false); |
434 | } |
435 | }); |
436 | if (Err) |
437 | return std::move(Err); |
438 | return std::make_pair(std::move(Rels), std::move(Relas)); |
439 | } |
440 | |
441 | template <class ELFT> |
442 | Expected<typename ELFFile<ELFT>::RelsOrRelas> |
443 | ELFFile<ELFT>::crels(const Elf_Shdr &Sec) const { |
444 | Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); |
445 | if (!ContentsOrErr) |
446 | return ContentsOrErr.takeError(); |
447 | return decodeCrel(Content: *ContentsOrErr); |
448 | } |
449 | |
450 | template <class ELFT> |
451 | Expected<std::vector<typename ELFT::Rela>> |
452 | ELFFile<ELFT>::android_relas(const Elf_Shdr &Sec) const { |
453 | // This function reads relocations in Android's packed relocation format, |
454 | // which is based on SLEB128 and delta encoding. |
455 | Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); |
456 | if (!ContentsOrErr) |
457 | return ContentsOrErr.takeError(); |
458 | ArrayRef<uint8_t> Content = *ContentsOrErr; |
459 | if (Content.size() < 4 || Content[0] != 'A' || Content[1] != 'P' || |
460 | Content[2] != 'S' || Content[3] != '2') |
461 | return createError(Err: "invalid packed relocation header" ); |
462 | DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4); |
463 | DataExtractor::Cursor Cur(/*Offset=*/4); |
464 | |
465 | uint64_t NumRelocs = Data.getSLEB128(C&: Cur); |
466 | uint64_t Offset = Data.getSLEB128(C&: Cur); |
467 | uint64_t Addend = 0; |
468 | |
469 | if (!Cur) |
470 | return std::move(Cur.takeError()); |
471 | |
472 | std::vector<Elf_Rela> Relocs; |
473 | Relocs.reserve(NumRelocs); |
474 | while (NumRelocs) { |
475 | uint64_t NumRelocsInGroup = Data.getSLEB128(C&: Cur); |
476 | if (!Cur) |
477 | return std::move(Cur.takeError()); |
478 | if (NumRelocsInGroup > NumRelocs) |
479 | return createError(Err: "relocation group unexpectedly large" ); |
480 | NumRelocs -= NumRelocsInGroup; |
481 | |
482 | uint64_t GroupFlags = Data.getSLEB128(C&: Cur); |
483 | bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG; |
484 | bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG; |
485 | bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG; |
486 | bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG; |
487 | |
488 | uint64_t GroupOffsetDelta; |
489 | if (GroupedByOffsetDelta) |
490 | GroupOffsetDelta = Data.getSLEB128(C&: Cur); |
491 | |
492 | uint64_t GroupRInfo; |
493 | if (GroupedByInfo) |
494 | GroupRInfo = Data.getSLEB128(C&: Cur); |
495 | |
496 | if (GroupedByAddend && GroupHasAddend) |
497 | Addend += Data.getSLEB128(C&: Cur); |
498 | |
499 | if (!GroupHasAddend) |
500 | Addend = 0; |
501 | |
502 | for (uint64_t I = 0; Cur && I != NumRelocsInGroup; ++I) { |
503 | Elf_Rela R; |
504 | Offset += GroupedByOffsetDelta ? GroupOffsetDelta : Data.getSLEB128(C&: Cur); |
505 | R.r_offset = Offset; |
506 | R.r_info = GroupedByInfo ? GroupRInfo : Data.getSLEB128(C&: Cur); |
507 | if (GroupHasAddend && !GroupedByAddend) |
508 | Addend += Data.getSLEB128(C&: Cur); |
509 | R.r_addend = Addend; |
510 | Relocs.push_back(R); |
511 | } |
512 | if (!Cur) |
513 | return std::move(Cur.takeError()); |
514 | } |
515 | |
516 | return Relocs; |
517 | } |
518 | |
519 | template <class ELFT> |
520 | std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch, |
521 | uint64_t Type) const { |
522 | #define DYNAMIC_STRINGIFY_ENUM(tag, value) \ |
523 | case value: \ |
524 | return #tag; |
525 | |
526 | #define DYNAMIC_TAG(n, v) |
527 | switch (Arch) { |
528 | case ELF::EM_AARCH64: |
529 | switch (Type) { |
530 | #define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
531 | #include "llvm/BinaryFormat/DynamicTags.def" |
532 | #undef AARCH64_DYNAMIC_TAG |
533 | } |
534 | break; |
535 | |
536 | case ELF::EM_HEXAGON: |
537 | switch (Type) { |
538 | #define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
539 | #include "llvm/BinaryFormat/DynamicTags.def" |
540 | #undef HEXAGON_DYNAMIC_TAG |
541 | } |
542 | break; |
543 | |
544 | case ELF::EM_MIPS: |
545 | switch (Type) { |
546 | #define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
547 | #include "llvm/BinaryFormat/DynamicTags.def" |
548 | #undef MIPS_DYNAMIC_TAG |
549 | } |
550 | break; |
551 | |
552 | case ELF::EM_PPC: |
553 | switch (Type) { |
554 | #define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
555 | #include "llvm/BinaryFormat/DynamicTags.def" |
556 | #undef PPC_DYNAMIC_TAG |
557 | } |
558 | break; |
559 | |
560 | case ELF::EM_PPC64: |
561 | switch (Type) { |
562 | #define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
563 | #include "llvm/BinaryFormat/DynamicTags.def" |
564 | #undef PPC64_DYNAMIC_TAG |
565 | } |
566 | break; |
567 | |
568 | case ELF::EM_RISCV: |
569 | switch (Type) { |
570 | #define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) |
571 | #include "llvm/BinaryFormat/DynamicTags.def" |
572 | #undef RISCV_DYNAMIC_TAG |
573 | } |
574 | break; |
575 | } |
576 | #undef DYNAMIC_TAG |
577 | switch (Type) { |
578 | // Now handle all dynamic tags except the architecture specific ones |
579 | #define AARCH64_DYNAMIC_TAG(name, value) |
580 | #define MIPS_DYNAMIC_TAG(name, value) |
581 | #define HEXAGON_DYNAMIC_TAG(name, value) |
582 | #define PPC_DYNAMIC_TAG(name, value) |
583 | #define PPC64_DYNAMIC_TAG(name, value) |
584 | #define RISCV_DYNAMIC_TAG(name, value) |
585 | // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. |
586 | #define DYNAMIC_TAG_MARKER(name, value) |
587 | #define DYNAMIC_TAG(name, value) case value: return #name; |
588 | #include "llvm/BinaryFormat/DynamicTags.def" |
589 | #undef DYNAMIC_TAG |
590 | #undef AARCH64_DYNAMIC_TAG |
591 | #undef MIPS_DYNAMIC_TAG |
592 | #undef HEXAGON_DYNAMIC_TAG |
593 | #undef PPC_DYNAMIC_TAG |
594 | #undef PPC64_DYNAMIC_TAG |
595 | #undef RISCV_DYNAMIC_TAG |
596 | #undef DYNAMIC_TAG_MARKER |
597 | #undef DYNAMIC_STRINGIFY_ENUM |
598 | default: |
599 | return "<unknown:>0x" + utohexstr(X: Type, LowerCase: true); |
600 | } |
601 | } |
602 | |
603 | template <class ELFT> |
604 | std::string ELFFile<ELFT>::getDynamicTagAsString(uint64_t Type) const { |
605 | return getDynamicTagAsString(getHeader().e_machine, Type); |
606 | } |
607 | |
608 | template <class ELFT> |
609 | Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { |
610 | ArrayRef<Elf_Dyn> Dyn; |
611 | |
612 | auto = program_headers(); |
613 | if (!ProgramHeadersOrError) |
614 | return ProgramHeadersOrError.takeError(); |
615 | |
616 | for (const Elf_Phdr &Phdr : *ProgramHeadersOrError) { |
617 | if (Phdr.p_type == ELF::PT_DYNAMIC) { |
618 | const uint8_t *DynOffset = base() + Phdr.p_offset; |
619 | if (DynOffset > end()) |
620 | return createError( |
621 | Err: "dynamic section offset past file size: corrupted ELF" ); |
622 | Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(DynOffset), |
623 | Phdr.p_filesz / sizeof(Elf_Dyn)); |
624 | break; |
625 | } |
626 | } |
627 | |
628 | // If we can't find the dynamic section in the program headers, we just fall |
629 | // back on the sections. |
630 | if (Dyn.empty()) { |
631 | auto SectionsOrError = sections(); |
632 | if (!SectionsOrError) |
633 | return SectionsOrError.takeError(); |
634 | |
635 | for (const Elf_Shdr &Sec : *SectionsOrError) { |
636 | if (Sec.sh_type == ELF::SHT_DYNAMIC) { |
637 | Expected<ArrayRef<Elf_Dyn>> DynOrError = |
638 | getSectionContentsAsArray<Elf_Dyn>(Sec); |
639 | if (!DynOrError) |
640 | return DynOrError.takeError(); |
641 | Dyn = *DynOrError; |
642 | break; |
643 | } |
644 | } |
645 | |
646 | if (!Dyn.data()) |
647 | return ArrayRef<Elf_Dyn>(); |
648 | } |
649 | |
650 | if (Dyn.empty()) |
651 | return createError(Err: "invalid empty dynamic section" ); |
652 | |
653 | if (Dyn.back().d_tag != ELF::DT_NULL) |
654 | return createError(Err: "dynamic sections must be DT_NULL terminated" ); |
655 | |
656 | return Dyn; |
657 | } |
658 | |
659 | template <class ELFT> |
660 | Expected<const uint8_t *> |
661 | ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const { |
662 | auto = program_headers(); |
663 | if (!ProgramHeadersOrError) |
664 | return ProgramHeadersOrError.takeError(); |
665 | |
666 | llvm::SmallVector<Elf_Phdr *, 4> LoadSegments; |
667 | |
668 | for (const Elf_Phdr &Phdr : *ProgramHeadersOrError) |
669 | if (Phdr.p_type == ELF::PT_LOAD) |
670 | LoadSegments.push_back(const_cast<Elf_Phdr *>(&Phdr)); |
671 | |
672 | auto SortPred = [](const Elf_Phdr_Impl<ELFT> *A, |
673 | const Elf_Phdr_Impl<ELFT> *B) { |
674 | return A->p_vaddr < B->p_vaddr; |
675 | }; |
676 | if (!llvm::is_sorted(LoadSegments, SortPred)) { |
677 | if (Error E = |
678 | WarnHandler("loadable segments are unsorted by virtual address" )) |
679 | return std::move(E); |
680 | llvm::stable_sort(LoadSegments, SortPred); |
681 | } |
682 | |
683 | const Elf_Phdr *const *I = llvm::upper_bound( |
684 | LoadSegments, VAddr, [](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) { |
685 | return VAddr < Phdr->p_vaddr; |
686 | }); |
687 | |
688 | if (I == LoadSegments.begin()) |
689 | return createError(Err: "virtual address is not in any segment: 0x" + |
690 | Twine::utohexstr(Val: VAddr)); |
691 | --I; |
692 | const Elf_Phdr &Phdr = **I; |
693 | uint64_t Delta = VAddr - Phdr.p_vaddr; |
694 | if (Delta >= Phdr.p_filesz) |
695 | return createError(Err: "virtual address is not in any segment: 0x" + |
696 | Twine::utohexstr(Val: VAddr)); |
697 | |
698 | uint64_t Offset = Phdr.p_offset + Delta; |
699 | if (Offset >= getBufSize()) |
700 | return createError("can't map virtual address 0x" + |
701 | Twine::utohexstr(Val: VAddr) + " to the segment with index " + |
702 | Twine(&Phdr - (*ProgramHeadersOrError).data() + 1) + |
703 | ": the segment ends at 0x" + |
704 | Twine::utohexstr(Val: Phdr.p_offset + Phdr.p_filesz) + |
705 | ", which is greater than the file size (0x" + |
706 | Twine::utohexstr(Val: getBufSize()) + ")" ); |
707 | |
708 | return base() + Offset; |
709 | } |
710 | |
711 | // Helper to extract and decode the next ULEB128 value as unsigned int. |
712 | // Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the unsigned |
713 | // int limit. |
714 | // Also returns zero if ULEBSizeErr is already in an error state. |
715 | // ULEBSizeErr is an out variable if an error occurs. |
716 | template <typename IntTy, std::enable_if_t<std::is_unsigned_v<IntTy>, int> = 0> |
717 | static IntTy (DataExtractor &Data, DataExtractor::Cursor &Cur, |
718 | Error &ULEBSizeErr) { |
719 | // Bail out and do not extract data if ULEBSizeErr is already set. |
720 | if (ULEBSizeErr) |
721 | return 0; |
722 | uint64_t Offset = Cur.tell(); |
723 | uint64_t Value = Data.getULEB128(C&: Cur); |
724 | if (Value > std::numeric_limits<IntTy>::max()) { |
725 | ULEBSizeErr = createError(Err: "ULEB128 value at offset 0x" + |
726 | Twine::utohexstr(Val: Offset) + " exceeds UINT" + |
727 | Twine(std::numeric_limits<IntTy>::digits) + |
728 | "_MAX (0x" + Twine::utohexstr(Val: Value) + ")" ); |
729 | return 0; |
730 | } |
731 | return static_cast<IntTy>(Value); |
732 | } |
733 | |
734 | template <typename ELFT> |
735 | static Expected<std::vector<BBAddrMap>> |
736 | decodeBBAddrMapImpl(const ELFFile<ELFT> &EF, |
737 | const typename ELFFile<ELFT>::Elf_Shdr &Sec, |
738 | const typename ELFFile<ELFT>::Elf_Shdr *RelaSec, |
739 | std::vector<PGOAnalysisMap> *PGOAnalyses) { |
740 | bool IsRelocatable = EF.getHeader().e_type == ELF::ET_REL; |
741 | |
742 | // This DenseMap maps the offset of each function (the location of the |
743 | // reference to the function in the SHT_LLVM_BB_ADDR_MAP section) to the |
744 | // addend (the location of the function in the text section). |
745 | llvm::DenseMap<uint64_t, uint64_t> FunctionOffsetTranslations; |
746 | if (IsRelocatable && RelaSec) { |
747 | assert(RelaSec && |
748 | "Can't read a SHT_LLVM_BB_ADDR_MAP section in a relocatable " |
749 | "object file without providing a relocation section." ); |
750 | if (RelaSec->sh_type == ELF::SHT_CREL) { |
751 | Expected<typename ELFFile<ELFT>::RelsOrRelas> Relas = EF.crels(*RelaSec); |
752 | if (!Relas) |
753 | return createError("unable to read CREL relocations for section " + |
754 | describe(EF, Sec) + ": " + |
755 | toString(Relas.takeError())); |
756 | for (typename ELFFile<ELFT>::Elf_Rela Rela : std::get<1>(*Relas)) { |
757 | FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend; |
758 | } |
759 | } else { |
760 | Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas = |
761 | EF.relas(*RelaSec); |
762 | if (!Relas) |
763 | return createError("unable to read relocations for section " + |
764 | describe(EF, Sec) + ": " + |
765 | toString(Relas.takeError())); |
766 | for (typename ELFFile<ELFT>::Elf_Rela Rela : *Relas) |
767 | FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend; |
768 | } |
769 | } |
770 | auto GetAddressForRelocation = |
771 | [&](unsigned RelocationOffsetInSection) -> Expected<unsigned> { |
772 | auto FOTIterator = |
773 | FunctionOffsetTranslations.find(Val: RelocationOffsetInSection); |
774 | if (FOTIterator == FunctionOffsetTranslations.end()) { |
775 | return createError("failed to get relocation data for offset: " + |
776 | Twine::utohexstr(Val: RelocationOffsetInSection) + |
777 | " in section " + describe(EF, Sec)); |
778 | } |
779 | return FOTIterator->second; |
780 | }; |
781 | Expected<ArrayRef<uint8_t>> ContentsOrErr = EF.getSectionContents(Sec); |
782 | if (!ContentsOrErr) |
783 | return ContentsOrErr.takeError(); |
784 | ArrayRef<uint8_t> Content = *ContentsOrErr; |
785 | |
786 | // Decompress the section if needed. |
787 | std::unique_ptr<uint8_t[]> DecompressedContent; |
788 | if (Sec.sh_flags & llvm::ELF::SHF_COMPRESSED) { |
789 | Expected<StringRef> SectionNameOrErr = EF.getSectionName(Sec); |
790 | if (!SectionNameOrErr) |
791 | return SectionNameOrErr.takeError(); |
792 | auto DecompressorOrErr = |
793 | Decompressor::create(Name: *SectionNameOrErr, Data: toStringRef(Input: *ContentsOrErr), |
794 | IsLE: EF.isLE(), Is64Bit: ELFT::Is64Bits); |
795 | if (!DecompressorOrErr) |
796 | return DecompressorOrErr.takeError(); |
797 | size_t DecompressedSize = DecompressorOrErr->getDecompressedSize(); |
798 | DecompressedContent = std::make_unique<uint8_t[]>(num: DecompressedSize); |
799 | MutableArrayRef<uint8_t> DecompressedContentRef(DecompressedContent.get(), |
800 | DecompressedSize); |
801 | if (Error Err = DecompressorOrErr->decompress(DecompressedContentRef)) |
802 | return std::move(Err); |
803 | Content = DecompressedContentRef; |
804 | } |
805 | |
806 | DataExtractor Data(Content, EF.isLE(), ELFT::Is64Bits ? 8 : 4); |
807 | std::vector<BBAddrMap> FunctionEntries; |
808 | |
809 | DataExtractor::Cursor Cur(0); |
810 | Error ULEBSizeErr = Error::success(); |
811 | Error MetadataDecodeErr = Error::success(); |
812 | |
813 | // Helper lampda to extract the (possiblly relocatable) address stored at Cur. |
814 | auto = [&]() -> Expected<typename ELFFile<ELFT>::uintX_t> { |
815 | uint64_t RelocationOffsetInSection = Cur.tell(); |
816 | auto Address = |
817 | static_cast<typename ELFFile<ELFT>::uintX_t>(Data.getAddress(C&: Cur)); |
818 | if (!Cur) |
819 | return Cur.takeError(); |
820 | if (!IsRelocatable) |
821 | return Address; |
822 | assert(Address == 0); |
823 | Expected<unsigned> AddressOrErr = |
824 | GetAddressForRelocation(RelocationOffsetInSection); |
825 | if (!AddressOrErr) |
826 | return AddressOrErr.takeError(); |
827 | return *AddressOrErr; |
828 | }; |
829 | |
830 | uint8_t Version = 0; |
831 | uint8_t Feature = 0; |
832 | BBAddrMap::Features FeatEnable{}; |
833 | while (!ULEBSizeErr && !MetadataDecodeErr && Cur && |
834 | Cur.tell() < Content.size()) { |
835 | Version = Data.getU8(C&: Cur); |
836 | if (!Cur) |
837 | break; |
838 | if (Version < 2 || Version > 3) |
839 | return createError(Err: "unsupported SHT_LLVM_BB_ADDR_MAP version: " + |
840 | Twine(static_cast<int>(Version))); |
841 | Feature = Data.getU8(C&: Cur); // Feature byte |
842 | if (!Cur) |
843 | break; |
844 | auto FeatEnableOrErr = BBAddrMap::Features::decode(Val: Feature); |
845 | if (!FeatEnableOrErr) |
846 | return FeatEnableOrErr.takeError(); |
847 | FeatEnable = *FeatEnableOrErr; |
848 | if (FeatEnable.CallsiteOffsets && Version < 3) |
849 | return createError(Err: "version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when " |
850 | "callsite offsets feature is enabled: version = " + |
851 | Twine(static_cast<int>(Version)) + |
852 | " feature = " + Twine(static_cast<int>(Feature))); |
853 | uint32_t NumBlocksInBBRange = 0; |
854 | uint32_t NumBBRanges = 1; |
855 | typename ELFFile<ELFT>::uintX_t RangeBaseAddress = 0; |
856 | if (FeatEnable.MultiBBRange) { |
857 | NumBBRanges = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
858 | if (!Cur || ULEBSizeErr) |
859 | break; |
860 | if (!NumBBRanges) |
861 | return createError("invalid zero number of BB ranges at offset " + |
862 | Twine::utohexstr(Val: Cur.tell()) + " in " + |
863 | describe(EF, Sec)); |
864 | } else { |
865 | auto AddressOrErr = ExtractAddress(); |
866 | if (!AddressOrErr) |
867 | return AddressOrErr.takeError(); |
868 | RangeBaseAddress = *AddressOrErr; |
869 | NumBlocksInBBRange = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
870 | } |
871 | std::vector<BBAddrMap::BBRangeEntry> BBRangeEntries; |
872 | uint32_t TotalNumBlocks = 0; |
873 | for (uint32_t BBRangeIndex = 0; BBRangeIndex < NumBBRanges; |
874 | ++BBRangeIndex) { |
875 | uint32_t PrevBBEndOffset = 0; |
876 | if (FeatEnable.MultiBBRange) { |
877 | auto AddressOrErr = ExtractAddress(); |
878 | if (!AddressOrErr) |
879 | return AddressOrErr.takeError(); |
880 | RangeBaseAddress = *AddressOrErr; |
881 | NumBlocksInBBRange = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
882 | } |
883 | std::vector<BBAddrMap::BBEntry> BBEntries; |
884 | if (!FeatEnable.OmitBBEntries) { |
885 | for (uint32_t BlockIndex = 0; !MetadataDecodeErr && !ULEBSizeErr && |
886 | Cur && (BlockIndex < NumBlocksInBBRange); |
887 | ++BlockIndex) { |
888 | uint32_t ID = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
889 | uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
890 | // Read the callsite offsets. |
891 | uint32_t LastCallsiteOffset = 0; |
892 | SmallVector<uint32_t, 1> CallsiteOffsets; |
893 | if (FeatEnable.CallsiteOffsets) { |
894 | uint32_t NumCallsites = |
895 | readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
896 | CallsiteOffsets.reserve(N: NumCallsites); |
897 | for (uint32_t CallsiteIndex = 0; |
898 | !ULEBSizeErr && Cur && (CallsiteIndex < NumCallsites); |
899 | ++CallsiteIndex) { |
900 | LastCallsiteOffset += |
901 | readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
902 | CallsiteOffsets.push_back(Elt: LastCallsiteOffset); |
903 | } |
904 | } |
905 | uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr) + |
906 | LastCallsiteOffset; |
907 | uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
908 | Expected<BBAddrMap::BBEntry::Metadata> MetadataOrErr = |
909 | BBAddrMap::BBEntry::Metadata::decode(V: MD); |
910 | if (!MetadataOrErr) { |
911 | MetadataDecodeErr = MetadataOrErr.takeError(); |
912 | break; |
913 | } |
914 | BBEntries.push_back(x: {ID, Offset + PrevBBEndOffset, Size, |
915 | *MetadataOrErr, CallsiteOffsets}); |
916 | PrevBBEndOffset += Offset + Size; |
917 | } |
918 | TotalNumBlocks += BBEntries.size(); |
919 | } |
920 | BBRangeEntries.push_back({RangeBaseAddress, std::move(BBEntries)}); |
921 | } |
922 | FunctionEntries.push_back(x: {.BBRanges: std::move(BBRangeEntries)}); |
923 | |
924 | if (PGOAnalyses || FeatEnable.hasPGOAnalysis()) { |
925 | // Function entry count |
926 | uint64_t FuncEntryCount = |
927 | FeatEnable.FuncEntryCount |
928 | ? readULEB128As<uint64_t>(Data, Cur, ULEBSizeErr) |
929 | : 0; |
930 | |
931 | std::vector<PGOAnalysisMap::PGOBBEntry> PGOBBEntries; |
932 | for (uint32_t BlockIndex = 0; |
933 | FeatEnable.hasPGOAnalysisBBData() && !MetadataDecodeErr && |
934 | !ULEBSizeErr && Cur && (BlockIndex < TotalNumBlocks); |
935 | ++BlockIndex) { |
936 | // Block frequency |
937 | uint64_t BBF = FeatEnable.BBFreq |
938 | ? readULEB128As<uint64_t>(Data, Cur, ULEBSizeErr) |
939 | : 0; |
940 | |
941 | // Branch probability |
942 | llvm::SmallVector<PGOAnalysisMap::PGOBBEntry::SuccessorEntry, 2> |
943 | Successors; |
944 | if (FeatEnable.BrProb) { |
945 | auto SuccCount = readULEB128As<uint64_t>(Data, Cur, ULEBSizeErr); |
946 | for (uint64_t I = 0; I < SuccCount; ++I) { |
947 | uint32_t BBID = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
948 | uint32_t BrProb = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr); |
949 | if (PGOAnalyses) |
950 | Successors.push_back(Elt: {.ID: BBID, .Prob: BranchProbability::getRaw(N: BrProb)}); |
951 | } |
952 | } |
953 | |
954 | if (PGOAnalyses) |
955 | PGOBBEntries.push_back(x: {.BlockFreq: BlockFrequency(BBF), .Successors: std::move(Successors)}); |
956 | } |
957 | |
958 | if (PGOAnalyses) |
959 | PGOAnalyses->push_back( |
960 | x: {.FuncEntryCount: FuncEntryCount, .BBEntries: std::move(PGOBBEntries), .FeatEnable: FeatEnable}); |
961 | } |
962 | } |
963 | // Either Cur is in the error state, or we have an error in ULEBSizeErr or |
964 | // MetadataDecodeErr (but not both), but we join all errors here to be safe. |
965 | if (!Cur || ULEBSizeErr || MetadataDecodeErr) |
966 | return joinErrors(E1: joinErrors(E1: Cur.takeError(), E2: std::move(ULEBSizeErr)), |
967 | E2: std::move(MetadataDecodeErr)); |
968 | return FunctionEntries; |
969 | } |
970 | |
971 | template <class ELFT> |
972 | Expected<std::vector<BBAddrMap>> |
973 | ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec, const Elf_Shdr *RelaSec, |
974 | std::vector<PGOAnalysisMap> *PGOAnalyses) const { |
975 | size_t OriginalPGOSize = PGOAnalyses ? PGOAnalyses->size() : 0; |
976 | auto AddrMapsOrErr = decodeBBAddrMapImpl(*this, Sec, RelaSec, PGOAnalyses); |
977 | // remove new analyses when an error occurs |
978 | if (!AddrMapsOrErr && PGOAnalyses) |
979 | PGOAnalyses->resize(new_size: OriginalPGOSize); |
980 | return std::move(AddrMapsOrErr); |
981 | } |
982 | |
983 | template <class ELFT> |
984 | Expected< |
985 | MapVector<const typename ELFT::Shdr *, const typename ELFT::Shdr *>> |
986 | ELFFile<ELFT>::getSectionAndRelocations( |
987 | std::function<Expected<bool>(const Elf_Shdr &)> IsMatch) const { |
988 | MapVector<const Elf_Shdr *, const Elf_Shdr *> SecToRelocMap; |
989 | Error Errors = Error::success(); |
990 | for (const Elf_Shdr &Sec : cantFail(this->sections())) { |
991 | Expected<bool> DoesSectionMatch = IsMatch(Sec); |
992 | if (!DoesSectionMatch) { |
993 | Errors = joinErrors(E1: std::move(Errors), E2: DoesSectionMatch.takeError()); |
994 | continue; |
995 | } |
996 | if (*DoesSectionMatch) { |
997 | if (SecToRelocMap.try_emplace(&Sec).second) |
998 | continue; |
999 | } |
1000 | |
1001 | if (Sec.sh_type != ELF::SHT_RELA && Sec.sh_type != ELF::SHT_REL && |
1002 | Sec.sh_type != ELF::SHT_CREL) |
1003 | continue; |
1004 | |
1005 | Expected<const Elf_Shdr *> RelSecOrErr = this->getSection(Sec.sh_info); |
1006 | if (!RelSecOrErr) { |
1007 | Errors = joinErrors(std::move(Errors), |
1008 | createError(describe(*this, Sec) + |
1009 | ": failed to get a relocated section: " + |
1010 | toString(RelSecOrErr.takeError()))); |
1011 | continue; |
1012 | } |
1013 | const Elf_Shdr *ContentsSec = *RelSecOrErr; |
1014 | Expected<bool> DoesRelTargetMatch = IsMatch(*ContentsSec); |
1015 | if (!DoesRelTargetMatch) { |
1016 | Errors = joinErrors(E1: std::move(Errors), E2: DoesRelTargetMatch.takeError()); |
1017 | continue; |
1018 | } |
1019 | if (*DoesRelTargetMatch) |
1020 | SecToRelocMap[ContentsSec] = &Sec; |
1021 | } |
1022 | if(Errors) |
1023 | return std::move(Errors); |
1024 | return SecToRelocMap; |
1025 | } |
1026 | |
1027 | template class LLVM_EXPORT_TEMPLATE llvm::object::ELFFile<ELF32LE>; |
1028 | template class LLVM_EXPORT_TEMPLATE llvm::object::ELFFile<ELF32BE>; |
1029 | template class LLVM_EXPORT_TEMPLATE llvm::object::ELFFile<ELF64LE>; |
1030 | template class LLVM_EXPORT_TEMPLATE llvm::object::ELFFile<ELF64BE>; |
1031 | |