1 | //===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===// |
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 | /// \file |
10 | /// This file declares classes for handling the YAML representation |
11 | /// of ELF. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_OBJECTYAML_ELFYAML_H |
16 | #define LLVM_OBJECTYAML_ELFYAML_H |
17 | |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/BinaryFormat/ELF.h" |
20 | #include "llvm/Object/ELFTypes.h" |
21 | #include "llvm/ObjectYAML/DWARFYAML.h" |
22 | #include "llvm/ObjectYAML/YAML.h" |
23 | #include "llvm/Support/YAMLTraits.h" |
24 | #include <cstdint> |
25 | #include <memory> |
26 | #include <optional> |
27 | #include <vector> |
28 | |
29 | namespace llvm { |
30 | namespace ELFYAML { |
31 | |
32 | StringRef dropUniqueSuffix(StringRef S); |
33 | std::string appendUniqueSuffix(StringRef Name, const Twine& Msg); |
34 | |
35 | // These types are invariant across 32/64-bit ELF, so for simplicity just |
36 | // directly give them their exact sizes. We don't need to worry about |
37 | // endianness because these are just the types in the YAMLIO structures, |
38 | // and are appropriately converted to the necessary endianness when |
39 | // reading/generating binary object files. |
40 | // The naming of these types is intended to be ELF_PREFIX, where PREFIX is |
41 | // the common prefix of the respective constants. E.g. ELF_EM corresponds |
42 | // to the `e_machine` constants, like `EM_X86_64`. |
43 | // In the future, these would probably be better suited by C++11 enum |
44 | // class's with appropriate fixed underlying type. |
45 | LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) |
46 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT) |
47 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) |
48 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) |
49 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) |
50 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) |
51 | // Just use 64, since it can hold 32-bit values too. |
52 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) |
53 | // Just use 64, since it can hold 32-bit values too. |
54 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_DYNTAG) |
55 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF) |
56 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) |
57 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) |
58 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ) |
59 | // Just use 64, since it can hold 32-bit values too. |
60 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) |
61 | LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_SHN) |
62 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB) |
63 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) |
64 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_NT) |
65 | |
66 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) |
67 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) |
68 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) |
69 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) |
70 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) |
71 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) |
72 | |
73 | LLVM_YAML_STRONG_TYPEDEF(StringRef, YAMLFlowString) |
74 | LLVM_YAML_STRONG_TYPEDEF(int64_t, YAMLIntUInt) |
75 | |
76 | template <class ELFT> |
77 | unsigned getDefaultShEntSize(unsigned EMachine, ELF_SHT SecType, |
78 | StringRef SecName) { |
79 | if (EMachine == ELF::EM_MIPS && SecType == ELF::SHT_MIPS_ABIFLAGS) |
80 | return sizeof(object::Elf_Mips_ABIFlags<ELFT>); |
81 | |
82 | switch (SecType) { |
83 | case ELF::SHT_SYMTAB: |
84 | case ELF::SHT_DYNSYM: |
85 | return sizeof(typename ELFT::Sym); |
86 | case ELF::SHT_GROUP: |
87 | return sizeof(typename ELFT::Word); |
88 | case ELF::SHT_REL: |
89 | return sizeof(typename ELFT::Rel); |
90 | case ELF::SHT_RELA: |
91 | return sizeof(typename ELFT::Rela); |
92 | case ELF::SHT_RELR: |
93 | return sizeof(typename ELFT::Relr); |
94 | case ELF::SHT_DYNAMIC: |
95 | return sizeof(typename ELFT::Dyn); |
96 | case ELF::SHT_HASH: |
97 | return sizeof(typename ELFT::Word); |
98 | case ELF::SHT_SYMTAB_SHNDX: |
99 | return sizeof(typename ELFT::Word); |
100 | case ELF::SHT_GNU_versym: |
101 | return sizeof(typename ELFT::Half); |
102 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: |
103 | return sizeof(object::Elf_CGProfile_Impl<ELFT>); |
104 | default: |
105 | if (SecName == ".debug_str" ) |
106 | return 1; |
107 | return 0; |
108 | } |
109 | } |
110 | |
111 | // For now, hardcode 64 bits everywhere that 32 or 64 would be needed |
112 | // since 64-bit can hold 32-bit values too. |
113 | struct { |
114 | ELF_ELFCLASS ; |
115 | ELF_ELFDATA ; |
116 | ELF_ELFOSABI ; |
117 | llvm::yaml::Hex8 ; |
118 | ELF_ET ; |
119 | std::optional<ELF_EM> ; |
120 | ELF_EF ; |
121 | llvm::yaml::Hex64 ; |
122 | std::optional<StringRef> ; |
123 | |
124 | std::optional<llvm::yaml::Hex64> ; |
125 | std::optional<llvm::yaml::Hex16> ; |
126 | std::optional<llvm::yaml::Hex16> ; |
127 | std::optional<llvm::yaml::Hex16> ; |
128 | std::optional<llvm::yaml::Hex64> ; |
129 | std::optional<llvm::yaml::Hex16> ; |
130 | std::optional<llvm::yaml::Hex16> ; |
131 | }; |
132 | |
133 | struct { |
134 | StringRef ; |
135 | }; |
136 | |
137 | struct Symbol { |
138 | StringRef Name; |
139 | ELF_STT Type; |
140 | std::optional<StringRef> Section; |
141 | std::optional<ELF_SHN> Index; |
142 | ELF_STB Binding; |
143 | std::optional<llvm::yaml::Hex64> Value; |
144 | std::optional<llvm::yaml::Hex64> Size; |
145 | std::optional<uint8_t> Other; |
146 | |
147 | std::optional<uint32_t> StName; |
148 | }; |
149 | |
150 | struct SectionOrType { |
151 | StringRef sectionNameOrType; |
152 | }; |
153 | |
154 | struct DynamicEntry { |
155 | ELF_DYNTAG Tag; |
156 | llvm::yaml::Hex64 Val; |
157 | }; |
158 | |
159 | struct BBAddrMapEntry { |
160 | struct BBEntry { |
161 | uint32_t ID; |
162 | llvm::yaml::Hex64 AddressOffset; |
163 | llvm::yaml::Hex64 Size; |
164 | llvm::yaml::Hex64 Metadata; |
165 | std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets; |
166 | }; |
167 | uint8_t Version; |
168 | llvm::yaml::Hex8 Feature; |
169 | |
170 | struct BBRangeEntry { |
171 | llvm::yaml::Hex64 BaseAddress; |
172 | std::optional<uint64_t> NumBlocks; |
173 | std::optional<std::vector<BBEntry>> BBEntries; |
174 | }; |
175 | |
176 | std::optional<uint64_t> NumBBRanges; |
177 | std::optional<std::vector<BBRangeEntry>> BBRanges; |
178 | |
179 | llvm::yaml::Hex64 getFunctionAddress() const { |
180 | if (!BBRanges || BBRanges->empty()) |
181 | return 0; |
182 | return BBRanges->front().BaseAddress; |
183 | } |
184 | |
185 | // Returns if any BB entries have non-empty callsite offsets. |
186 | bool hasAnyCallsiteOffsets() const { |
187 | if (!BBRanges) |
188 | return false; |
189 | for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *BBRanges) { |
190 | if (!BBR.BBEntries) |
191 | continue; |
192 | for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) |
193 | if (BBE.CallsiteOffsets && !BBE.CallsiteOffsets->empty()) |
194 | return true; |
195 | } |
196 | return false; |
197 | } |
198 | }; |
199 | |
200 | struct PGOAnalysisMapEntry { |
201 | struct PGOBBEntry { |
202 | struct SuccessorEntry { |
203 | uint32_t ID; |
204 | llvm::yaml::Hex32 BrProb; |
205 | }; |
206 | std::optional<uint64_t> BBFreq; |
207 | std::optional<std::vector<SuccessorEntry>> Successors; |
208 | }; |
209 | std::optional<uint64_t> FuncEntryCount; |
210 | std::optional<std::vector<PGOBBEntry>> PGOBBEntries; |
211 | }; |
212 | |
213 | struct StackSizeEntry { |
214 | llvm::yaml::Hex64 Address; |
215 | llvm::yaml::Hex64 Size; |
216 | }; |
217 | |
218 | struct NoteEntry { |
219 | StringRef Name; |
220 | yaml::BinaryRef Desc; |
221 | ELF_NT Type; |
222 | }; |
223 | |
224 | struct Chunk { |
225 | enum class ChunkKind { |
226 | Dynamic, |
227 | Group, |
228 | RawContent, |
229 | Relocation, |
230 | Relr, |
231 | NoBits, |
232 | Note, |
233 | Hash, |
234 | GnuHash, |
235 | Verdef, |
236 | Verneed, |
237 | StackSizes, |
238 | SymtabShndxSection, |
239 | Symver, |
240 | ARMIndexTable, |
241 | MipsABIFlags, |
242 | Addrsig, |
243 | LinkerOptions, |
244 | DependentLibraries, |
245 | CallGraphProfile, |
246 | BBAddrMap, |
247 | |
248 | // Special chunks. |
249 | SpecialChunksStart, |
250 | Fill = SpecialChunksStart, |
251 | , |
252 | }; |
253 | |
254 | ChunkKind Kind; |
255 | StringRef Name; |
256 | std::optional<llvm::yaml::Hex64> Offset; |
257 | |
258 | // Usually chunks are not created implicitly, but rather loaded from YAML. |
259 | // This flag is used to signal whether this is the case or not. |
260 | bool IsImplicit; |
261 | |
262 | Chunk(ChunkKind K, bool Implicit) : Kind(K), IsImplicit(Implicit) {} |
263 | virtual ~Chunk(); |
264 | }; |
265 | |
266 | struct Section : public Chunk { |
267 | ELF_SHT Type; |
268 | std::optional<ELF_SHF> Flags; |
269 | std::optional<llvm::yaml::Hex64> Address; |
270 | std::optional<StringRef> Link; |
271 | llvm::yaml::Hex64 AddressAlign; |
272 | std::optional<llvm::yaml::Hex64> EntSize; |
273 | |
274 | std::optional<yaml::BinaryRef> Content; |
275 | std::optional<llvm::yaml::Hex64> Size; |
276 | |
277 | // Holds the original section index. |
278 | unsigned OriginalSecNdx; |
279 | |
280 | Section(ChunkKind Kind, bool IsImplicit = false) : Chunk(Kind, IsImplicit) {} |
281 | |
282 | static bool classof(const Chunk *S) { |
283 | return S->Kind < ChunkKind::SpecialChunksStart; |
284 | } |
285 | |
286 | // Some derived sections might have their own special entries. This method |
287 | // returns a vector of <entry name, is used> pairs. It is used for section |
288 | // validation. |
289 | virtual std::vector<std::pair<StringRef, bool>> getEntries() const { |
290 | return {}; |
291 | }; |
292 | |
293 | // The following members are used to override section fields which is |
294 | // useful for creating invalid objects. |
295 | |
296 | // This can be used to override the sh_addralign field. |
297 | std::optional<llvm::yaml::Hex64> ShAddrAlign; |
298 | |
299 | // This can be used to override the offset stored in the sh_name field. |
300 | // It does not affect the name stored in the string table. |
301 | std::optional<llvm::yaml::Hex64> ShName; |
302 | |
303 | // This can be used to override the sh_offset field. It does not place the |
304 | // section data at the offset specified. |
305 | std::optional<llvm::yaml::Hex64> ShOffset; |
306 | |
307 | // This can be used to override the sh_size field. It does not affect the |
308 | // content written. |
309 | std::optional<llvm::yaml::Hex64> ShSize; |
310 | |
311 | // This can be used to override the sh_flags field. |
312 | std::optional<llvm::yaml::Hex64> ShFlags; |
313 | |
314 | // This can be used to override the sh_type field. It is useful when we |
315 | // want to use specific YAML keys for a section of a particular type to |
316 | // describe the content, but still want to have a different final type |
317 | // for the section. |
318 | std::optional<ELF_SHT> ShType; |
319 | }; |
320 | |
321 | // Fill is a block of data which is placed outside of sections. It is |
322 | // not present in the sections header table, but it might affect the output file |
323 | // size and program headers produced. |
324 | struct Fill : Chunk { |
325 | std::optional<yaml::BinaryRef> Pattern; |
326 | llvm::yaml::Hex64 Size; |
327 | |
328 | Fill() : Chunk(ChunkKind::Fill, /*Implicit=*/false) {} |
329 | |
330 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; } |
331 | }; |
332 | |
333 | struct : Chunk { |
334 | (bool IsImplicit) |
335 | : Chunk(ChunkKind::SectionHeaderTable, IsImplicit) {} |
336 | |
337 | static bool (const Chunk *S) { |
338 | return S->Kind == ChunkKind::SectionHeaderTable; |
339 | } |
340 | |
341 | std::optional<std::vector<SectionHeader>> ; |
342 | std::optional<std::vector<SectionHeader>> ; |
343 | std::optional<bool> ; |
344 | |
345 | size_t (size_t SectionsNum) const { |
346 | if (IsImplicit || isDefault()) |
347 | return SectionsNum; |
348 | if (NoHeaders) |
349 | return (*NoHeaders) ? 0 : SectionsNum; |
350 | return (Sections ? Sections->size() : 0) + /*Null section*/ 1; |
351 | } |
352 | |
353 | bool () const { return !Sections && !Excluded && !NoHeaders; } |
354 | |
355 | static constexpr StringRef = "SectionHeaderTable" ; |
356 | }; |
357 | |
358 | struct BBAddrMapSection : Section { |
359 | std::optional<std::vector<BBAddrMapEntry>> Entries; |
360 | std::optional<std::vector<PGOAnalysisMapEntry>> PGOAnalyses; |
361 | |
362 | BBAddrMapSection() : Section(ChunkKind::BBAddrMap) {} |
363 | |
364 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
365 | return {{"Entries" , Entries.has_value()}}; |
366 | }; |
367 | |
368 | static bool classof(const Chunk *S) { |
369 | return S->Kind == ChunkKind::BBAddrMap; |
370 | } |
371 | }; |
372 | |
373 | struct StackSizesSection : Section { |
374 | std::optional<std::vector<StackSizeEntry>> Entries; |
375 | |
376 | StackSizesSection() : Section(ChunkKind::StackSizes) {} |
377 | |
378 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
379 | return {{"Entries" , Entries.has_value()}}; |
380 | }; |
381 | |
382 | static bool classof(const Chunk *S) { |
383 | return S->Kind == ChunkKind::StackSizes; |
384 | } |
385 | |
386 | static bool nameMatches(StringRef Name) { |
387 | return Name == ".stack_sizes" ; |
388 | } |
389 | }; |
390 | |
391 | struct DynamicSection : Section { |
392 | std::optional<std::vector<DynamicEntry>> Entries; |
393 | |
394 | DynamicSection() : Section(ChunkKind::Dynamic) {} |
395 | |
396 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
397 | return {{"Entries" , Entries.has_value()}}; |
398 | }; |
399 | |
400 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Dynamic; } |
401 | }; |
402 | |
403 | struct RawContentSection : Section { |
404 | std::optional<llvm::yaml::Hex64> Info; |
405 | |
406 | RawContentSection() : Section(ChunkKind::RawContent) {} |
407 | |
408 | static bool classof(const Chunk *S) { |
409 | return S->Kind == ChunkKind::RawContent; |
410 | } |
411 | |
412 | // Is used when a content is read as an array of bytes. |
413 | std::optional<std::vector<uint8_t>> ContentBuf; |
414 | }; |
415 | |
416 | struct NoBitsSection : Section { |
417 | NoBitsSection() : Section(ChunkKind::NoBits) {} |
418 | |
419 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::NoBits; } |
420 | }; |
421 | |
422 | struct NoteSection : Section { |
423 | std::optional<std::vector<ELFYAML::NoteEntry>> Notes; |
424 | |
425 | NoteSection() : Section(ChunkKind::Note) {} |
426 | |
427 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
428 | return {{"Notes" , Notes.has_value()}}; |
429 | }; |
430 | |
431 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Note; } |
432 | }; |
433 | |
434 | struct HashSection : Section { |
435 | std::optional<std::vector<uint32_t>> Bucket; |
436 | std::optional<std::vector<uint32_t>> Chain; |
437 | |
438 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
439 | return {{"Bucket" , Bucket.has_value()}, {"Chain" , Chain.has_value()}}; |
440 | }; |
441 | |
442 | // The following members are used to override section fields. |
443 | // This is useful for creating invalid objects. |
444 | std::optional<llvm::yaml::Hex64> NBucket; |
445 | std::optional<llvm::yaml::Hex64> NChain; |
446 | |
447 | HashSection() : Section(ChunkKind::Hash) {} |
448 | |
449 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Hash; } |
450 | }; |
451 | |
452 | struct { |
453 | // The number of hash buckets. |
454 | // Not used when dumping the object, but can be used to override |
455 | // the real number of buckets when emiting an object from a YAML document. |
456 | std::optional<llvm::yaml::Hex32> ; |
457 | |
458 | // Index of the first symbol in the dynamic symbol table |
459 | // included in the hash table. |
460 | llvm::yaml::Hex32 ; |
461 | |
462 | // The number of words in the Bloom filter. |
463 | // Not used when dumping the object, but can be used to override the real |
464 | // number of words in the Bloom filter when emiting an object from a YAML |
465 | // document. |
466 | std::optional<llvm::yaml::Hex32> ; |
467 | |
468 | // A shift constant used by the Bloom filter. |
469 | llvm::yaml::Hex32 ; |
470 | }; |
471 | |
472 | struct GnuHashSection : Section { |
473 | std::optional<GnuHashHeader> ; |
474 | std::optional<std::vector<llvm::yaml::Hex64>> BloomFilter; |
475 | std::optional<std::vector<llvm::yaml::Hex32>> HashBuckets; |
476 | std::optional<std::vector<llvm::yaml::Hex32>> HashValues; |
477 | |
478 | GnuHashSection() : Section(ChunkKind::GnuHash) {} |
479 | |
480 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
481 | return {{"Header" , Header.has_value()}, |
482 | {"BloomFilter" , BloomFilter.has_value()}, |
483 | {"HashBuckets" , HashBuckets.has_value()}, |
484 | {"HashValues" , HashValues.has_value()}}; |
485 | }; |
486 | |
487 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::GnuHash; } |
488 | }; |
489 | |
490 | struct VernauxEntry { |
491 | uint32_t Hash; |
492 | uint16_t Flags; |
493 | uint16_t Other; |
494 | StringRef Name; |
495 | }; |
496 | |
497 | struct VerneedEntry { |
498 | uint16_t Version; |
499 | StringRef File; |
500 | std::vector<VernauxEntry> AuxV; |
501 | }; |
502 | |
503 | struct VerneedSection : Section { |
504 | std::optional<std::vector<VerneedEntry>> VerneedV; |
505 | std::optional<llvm::yaml::Hex64> Info; |
506 | |
507 | VerneedSection() : Section(ChunkKind::Verneed) {} |
508 | |
509 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
510 | return {{"Dependencies" , VerneedV.has_value()}}; |
511 | }; |
512 | |
513 | static bool classof(const Chunk *S) { |
514 | return S->Kind == ChunkKind::Verneed; |
515 | } |
516 | }; |
517 | |
518 | struct AddrsigSection : Section { |
519 | std::optional<std::vector<YAMLFlowString>> Symbols; |
520 | |
521 | AddrsigSection() : Section(ChunkKind::Addrsig) {} |
522 | |
523 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
524 | return {{"Symbols" , Symbols.has_value()}}; |
525 | }; |
526 | |
527 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Addrsig; } |
528 | }; |
529 | |
530 | struct LinkerOption { |
531 | StringRef Key; |
532 | StringRef Value; |
533 | }; |
534 | |
535 | struct LinkerOptionsSection : Section { |
536 | std::optional<std::vector<LinkerOption>> Options; |
537 | |
538 | LinkerOptionsSection() : Section(ChunkKind::LinkerOptions) {} |
539 | |
540 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
541 | return {{"Options" , Options.has_value()}}; |
542 | }; |
543 | |
544 | static bool classof(const Chunk *S) { |
545 | return S->Kind == ChunkKind::LinkerOptions; |
546 | } |
547 | }; |
548 | |
549 | struct DependentLibrariesSection : Section { |
550 | std::optional<std::vector<YAMLFlowString>> Libs; |
551 | |
552 | DependentLibrariesSection() : Section(ChunkKind::DependentLibraries) {} |
553 | |
554 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
555 | return {{"Libraries" , Libs.has_value()}}; |
556 | }; |
557 | |
558 | static bool classof(const Chunk *S) { |
559 | return S->Kind == ChunkKind::DependentLibraries; |
560 | } |
561 | }; |
562 | |
563 | // Represents the call graph profile section entry. |
564 | struct CallGraphEntryWeight { |
565 | // The weight of the edge. |
566 | uint64_t Weight; |
567 | }; |
568 | |
569 | struct CallGraphProfileSection : Section { |
570 | std::optional<std::vector<CallGraphEntryWeight>> Entries; |
571 | |
572 | CallGraphProfileSection() : Section(ChunkKind::CallGraphProfile) {} |
573 | |
574 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
575 | return {{"Entries" , Entries.has_value()}}; |
576 | }; |
577 | |
578 | static bool classof(const Chunk *S) { |
579 | return S->Kind == ChunkKind::CallGraphProfile; |
580 | } |
581 | }; |
582 | |
583 | struct SymverSection : Section { |
584 | std::optional<std::vector<uint16_t>> Entries; |
585 | |
586 | SymverSection() : Section(ChunkKind::Symver) {} |
587 | |
588 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
589 | return {{"Entries" , Entries.has_value()}}; |
590 | }; |
591 | |
592 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Symver; } |
593 | }; |
594 | |
595 | struct VerdefEntry { |
596 | std::optional<uint16_t> Version; |
597 | std::optional<uint16_t> Flags; |
598 | std::optional<uint16_t> VersionNdx; |
599 | std::optional<uint32_t> Hash; |
600 | std::optional<uint16_t> VDAux; |
601 | std::vector<StringRef> VerNames; |
602 | }; |
603 | |
604 | struct VerdefSection : Section { |
605 | std::optional<std::vector<VerdefEntry>> Entries; |
606 | std::optional<llvm::yaml::Hex64> Info; |
607 | |
608 | VerdefSection() : Section(ChunkKind::Verdef) {} |
609 | |
610 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
611 | return {{"Entries" , Entries.has_value()}}; |
612 | }; |
613 | |
614 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Verdef; } |
615 | }; |
616 | |
617 | struct GroupSection : Section { |
618 | // Members of a group contain a flag and a list of section indices |
619 | // that are part of the group. |
620 | std::optional<std::vector<SectionOrType>> Members; |
621 | std::optional<StringRef> Signature; /* Info */ |
622 | |
623 | GroupSection() : Section(ChunkKind::Group) {} |
624 | |
625 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
626 | return {{"Members" , Members.has_value()}}; |
627 | }; |
628 | |
629 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Group; } |
630 | }; |
631 | |
632 | struct Relocation { |
633 | llvm::yaml::Hex64 Offset; |
634 | YAMLIntUInt Addend; |
635 | ELF_REL Type; |
636 | std::optional<StringRef> Symbol; |
637 | }; |
638 | |
639 | struct RelocationSection : Section { |
640 | std::optional<std::vector<Relocation>> Relocations; |
641 | StringRef RelocatableSec; /* Info */ |
642 | |
643 | RelocationSection() : Section(ChunkKind::Relocation) {} |
644 | |
645 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
646 | return {{"Relocations" , Relocations.has_value()}}; |
647 | }; |
648 | |
649 | static bool classof(const Chunk *S) { |
650 | return S->Kind == ChunkKind::Relocation; |
651 | } |
652 | }; |
653 | |
654 | struct RelrSection : Section { |
655 | std::optional<std::vector<llvm::yaml::Hex64>> Entries; |
656 | |
657 | RelrSection() : Section(ChunkKind::Relr) {} |
658 | |
659 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
660 | return {{"Entries" , Entries.has_value()}}; |
661 | }; |
662 | |
663 | static bool classof(const Chunk *S) { |
664 | return S->Kind == ChunkKind::Relr; |
665 | } |
666 | }; |
667 | |
668 | struct SymtabShndxSection : Section { |
669 | std::optional<std::vector<uint32_t>> Entries; |
670 | |
671 | SymtabShndxSection() : Section(ChunkKind::SymtabShndxSection) {} |
672 | |
673 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
674 | return {{"Entries" , Entries.has_value()}}; |
675 | }; |
676 | |
677 | static bool classof(const Chunk *S) { |
678 | return S->Kind == ChunkKind::SymtabShndxSection; |
679 | } |
680 | }; |
681 | |
682 | struct ARMIndexTableEntry { |
683 | llvm::yaml::Hex32 Offset; |
684 | llvm::yaml::Hex32 Value; |
685 | }; |
686 | |
687 | struct ARMIndexTableSection : Section { |
688 | std::optional<std::vector<ARMIndexTableEntry>> Entries; |
689 | |
690 | ARMIndexTableSection() : Section(ChunkKind::ARMIndexTable) {} |
691 | |
692 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
693 | return {{"Entries" , Entries.has_value()}}; |
694 | }; |
695 | |
696 | static bool classof(const Chunk *S) { |
697 | return S->Kind == ChunkKind::ARMIndexTable; |
698 | } |
699 | }; |
700 | |
701 | // Represents .MIPS.abiflags section |
702 | struct MipsABIFlags : Section { |
703 | llvm::yaml::Hex16 Version; |
704 | MIPS_ISA ISALevel; |
705 | llvm::yaml::Hex8 ISARevision; |
706 | MIPS_AFL_REG GPRSize; |
707 | MIPS_AFL_REG CPR1Size; |
708 | MIPS_AFL_REG CPR2Size; |
709 | MIPS_ABI_FP FpABI; |
710 | MIPS_AFL_EXT ISAExtension; |
711 | MIPS_AFL_ASE ASEs; |
712 | MIPS_AFL_FLAGS1 Flags1; |
713 | llvm::yaml::Hex32 Flags2; |
714 | |
715 | MipsABIFlags() : Section(ChunkKind::MipsABIFlags) {} |
716 | |
717 | static bool classof(const Chunk *S) { |
718 | return S->Kind == ChunkKind::MipsABIFlags; |
719 | } |
720 | }; |
721 | |
722 | struct { |
723 | ELF_PT ; |
724 | ELF_PF ; |
725 | llvm::yaml::Hex64 ; |
726 | llvm::yaml::Hex64 ; |
727 | std::optional<llvm::yaml::Hex64> ; |
728 | std::optional<llvm::yaml::Hex64> ; |
729 | std::optional<llvm::yaml::Hex64> ; |
730 | std::optional<llvm::yaml::Hex64> ; |
731 | std::optional<StringRef> ; |
732 | std::optional<StringRef> ; |
733 | |
734 | // This vector contains all chunks from [FirstSec, LastSec]. |
735 | std::vector<Chunk *> ; |
736 | }; |
737 | |
738 | struct Object { |
739 | FileHeader ; |
740 | std::vector<ProgramHeader> ; |
741 | |
742 | // An object might contain output section descriptions as well as |
743 | // custom data that does not belong to any section. |
744 | std::vector<std::unique_ptr<Chunk>> Chunks; |
745 | |
746 | // Although in reality the symbols reside in a section, it is a lot |
747 | // cleaner and nicer if we read them from the YAML as a separate |
748 | // top-level key, which automatically ensures that invariants like there |
749 | // being a single SHT_SYMTAB section are upheld. |
750 | std::optional<std::vector<Symbol>> Symbols; |
751 | std::optional<std::vector<Symbol>> DynamicSymbols; |
752 | std::optional<DWARFYAML::Data> DWARF; |
753 | |
754 | std::vector<Section *> getSections() { |
755 | std::vector<Section *> Ret; |
756 | for (const std::unique_ptr<Chunk> &Sec : Chunks) |
757 | if (auto S = dyn_cast<ELFYAML::Section>(Val: Sec.get())) |
758 | Ret.push_back(x: S); |
759 | return Ret; |
760 | } |
761 | |
762 | const SectionHeaderTable &() const { |
763 | for (const std::unique_ptr<Chunk> &C : Chunks) |
764 | if (auto *S = dyn_cast<ELFYAML::SectionHeaderTable>(Val: C.get())) |
765 | return *S; |
766 | llvm_unreachable("the section header table chunk must always be present" ); |
767 | } |
768 | |
769 | ELF_ELFOSABI getOSAbi() const; |
770 | unsigned getMachine() const; |
771 | }; |
772 | |
773 | bool (ArrayRef<ProgramHeader> Phdrs, |
774 | const NoBitsSection &S); |
775 | |
776 | } // end namespace ELFYAML |
777 | } // end namespace llvm |
778 | |
779 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry) |
780 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry) |
781 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry::BBEntry) |
782 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry::BBRangeEntry) |
783 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::PGOAnalysisMapEntry) |
784 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::PGOAnalysisMapEntry::PGOBBEntry) |
785 | LLVM_YAML_IS_SEQUENCE_VECTOR( |
786 | llvm::ELFYAML::PGOAnalysisMapEntry::PGOBBEntry::SuccessorEntry) |
787 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry) |
788 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::LinkerOption) |
789 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::CallGraphEntryWeight) |
790 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::NoteEntry) |
791 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader) |
792 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionHeader) |
793 | LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Chunk>) |
794 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) |
795 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry) |
796 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry) |
797 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry) |
798 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) |
799 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) |
800 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ARMIndexTableEntry) |
801 | |
802 | namespace llvm { |
803 | namespace yaml { |
804 | |
805 | template <> struct ScalarTraits<ELFYAML::YAMLIntUInt> { |
806 | static void output(const ELFYAML::YAMLIntUInt &Val, void *Ctx, |
807 | raw_ostream &Out); |
808 | static StringRef input(StringRef Scalar, void *Ctx, |
809 | ELFYAML::YAMLIntUInt &Val); |
810 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
811 | }; |
812 | |
813 | template <> |
814 | struct ScalarEnumerationTraits<ELFYAML::ELF_ET> { |
815 | static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); |
816 | }; |
817 | |
818 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_PT> { |
819 | static void enumeration(IO &IO, ELFYAML::ELF_PT &Value); |
820 | }; |
821 | |
822 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_NT> { |
823 | static void enumeration(IO &IO, ELFYAML::ELF_NT &Value); |
824 | }; |
825 | |
826 | template <> |
827 | struct ScalarEnumerationTraits<ELFYAML::ELF_EM> { |
828 | static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); |
829 | }; |
830 | |
831 | template <> |
832 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS> { |
833 | static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value); |
834 | }; |
835 | |
836 | template <> |
837 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA> { |
838 | static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value); |
839 | }; |
840 | |
841 | template <> |
842 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { |
843 | static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); |
844 | }; |
845 | |
846 | template <> |
847 | struct ScalarBitSetTraits<ELFYAML::ELF_EF> { |
848 | static void bitset(IO &IO, ELFYAML::ELF_EF &Value); |
849 | }; |
850 | |
851 | template <> struct ScalarBitSetTraits<ELFYAML::ELF_PF> { |
852 | static void bitset(IO &IO, ELFYAML::ELF_PF &Value); |
853 | }; |
854 | |
855 | template <> |
856 | struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> { |
857 | static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); |
858 | }; |
859 | |
860 | template <> |
861 | struct ScalarBitSetTraits<ELFYAML::ELF_SHF> { |
862 | static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); |
863 | }; |
864 | |
865 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_SHN> { |
866 | static void enumeration(IO &IO, ELFYAML::ELF_SHN &Value); |
867 | }; |
868 | |
869 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_STB> { |
870 | static void enumeration(IO &IO, ELFYAML::ELF_STB &Value); |
871 | }; |
872 | |
873 | template <> |
874 | struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { |
875 | static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); |
876 | }; |
877 | |
878 | template <> |
879 | struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { |
880 | static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); |
881 | }; |
882 | |
883 | template <> |
884 | struct ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG> { |
885 | static void enumeration(IO &IO, ELFYAML::ELF_DYNTAG &Value); |
886 | }; |
887 | |
888 | template <> |
889 | struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { |
890 | static void (IO &IO, ELFYAML::ELF_RSS &Value); |
891 | }; |
892 | |
893 | template <> |
894 | struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> { |
895 | static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); |
896 | }; |
897 | |
898 | template <> |
899 | struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> { |
900 | static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); |
901 | }; |
902 | |
903 | template <> |
904 | struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> { |
905 | static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); |
906 | }; |
907 | |
908 | template <> |
909 | struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> { |
910 | static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); |
911 | }; |
912 | |
913 | template <> |
914 | struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> { |
915 | static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); |
916 | }; |
917 | |
918 | template <> |
919 | struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> { |
920 | static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); |
921 | }; |
922 | |
923 | template <> |
924 | struct MappingTraits<ELFYAML::FileHeader> { |
925 | static void (IO &IO, ELFYAML::FileHeader &FileHdr); |
926 | }; |
927 | |
928 | template <> struct MappingTraits<ELFYAML::SectionHeader> { |
929 | static void (IO &IO, ELFYAML::SectionHeader &SHdr); |
930 | }; |
931 | |
932 | template <> struct MappingTraits<ELFYAML::ProgramHeader> { |
933 | static void (IO &IO, ELFYAML::ProgramHeader &FileHdr); |
934 | static std::string (IO &IO, ELFYAML::ProgramHeader &FileHdr); |
935 | }; |
936 | |
937 | template <> |
938 | struct MappingTraits<ELFYAML::Symbol> { |
939 | static void mapping(IO &IO, ELFYAML::Symbol &Symbol); |
940 | static std::string validate(IO &IO, ELFYAML::Symbol &Symbol); |
941 | }; |
942 | |
943 | template <> struct MappingTraits<ELFYAML::StackSizeEntry> { |
944 | static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel); |
945 | }; |
946 | |
947 | template <> struct MappingTraits<ELFYAML::BBAddrMapEntry> { |
948 | static void mapping(IO &IO, ELFYAML::BBAddrMapEntry &E); |
949 | }; |
950 | |
951 | template <> struct MappingTraits<ELFYAML::BBAddrMapEntry::BBRangeEntry> { |
952 | static void mapping(IO &IO, ELFYAML::BBAddrMapEntry::BBRangeEntry &E); |
953 | }; |
954 | |
955 | template <> struct MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry> { |
956 | static void mapping(IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &E); |
957 | }; |
958 | |
959 | template <> struct MappingTraits<ELFYAML::PGOAnalysisMapEntry> { |
960 | static void mapping(IO &IO, ELFYAML::PGOAnalysisMapEntry &Rel); |
961 | }; |
962 | |
963 | template <> struct MappingTraits<ELFYAML::PGOAnalysisMapEntry::PGOBBEntry> { |
964 | static void mapping(IO &IO, ELFYAML::PGOAnalysisMapEntry::PGOBBEntry &Rel); |
965 | }; |
966 | |
967 | template <> |
968 | struct MappingTraits<ELFYAML::PGOAnalysisMapEntry::PGOBBEntry::SuccessorEntry> { |
969 | static void |
970 | mapping(IO &IO, |
971 | ELFYAML::PGOAnalysisMapEntry::PGOBBEntry::SuccessorEntry &Rel); |
972 | }; |
973 | |
974 | template <> struct MappingTraits<ELFYAML::GnuHashHeader> { |
975 | static void (IO &IO, ELFYAML::GnuHashHeader &Rel); |
976 | }; |
977 | |
978 | template <> struct MappingTraits<ELFYAML::DynamicEntry> { |
979 | static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); |
980 | }; |
981 | |
982 | template <> struct MappingTraits<ELFYAML::NoteEntry> { |
983 | static void mapping(IO &IO, ELFYAML::NoteEntry &N); |
984 | }; |
985 | |
986 | template <> struct MappingTraits<ELFYAML::VerdefEntry> { |
987 | static void mapping(IO &IO, ELFYAML::VerdefEntry &E); |
988 | }; |
989 | |
990 | template <> struct MappingTraits<ELFYAML::VerneedEntry> { |
991 | static void mapping(IO &IO, ELFYAML::VerneedEntry &E); |
992 | }; |
993 | |
994 | template <> struct MappingTraits<ELFYAML::VernauxEntry> { |
995 | static void mapping(IO &IO, ELFYAML::VernauxEntry &E); |
996 | }; |
997 | |
998 | template <> struct MappingTraits<ELFYAML::LinkerOption> { |
999 | static void mapping(IO &IO, ELFYAML::LinkerOption &Sym); |
1000 | }; |
1001 | |
1002 | template <> struct MappingTraits<ELFYAML::CallGraphEntryWeight> { |
1003 | static void mapping(IO &IO, ELFYAML::CallGraphEntryWeight &E); |
1004 | }; |
1005 | |
1006 | template <> struct MappingTraits<ELFYAML::Relocation> { |
1007 | static void mapping(IO &IO, ELFYAML::Relocation &Rel); |
1008 | }; |
1009 | |
1010 | template <> struct MappingTraits<ELFYAML::ARMIndexTableEntry> { |
1011 | static void mapping(IO &IO, ELFYAML::ARMIndexTableEntry &E); |
1012 | }; |
1013 | |
1014 | template <> struct MappingTraits<std::unique_ptr<ELFYAML::Chunk>> { |
1015 | static void mapping(IO &IO, std::unique_ptr<ELFYAML::Chunk> &C); |
1016 | static std::string validate(IO &io, std::unique_ptr<ELFYAML::Chunk> &C); |
1017 | }; |
1018 | |
1019 | template <> |
1020 | struct MappingTraits<ELFYAML::Object> { |
1021 | static void mapping(IO &IO, ELFYAML::Object &Object); |
1022 | }; |
1023 | |
1024 | template <> struct MappingTraits<ELFYAML::SectionOrType> { |
1025 | static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); |
1026 | }; |
1027 | |
1028 | } // end namespace yaml |
1029 | } // end namespace llvm |
1030 | |
1031 | #endif // LLVM_OBJECTYAML_ELFYAML_H |
1032 | |