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