blob: 68a0fc36b501928a76694707a15714dc1e2f3173 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Andrew Scullcdfcccc2018-10-05 20:58:37 +010010/// This file declares classes for handling the YAML representation
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010011/// 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/ObjectYAML/YAML.h"
20#include "llvm/Support/YAMLTraits.h"
21#include <cstdint>
22#include <memory>
23#include <vector>
24
25namespace llvm {
26namespace ELFYAML {
27
28// These types are invariant across 32/64-bit ELF, so for simplicity just
29// directly give them their exact sizes. We don't need to worry about
30// endianness because these are just the types in the YAMLIO structures,
31// and are appropriately converted to the necessary endianness when
32// reading/generating binary object files.
33// The naming of these types is intended to be ELF_PREFIX, where PREFIX is
34// the common prefix of the respective constants. E.g. ELF_EM corresponds
35// to the `e_machine` constants, like `EM_X86_64`.
36// In the future, these would probably be better suited by C++11 enum
37// class's with appropriate fixed underlying type.
38LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET)
39LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT)
40LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM)
41LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS)
42LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA)
43LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)
44// Just use 64, since it can hold 32-bit values too.
45LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
Andrew Walbran16937d02019-10-22 13:54:20 +010046// Just use 64, since it can hold 32-bit values too.
47LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_DYNTAG)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010048LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF)
49LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
50LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
51LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)
52// Just use 64, since it can hold 32-bit values too.
53LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
54LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_SHN)
Andrew Walbran3d2c1972020-04-07 12:24:26 +010055LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010056LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
57LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV)
58LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO)
59
60LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG)
61LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP)
62LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT)
63LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE)
64LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1)
65LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA)
66
67// For now, hardcode 64 bits everywhere that 32 or 64 would be needed
68// since 64-bit can hold 32-bit values too.
69struct FileHeader {
70 ELF_ELFCLASS Class;
71 ELF_ELFDATA Data;
72 ELF_ELFOSABI OSABI;
Andrew Walbran16937d02019-10-22 13:54:20 +010073 llvm::yaml::Hex8 ABIVersion;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010074 ELF_ET Type;
75 ELF_EM Machine;
76 ELF_EF Flags;
77 llvm::yaml::Hex64 Entry;
Andrew Walbran3d2c1972020-04-07 12:24:26 +010078
79 Optional<llvm::yaml::Hex16> SHEntSize;
80 Optional<llvm::yaml::Hex16> SHOffset;
81 Optional<llvm::yaml::Hex16> SHNum;
82 Optional<llvm::yaml::Hex16> SHStrNdx;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010083};
84
85struct SectionName {
86 StringRef Section;
87};
88
89struct ProgramHeader {
90 ELF_PT Type;
91 ELF_PF Flags;
92 llvm::yaml::Hex64 VAddr;
93 llvm::yaml::Hex64 PAddr;
94 Optional<llvm::yaml::Hex64> Align;
Andrew Walbran3d2c1972020-04-07 12:24:26 +010095 Optional<llvm::yaml::Hex64> FileSize;
96 Optional<llvm::yaml::Hex64> MemSize;
97 Optional<llvm::yaml::Hex64> Offset;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098 std::vector<SectionName> Sections;
99};
100
101struct Symbol {
102 StringRef Name;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100103 Optional<uint32_t> NameIndex;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100104 ELF_STT Type;
105 StringRef Section;
106 Optional<ELF_SHN> Index;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100107 ELF_STB Binding;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100108 llvm::yaml::Hex64 Value;
109 llvm::yaml::Hex64 Size;
110 uint8_t Other;
111};
112
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100113struct SectionOrType {
114 StringRef sectionNameOrType;
115};
116
Andrew Walbran16937d02019-10-22 13:54:20 +0100117struct DynamicEntry {
118 ELF_DYNTAG Tag;
119 llvm::yaml::Hex64 Val;
120};
121
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100122struct Section {
123 enum class SectionKind {
Andrew Walbran16937d02019-10-22 13:54:20 +0100124 Dynamic,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100125 Group,
126 RawContent,
127 Relocation,
128 NoBits,
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100129 Verdef,
130 Verneed,
131 Symver,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100132 MipsABIFlags
133 };
134 SectionKind Kind;
135 StringRef Name;
136 ELF_SHT Type;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100137 Optional<ELF_SHF> Flags;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100138 llvm::yaml::Hex64 Address;
139 StringRef Link;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100140 llvm::yaml::Hex64 AddressAlign;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100141 Optional<llvm::yaml::Hex64> EntSize;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100142
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100143 // This can be used to override the sh_offset field. It does not place the
144 // section data at the offset specified. Useful for creating invalid objects.
145 Optional<llvm::yaml::Hex64> ShOffset;
146
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100147 Section(SectionKind Kind) : Kind(Kind) {}
148 virtual ~Section();
149};
Andrew Walbran16937d02019-10-22 13:54:20 +0100150
151struct DynamicSection : Section {
152 std::vector<DynamicEntry> Entries;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100153 Optional<yaml::BinaryRef> Content;
Andrew Walbran16937d02019-10-22 13:54:20 +0100154
155 DynamicSection() : Section(SectionKind::Dynamic) {}
156
157 static bool classof(const Section *S) {
158 return S->Kind == SectionKind::Dynamic;
159 }
160};
161
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100162struct RawContentSection : Section {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100163 Optional<yaml::BinaryRef> Content;
164 Optional<llvm::yaml::Hex64> Size;
165 Optional<llvm::yaml::Hex64> Info;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100166
167 RawContentSection() : Section(SectionKind::RawContent) {}
168
169 static bool classof(const Section *S) {
170 return S->Kind == SectionKind::RawContent;
171 }
172};
173
174struct NoBitsSection : Section {
175 llvm::yaml::Hex64 Size;
176
177 NoBitsSection() : Section(SectionKind::NoBits) {}
178
179 static bool classof(const Section *S) {
180 return S->Kind == SectionKind::NoBits;
181 }
182};
183
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100184struct VernauxEntry {
185 uint32_t Hash;
186 uint16_t Flags;
187 uint16_t Other;
188 StringRef Name;
189};
190
191struct VerneedEntry {
192 uint16_t Version;
193 StringRef File;
194 std::vector<VernauxEntry> AuxV;
195};
196
197struct VerneedSection : Section {
198 std::vector<VerneedEntry> VerneedV;
199 llvm::yaml::Hex64 Info;
200
201 VerneedSection() : Section(SectionKind::Verneed) {}
202
203 static bool classof(const Section *S) {
204 return S->Kind == SectionKind::Verneed;
205 }
206};
207
208struct SymverSection : Section {
209 std::vector<uint16_t> Entries;
210
211 SymverSection() : Section(SectionKind::Symver) {}
212
213 static bool classof(const Section *S) {
214 return S->Kind == SectionKind::Symver;
215 }
216};
217
218struct VerdefEntry {
219 uint16_t Version;
220 uint16_t Flags;
221 uint16_t VersionNdx;
222 uint32_t Hash;
223 std::vector<StringRef> VerNames;
224};
225
226struct VerdefSection : Section {
227 std::vector<VerdefEntry> Entries;
228 llvm::yaml::Hex64 Info;
229
230 VerdefSection() : Section(SectionKind::Verdef) {}
231
232 static bool classof(const Section *S) {
233 return S->Kind == SectionKind::Verdef;
234 }
235};
236
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100237struct Group : Section {
238 // Members of a group contain a flag and a list of section indices
239 // that are part of the group.
240 std::vector<SectionOrType> Members;
Andrew Walbran16937d02019-10-22 13:54:20 +0100241 StringRef Signature; /* Info */
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100242
243 Group() : Section(SectionKind::Group) {}
244
245 static bool classof(const Section *S) {
246 return S->Kind == SectionKind::Group;
247 }
248};
249
250struct Relocation {
251 llvm::yaml::Hex64 Offset;
252 int64_t Addend;
253 ELF_REL Type;
254 Optional<StringRef> Symbol;
255};
256
257struct RelocationSection : Section {
258 std::vector<Relocation> Relocations;
Andrew Walbran16937d02019-10-22 13:54:20 +0100259 StringRef RelocatableSec; /* Info */
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100260
261 RelocationSection() : Section(SectionKind::Relocation) {}
262
263 static bool classof(const Section *S) {
264 return S->Kind == SectionKind::Relocation;
265 }
266};
267
268// Represents .MIPS.abiflags section
269struct MipsABIFlags : Section {
270 llvm::yaml::Hex16 Version;
271 MIPS_ISA ISALevel;
272 llvm::yaml::Hex8 ISARevision;
273 MIPS_AFL_REG GPRSize;
274 MIPS_AFL_REG CPR1Size;
275 MIPS_AFL_REG CPR2Size;
276 MIPS_ABI_FP FpABI;
277 MIPS_AFL_EXT ISAExtension;
278 MIPS_AFL_ASE ASEs;
279 MIPS_AFL_FLAGS1 Flags1;
280 llvm::yaml::Hex32 Flags2;
281
282 MipsABIFlags() : Section(SectionKind::MipsABIFlags) {}
283
284 static bool classof(const Section *S) {
285 return S->Kind == SectionKind::MipsABIFlags;
286 }
287};
288
289struct Object {
290 FileHeader Header;
291 std::vector<ProgramHeader> ProgramHeaders;
292 std::vector<std::unique_ptr<Section>> Sections;
293 // Although in reality the symbols reside in a section, it is a lot
294 // cleaner and nicer if we read them from the YAML as a separate
295 // top-level key, which automatically ensures that invariants like there
296 // being a single SHT_SYMTAB section are upheld.
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100297 std::vector<Symbol> Symbols;
298 std::vector<Symbol> DynamicSymbols;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100299};
300
301} // end namespace ELFYAML
302} // end namespace llvm
303
Andrew Walbran16937d02019-10-22 13:54:20 +0100304LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100305LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)
306LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>)
307LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100308LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)
309LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)
310LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100311LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)
312LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)
313LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName)
314
315namespace llvm {
316namespace yaml {
317
318template <>
319struct ScalarEnumerationTraits<ELFYAML::ELF_ET> {
320 static void enumeration(IO &IO, ELFYAML::ELF_ET &Value);
321};
322
323template <> struct ScalarEnumerationTraits<ELFYAML::ELF_PT> {
324 static void enumeration(IO &IO, ELFYAML::ELF_PT &Value);
325};
326
327template <>
328struct ScalarEnumerationTraits<ELFYAML::ELF_EM> {
329 static void enumeration(IO &IO, ELFYAML::ELF_EM &Value);
330};
331
332template <>
333struct ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS> {
334 static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value);
335};
336
337template <>
338struct ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA> {
339 static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value);
340};
341
342template <>
343struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> {
344 static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value);
345};
346
347template <>
348struct ScalarBitSetTraits<ELFYAML::ELF_EF> {
349 static void bitset(IO &IO, ELFYAML::ELF_EF &Value);
350};
351
352template <> struct ScalarBitSetTraits<ELFYAML::ELF_PF> {
353 static void bitset(IO &IO, ELFYAML::ELF_PF &Value);
354};
355
356template <>
357struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> {
358 static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value);
359};
360
361template <>
362struct ScalarBitSetTraits<ELFYAML::ELF_SHF> {
363 static void bitset(IO &IO, ELFYAML::ELF_SHF &Value);
364};
365
366template <> struct ScalarEnumerationTraits<ELFYAML::ELF_SHN> {
367 static void enumeration(IO &IO, ELFYAML::ELF_SHN &Value);
368};
369
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100370template <> struct ScalarEnumerationTraits<ELFYAML::ELF_STB> {
371 static void enumeration(IO &IO, ELFYAML::ELF_STB &Value);
372};
373
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100374template <>
375struct ScalarEnumerationTraits<ELFYAML::ELF_STT> {
376 static void enumeration(IO &IO, ELFYAML::ELF_STT &Value);
377};
378
379template <>
380struct ScalarEnumerationTraits<ELFYAML::ELF_STV> {
381 static void enumeration(IO &IO, ELFYAML::ELF_STV &Value);
382};
383
384template <>
385struct ScalarBitSetTraits<ELFYAML::ELF_STO> {
386 static void bitset(IO &IO, ELFYAML::ELF_STO &Value);
387};
388
389template <>
390struct ScalarEnumerationTraits<ELFYAML::ELF_REL> {
391 static void enumeration(IO &IO, ELFYAML::ELF_REL &Value);
392};
393
394template <>
Andrew Walbran16937d02019-10-22 13:54:20 +0100395struct ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG> {
396 static void enumeration(IO &IO, ELFYAML::ELF_DYNTAG &Value);
397};
398
399template <>
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100400struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> {
401 static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value);
402};
403
404template <>
405struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> {
406 static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value);
407};
408
409template <>
410struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> {
411 static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value);
412};
413
414template <>
415struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> {
416 static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value);
417};
418
419template <>
420struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> {
421 static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value);
422};
423
424template <>
425struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> {
426 static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value);
427};
428
429template <>
430struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> {
431 static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value);
432};
433
434template <>
435struct MappingTraits<ELFYAML::FileHeader> {
436 static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
437};
438
439template <> struct MappingTraits<ELFYAML::ProgramHeader> {
440 static void mapping(IO &IO, ELFYAML::ProgramHeader &FileHdr);
441};
442
443template <>
444struct MappingTraits<ELFYAML::Symbol> {
445 static void mapping(IO &IO, ELFYAML::Symbol &Symbol);
446 static StringRef validate(IO &IO, ELFYAML::Symbol &Symbol);
447};
448
Andrew Walbran16937d02019-10-22 13:54:20 +0100449template <> struct MappingTraits<ELFYAML::DynamicEntry> {
450 static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel);
451};
452
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100453template <> struct MappingTraits<ELFYAML::VerdefEntry> {
454 static void mapping(IO &IO, ELFYAML::VerdefEntry &E);
455};
456
457template <> struct MappingTraits<ELFYAML::VerneedEntry> {
458 static void mapping(IO &IO, ELFYAML::VerneedEntry &E);
459};
460
461template <> struct MappingTraits<ELFYAML::VernauxEntry> {
462 static void mapping(IO &IO, ELFYAML::VernauxEntry &E);
463};
464
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100465template <> struct MappingTraits<ELFYAML::Relocation> {
466 static void mapping(IO &IO, ELFYAML::Relocation &Rel);
467};
468
469template <>
470struct MappingTraits<std::unique_ptr<ELFYAML::Section>> {
471 static void mapping(IO &IO, std::unique_ptr<ELFYAML::Section> &Section);
472 static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Section> &Section);
473};
474
475template <>
476struct MappingTraits<ELFYAML::Object> {
477 static void mapping(IO &IO, ELFYAML::Object &Object);
478};
479
480template <> struct MappingTraits<ELFYAML::SectionOrType> {
481 static void mapping(IO &IO, ELFYAML::SectionOrType &sectionOrType);
482};
483
484template <> struct MappingTraits<ELFYAML::SectionName> {
485 static void mapping(IO &IO, ELFYAML::SectionName &sectionName);
486};
487
488} // end namespace yaml
489} // end namespace llvm
490
491#endif // LLVM_OBJECTYAML_ELFYAML_H