File: | build/source/llvm/tools/obj2yaml/elf2yaml.cpp |
Warning: | line 1047, column 41 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===------ utils/elf2yaml.cpp - obj2yaml conversion tool -------*- 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 | #include "obj2yaml.h" | |||
10 | #include "llvm/ADT/DenseSet.h" | |||
11 | #include "llvm/ADT/STLExtras.h" | |||
12 | #include "llvm/ADT/Twine.h" | |||
13 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | |||
14 | #include "llvm/Object/ELFObjectFile.h" | |||
15 | #include "llvm/ObjectYAML/DWARFYAML.h" | |||
16 | #include "llvm/ObjectYAML/ELFYAML.h" | |||
17 | #include "llvm/Support/DataExtractor.h" | |||
18 | #include "llvm/Support/Errc.h" | |||
19 | #include "llvm/Support/ErrorHandling.h" | |||
20 | #include "llvm/Support/YAMLTraits.h" | |||
21 | #include <optional> | |||
22 | ||||
23 | using namespace llvm; | |||
24 | ||||
25 | namespace { | |||
26 | ||||
27 | template <class ELFT> | |||
28 | class ELFDumper { | |||
29 | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)using Elf_Addr = typename ELFT::Addr; using Elf_Off = typename ELFT::Off; using Elf_Half = typename ELFT::Half; using Elf_Word = typename ELFT::Word; using Elf_Sword = typename ELFT::Sword ; using Elf_Xword = typename ELFT::Xword; using Elf_Sxword = typename ELFT::Sxword; using uintX_t = typename ELFT::uint; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Shdr = typename ELFT::Shdr; using Elf_Sym = typename ELFT::Sym; using Elf_Dyn = typename ELFT::Dyn; using Elf_Phdr = typename ELFT::Phdr; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; using Elf_Relr = typename ELFT::Relr; using Elf_Verdef = typename ELFT ::Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_Verneed = typename ELFT::Verneed; using Elf_Vernaux = typename ELFT:: Vernaux; using Elf_Versym = typename ELFT::Versym; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash ; using Elf_Chdr = typename ELFT::Chdr; using Elf_Nhdr = typename ELFT::Nhdr; using Elf_Note = typename ELFT::Note; using Elf_Note_Iterator = typename ELFT::NoteIterator; using Elf_CGProfile = typename ELFT::CGProfile; using Elf_Dyn_Range = typename ELFT::DynRange ; using Elf_Shdr_Range = typename ELFT::ShdrRange; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Rel_Range = typename ELFT ::RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr_Range = typename ELFT::PhdrRange; | |||
30 | ||||
31 | ArrayRef<Elf_Shdr> Sections; | |||
32 | ArrayRef<Elf_Sym> SymTable; | |||
33 | ||||
34 | DenseMap<StringRef, uint32_t> UsedSectionNames; | |||
35 | std::vector<std::string> SectionNames; | |||
36 | std::optional<uint32_t> ShStrTabIndex; | |||
37 | ||||
38 | DenseMap<StringRef, uint32_t> UsedSymbolNames; | |||
39 | std::vector<std::string> SymbolNames; | |||
40 | ||||
41 | BumpPtrAllocator StringAllocator; | |||
42 | ||||
43 | Expected<StringRef> getUniquedSectionName(const Elf_Shdr &Sec); | |||
44 | Expected<StringRef> getUniquedSymbolName(const Elf_Sym *Sym, | |||
45 | StringRef StrTable, | |||
46 | const Elf_Shdr *SymTab); | |||
47 | Expected<StringRef> getSymbolName(uint32_t SymtabNdx, uint32_t SymbolNdx); | |||
48 | ||||
49 | const object::ELFFile<ELFT> &Obj; | |||
50 | std::unique_ptr<DWARFContext> DWARFCtx; | |||
51 | ||||
52 | DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables; | |||
53 | ||||
54 | Expected<std::vector<ELFYAML::ProgramHeader>> | |||
55 | dumpProgramHeaders(ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Sections); | |||
56 | ||||
57 | std::optional<DWARFYAML::Data> | |||
58 | dumpDWARFSections(std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections); | |||
59 | ||||
60 | Error dumpSymbols(const Elf_Shdr *Symtab, | |||
61 | std::optional<std::vector<ELFYAML::Symbol>> &Symbols); | |||
62 | Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, | |||
63 | StringRef StrTable, ELFYAML::Symbol &S); | |||
64 | Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> dumpSections(); | |||
65 | Error dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); | |||
66 | Error dumpCommonRelocationSection(const Elf_Shdr *Shdr, | |||
67 | ELFYAML::RelocationSection &S); | |||
68 | template <class RelT> | |||
69 | Error dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab, | |||
70 | ELFYAML::Relocation &R); | |||
71 | ||||
72 | Expected<ELFYAML::AddrsigSection *> dumpAddrsigSection(const Elf_Shdr *Shdr); | |||
73 | Expected<ELFYAML::LinkerOptionsSection *> | |||
74 | dumpLinkerOptionsSection(const Elf_Shdr *Shdr); | |||
75 | Expected<ELFYAML::DependentLibrariesSection *> | |||
76 | dumpDependentLibrariesSection(const Elf_Shdr *Shdr); | |||
77 | Expected<ELFYAML::CallGraphProfileSection *> | |||
78 | dumpCallGraphProfileSection(const Elf_Shdr *Shdr); | |||
79 | Expected<ELFYAML::DynamicSection *> dumpDynamicSection(const Elf_Shdr *Shdr); | |||
80 | Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr); | |||
81 | Expected<ELFYAML::RelrSection *> dumpRelrSection(const Elf_Shdr *Shdr); | |||
82 | Expected<ELFYAML::RawContentSection *> | |||
83 | dumpContentSection(const Elf_Shdr *Shdr); | |||
84 | Expected<ELFYAML::SymtabShndxSection *> | |||
85 | dumpSymtabShndxSection(const Elf_Shdr *Shdr); | |||
86 | Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr); | |||
87 | Expected<ELFYAML::HashSection *> dumpHashSection(const Elf_Shdr *Shdr); | |||
88 | Expected<ELFYAML::NoteSection *> dumpNoteSection(const Elf_Shdr *Shdr); | |||
89 | Expected<ELFYAML::GnuHashSection *> dumpGnuHashSection(const Elf_Shdr *Shdr); | |||
90 | Expected<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr); | |||
91 | Expected<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr); | |||
92 | Expected<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr); | |||
93 | Expected<ELFYAML::GroupSection *> dumpGroupSection(const Elf_Shdr *Shdr); | |||
94 | Expected<ELFYAML::ARMIndexTableSection *> | |||
95 | dumpARMIndexTableSection(const Elf_Shdr *Shdr); | |||
96 | Expected<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr); | |||
97 | Expected<ELFYAML::StackSizesSection *> | |||
98 | dumpStackSizesSection(const Elf_Shdr *Shdr); | |||
99 | Expected<ELFYAML::BBAddrMapSection *> | |||
100 | dumpBBAddrMapSection(const Elf_Shdr *Shdr); | |||
101 | Expected<ELFYAML::RawContentSection *> | |||
102 | dumpPlaceholderSection(const Elf_Shdr *Shdr); | |||
103 | ||||
104 | bool shouldPrintSection(const ELFYAML::Section &S, const Elf_Shdr &SHdr, | |||
105 | std::optional<DWARFYAML::Data> DWARF); | |||
106 | ||||
107 | public: | |||
108 | ELFDumper(const object::ELFFile<ELFT> &O, std::unique_ptr<DWARFContext> DCtx); | |||
109 | Expected<ELFYAML::Object *> dump(); | |||
110 | }; | |||
111 | ||||
112 | } | |||
113 | ||||
114 | template <class ELFT> | |||
115 | ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O, | |||
116 | std::unique_ptr<DWARFContext> DCtx) | |||
117 | : Obj(O), DWARFCtx(std::move(DCtx)) {} | |||
118 | ||||
119 | template <class ELFT> | |||
120 | Expected<StringRef> | |||
121 | ELFDumper<ELFT>::getUniquedSectionName(const Elf_Shdr &Sec) { | |||
122 | unsigned SecIndex = &Sec - &Sections[0]; | |||
123 | if (!SectionNames[SecIndex].empty()) | |||
124 | return SectionNames[SecIndex]; | |||
125 | ||||
126 | auto NameOrErr = Obj.getSectionName(Sec); | |||
127 | if (!NameOrErr) | |||
128 | return NameOrErr; | |||
129 | StringRef Name = *NameOrErr; | |||
130 | // In some specific cases we might have more than one section without a | |||
131 | // name (sh_name == 0). It normally doesn't happen, but when we have this case | |||
132 | // it doesn't make sense to uniquify their names and add noise to the output. | |||
133 | if (Name.empty()) | |||
134 | return ""; | |||
135 | ||||
136 | std::string &Ret = SectionNames[SecIndex]; | |||
137 | ||||
138 | auto It = UsedSectionNames.insert({Name, 0}); | |||
139 | if (!It.second) | |||
140 | Ret = ELFYAML::appendUniqueSuffix(Name, Twine(++It.first->second)); | |||
141 | else | |||
142 | Ret = std::string(Name); | |||
143 | return Ret; | |||
144 | } | |||
145 | ||||
146 | template <class ELFT> | |||
147 | Expected<StringRef> | |||
148 | ELFDumper<ELFT>::getUniquedSymbolName(const Elf_Sym *Sym, StringRef StrTable, | |||
149 | const Elf_Shdr *SymTab) { | |||
150 | Expected<StringRef> SymbolNameOrErr = Sym->getName(StrTable); | |||
151 | if (!SymbolNameOrErr) | |||
152 | return SymbolNameOrErr; | |||
153 | StringRef Name = *SymbolNameOrErr; | |||
154 | if (Name.empty() && Sym->getType() == ELF::STT_SECTION) { | |||
155 | Expected<const Elf_Shdr *> ShdrOrErr = | |||
156 | Obj.getSection(*Sym, SymTab, ShndxTables.lookup(SymTab)); | |||
157 | if (!ShdrOrErr) | |||
158 | return ShdrOrErr.takeError(); | |||
159 | // The null section has no name. | |||
160 | return (*ShdrOrErr == nullptr) ? "" : getUniquedSectionName(**ShdrOrErr); | |||
161 | } | |||
162 | ||||
163 | // Symbols in .symtab can have duplicate names. For example, it is a common | |||
164 | // situation for local symbols in a relocatable object. Here we assign unique | |||
165 | // suffixes for such symbols so that we can differentiate them. | |||
166 | if (SymTab->sh_type == ELF::SHT_SYMTAB) { | |||
167 | unsigned Index = Sym - SymTable.data(); | |||
168 | if (!SymbolNames[Index].empty()) | |||
169 | return SymbolNames[Index]; | |||
170 | ||||
171 | auto It = UsedSymbolNames.insert({Name, 0}); | |||
172 | if (!It.second) | |||
173 | SymbolNames[Index] = | |||
174 | ELFYAML::appendUniqueSuffix(Name, Twine(++It.first->second)); | |||
175 | else | |||
176 | SymbolNames[Index] = std::string(Name); | |||
177 | return SymbolNames[Index]; | |||
178 | } | |||
179 | ||||
180 | return Name; | |||
181 | } | |||
182 | ||||
183 | template <class ELFT> | |||
184 | bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S, | |||
185 | const Elf_Shdr &SHdr, | |||
186 | std::optional<DWARFYAML::Data> DWARF) { | |||
187 | // We only print the SHT_NULL section at index 0 when it | |||
188 | // has at least one non-null field, because yaml2obj | |||
189 | // normally creates the zero section at index 0 implicitly. | |||
190 | if (S.Type == ELF::SHT_NULL && (&SHdr == &Sections[0])) { | |||
191 | const uint8_t *Begin = reinterpret_cast<const uint8_t *>(&SHdr); | |||
192 | const uint8_t *End = Begin + sizeof(Elf_Shdr); | |||
193 | return std::any_of(Begin, End, [](uint8_t V) { return V != 0; }); | |||
194 | } | |||
195 | ||||
196 | // Normally we use "DWARF:" to describe contents of DWARF sections. Sometimes | |||
197 | // the content of DWARF sections can be successfully parsed into the "DWARF:" | |||
198 | // entry but their section headers may have special flags, entry size, address | |||
199 | // alignment, etc. We will preserve the header for them under such | |||
200 | // circumstances. | |||
201 | StringRef SecName = S.Name.substr(1); | |||
202 | if (DWARF && DWARF->getNonEmptySectionNames().count(SecName)) { | |||
203 | if (const ELFYAML::RawContentSection *RawSec = | |||
204 | dyn_cast<const ELFYAML::RawContentSection>(&S)) { | |||
205 | if (RawSec->Type != ELF::SHT_PROGBITS || RawSec->Link || RawSec->Info || | |||
206 | RawSec->AddressAlign != yaml::Hex64{1} || RawSec->Address || | |||
207 | RawSec->EntSize) | |||
208 | return true; | |||
209 | ||||
210 | ELFYAML::ELF_SHF ShFlags = RawSec->Flags.value_or(ELFYAML::ELF_SHF(0)); | |||
211 | ||||
212 | if (SecName == "debug_str") | |||
213 | return ShFlags != ELFYAML::ELF_SHF(ELF::SHF_MERGE | ELF::SHF_STRINGS); | |||
214 | ||||
215 | return ShFlags != ELFYAML::ELF_SHF{0}; | |||
216 | } | |||
217 | } | |||
218 | ||||
219 | // Normally we use "Symbols:" and "DynamicSymbols:" to describe contents of | |||
220 | // symbol tables. We also build and emit corresponding string tables | |||
221 | // implicitly. But sometimes it is important to preserve positions and virtual | |||
222 | // addresses of allocatable sections, e.g. for creating program headers. | |||
223 | // Generally we are trying to reduce noise in the YAML output. Because | |||
224 | // of that we do not print non-allocatable versions of such sections and | |||
225 | // assume they are placed at the end. | |||
226 | // We also dump symbol tables when the Size field is set. It happens when they | |||
227 | // are empty, which should not normally happen. | |||
228 | if (S.Type == ELF::SHT_STRTAB || S.Type == ELF::SHT_SYMTAB || | |||
229 | S.Type == ELF::SHT_DYNSYM) { | |||
230 | return S.Size || S.Flags.value_or(ELFYAML::ELF_SHF(0)) & ELF::SHF_ALLOC; | |||
231 | } | |||
232 | ||||
233 | return true; | |||
234 | } | |||
235 | ||||
236 | template <class ELFT> | |||
237 | static void dumpSectionOffsets(const typename ELFT::Ehdr &Header, | |||
238 | ArrayRef<ELFYAML::ProgramHeader> Phdrs, | |||
239 | std::vector<std::unique_ptr<ELFYAML::Chunk>> &V, | |||
240 | ArrayRef<typename ELFT::Shdr> S) { | |||
241 | if (V.empty()) | |||
242 | return; | |||
243 | ||||
244 | uint64_t ExpectedOffset; | |||
245 | if (Header.e_phoff > 0) | |||
246 | ExpectedOffset = Header.e_phoff + Header.e_phentsize * Header.e_phnum; | |||
247 | else | |||
248 | ExpectedOffset = sizeof(typename ELFT::Ehdr); | |||
249 | ||||
250 | for (const std::unique_ptr<ELFYAML::Chunk> &C : ArrayRef(V).drop_front()) { | |||
251 | ELFYAML::Section &Sec = *cast<ELFYAML::Section>(C.get()); | |||
252 | const typename ELFT::Shdr &SecHdr = S[Sec.OriginalSecNdx]; | |||
253 | ||||
254 | ExpectedOffset = alignTo(ExpectedOffset, | |||
255 | SecHdr.sh_addralign ? SecHdr.sh_addralign : 1uLL); | |||
256 | ||||
257 | // We only set the "Offset" field when it can't be naturally derived | |||
258 | // from the offset and size of the previous section. This reduces | |||
259 | // the noise in the YAML output. | |||
260 | if (SecHdr.sh_offset != ExpectedOffset) | |||
261 | Sec.Offset = (yaml::Hex64)SecHdr.sh_offset; | |||
262 | ||||
263 | if (Sec.Type == ELF::SHT_NOBITS && | |||
264 | !ELFYAML::shouldAllocateFileSpace(Phdrs, | |||
265 | *cast<ELFYAML::NoBitsSection>(&Sec))) | |||
266 | ExpectedOffset = SecHdr.sh_offset; | |||
267 | else | |||
268 | ExpectedOffset = SecHdr.sh_offset + SecHdr.sh_size; | |||
269 | } | |||
270 | } | |||
271 | ||||
272 | template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() { | |||
273 | auto Y = std::make_unique<ELFYAML::Object>(); | |||
274 | ||||
275 | // Dump header. We do not dump EPh* and ESh* fields. When not explicitly set, | |||
276 | // the values are set by yaml2obj automatically and there is no need to dump | |||
277 | // them here. | |||
278 | Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader().getFileClass()); | |||
279 | Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader().getDataEncoding()); | |||
280 | Y->Header.OSABI = Obj.getHeader().e_ident[ELF::EI_OSABI]; | |||
281 | Y->Header.ABIVersion = Obj.getHeader().e_ident[ELF::EI_ABIVERSION]; | |||
282 | Y->Header.Type = Obj.getHeader().e_type; | |||
283 | if (Obj.getHeader().e_machine != 0) | |||
284 | Y->Header.Machine = ELFYAML::ELF_EM(Obj.getHeader().e_machine); | |||
285 | Y->Header.Flags = Obj.getHeader().e_flags; | |||
286 | Y->Header.Entry = Obj.getHeader().e_entry; | |||
287 | ||||
288 | // Dump sections | |||
289 | auto SectionsOrErr = Obj.sections(); | |||
290 | if (!SectionsOrErr) | |||
291 | return SectionsOrErr.takeError(); | |||
292 | Sections = *SectionsOrErr; | |||
293 | SectionNames.resize(Sections.size()); | |||
294 | ||||
295 | if (Sections.size() > 0) { | |||
296 | ShStrTabIndex = Obj.getHeader().e_shstrndx; | |||
297 | if (*ShStrTabIndex == ELF::SHN_XINDEX) | |||
298 | ShStrTabIndex = Sections[0].sh_link; | |||
299 | // TODO: Set EShStrndx if the value doesn't represent a real section. | |||
300 | } | |||
301 | ||||
302 | // Normally an object that does not have sections has e_shnum == 0. | |||
303 | // Also, e_shnum might be 0, when the the number of entries in the section | |||
304 | // header table is larger than or equal to SHN_LORESERVE (0xff00). In this | |||
305 | // case the real number of entries is held in the sh_size member of the | |||
306 | // initial entry. We have a section header table when `e_shoff` is not 0. | |||
307 | if (Obj.getHeader().e_shoff != 0 && Obj.getHeader().e_shnum == 0) | |||
308 | Y->Header.EShNum = 0; | |||
309 | ||||
310 | // Dump symbols. We need to do this early because other sections might want | |||
311 | // to access the deduplicated symbol names that we also create here. | |||
312 | const Elf_Shdr *SymTab = nullptr; | |||
313 | const Elf_Shdr *DynSymTab = nullptr; | |||
314 | ||||
315 | for (const Elf_Shdr &Sec : Sections) { | |||
316 | if (Sec.sh_type == ELF::SHT_SYMTAB) { | |||
317 | SymTab = &Sec; | |||
318 | } else if (Sec.sh_type == ELF::SHT_DYNSYM) { | |||
319 | DynSymTab = &Sec; | |||
320 | } else if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) { | |||
321 | // We need to locate SHT_SYMTAB_SHNDX sections early, because they | |||
322 | // might be needed for dumping symbols. | |||
323 | if (Expected<ArrayRef<Elf_Word>> TableOrErr = Obj.getSHNDXTable(Sec)) { | |||
324 | // The `getSHNDXTable` calls the `getSection` internally when validates | |||
325 | // the symbol table section linked to the SHT_SYMTAB_SHNDX section. | |||
326 | const Elf_Shdr *LinkedSymTab = cantFail(Obj.getSection(Sec.sh_link)); | |||
327 | if (!ShndxTables.insert({LinkedSymTab, *TableOrErr}).second) | |||
328 | return createStringError( | |||
329 | errc::invalid_argument, | |||
330 | "multiple SHT_SYMTAB_SHNDX sections are " | |||
331 | "linked to the same symbol table with index " + | |||
332 | Twine(Sec.sh_link)); | |||
333 | } else { | |||
334 | return createStringError(errc::invalid_argument, | |||
335 | "unable to read extended section indexes: " + | |||
336 | toString(TableOrErr.takeError())); | |||
337 | } | |||
338 | } | |||
339 | } | |||
340 | ||||
341 | if (SymTab) | |||
342 | if (Error E = dumpSymbols(SymTab, Y->Symbols)) | |||
343 | return std::move(E); | |||
344 | ||||
345 | if (DynSymTab) | |||
346 | if (Error E = dumpSymbols(DynSymTab, Y->DynamicSymbols)) | |||
347 | return std::move(E); | |||
348 | ||||
349 | // We dump all sections first. It is simple and allows us to verify that all | |||
350 | // sections are valid and also to generalize the code. But we are not going to | |||
351 | // keep all of them in the final output (see comments for | |||
352 | // 'shouldPrintSection()'). Undesired chunks will be removed later. | |||
353 | Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> ChunksOrErr = | |||
354 | dumpSections(); | |||
355 | if (!ChunksOrErr) | |||
356 | return ChunksOrErr.takeError(); | |||
357 | std::vector<std::unique_ptr<ELFYAML::Chunk>> Chunks = std::move(*ChunksOrErr); | |||
358 | ||||
359 | std::vector<ELFYAML::Section *> OriginalOrder; | |||
360 | if (!Chunks.empty()) | |||
361 | for (const std::unique_ptr<ELFYAML::Chunk> &C : | |||
362 | ArrayRef(Chunks).drop_front()) | |||
363 | OriginalOrder.push_back(cast<ELFYAML::Section>(C.get())); | |||
364 | ||||
365 | // Sometimes the order of sections in the section header table does not match | |||
366 | // their actual order. Here we sort sections by the file offset. | |||
367 | llvm::stable_sort(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A, | |||
368 | const std::unique_ptr<ELFYAML::Chunk> &B) { | |||
369 | return Sections[cast<ELFYAML::Section>(A.get())->OriginalSecNdx].sh_offset < | |||
370 | Sections[cast<ELFYAML::Section>(B.get())->OriginalSecNdx].sh_offset; | |||
371 | }); | |||
372 | ||||
373 | // Dump program headers. | |||
374 | Expected<std::vector<ELFYAML::ProgramHeader>> PhdrsOrErr = | |||
375 | dumpProgramHeaders(Chunks); | |||
376 | if (!PhdrsOrErr) | |||
377 | return PhdrsOrErr.takeError(); | |||
378 | Y->ProgramHeaders = std::move(*PhdrsOrErr); | |||
379 | ||||
380 | dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks, | |||
381 | Sections); | |||
382 | ||||
383 | // Dump DWARF sections. | |||
384 | Y->DWARF = dumpDWARFSections(Chunks); | |||
385 | ||||
386 | // We emit the "SectionHeaderTable" key when the order of sections in the | |||
387 | // sections header table doesn't match the file order. | |||
388 | const bool SectionsSorted = | |||
389 | llvm::is_sorted(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A, | |||
390 | const std::unique_ptr<ELFYAML::Chunk> &B) { | |||
391 | return cast<ELFYAML::Section>(A.get())->OriginalSecNdx < | |||
392 | cast<ELFYAML::Section>(B.get())->OriginalSecNdx; | |||
393 | }); | |||
394 | if (!SectionsSorted) { | |||
395 | std::unique_ptr<ELFYAML::SectionHeaderTable> SHT = | |||
396 | std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/false); | |||
397 | SHT->Sections.emplace(); | |||
398 | for (ELFYAML::Section *S : OriginalOrder) | |||
399 | SHT->Sections->push_back({S->Name}); | |||
400 | Chunks.push_back(std::move(SHT)); | |||
401 | } | |||
402 | ||||
403 | llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) { | |||
404 | if (isa<ELFYAML::SectionHeaderTable>(*C)) | |||
405 | return false; | |||
406 | ||||
407 | const ELFYAML::Section &S = cast<ELFYAML::Section>(*C); | |||
408 | return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF); | |||
409 | }); | |||
410 | ||||
411 | // The section header string table by default is assumed to be called | |||
412 | // ".shstrtab" and be in its own unique section. However, it's possible for it | |||
413 | // to be called something else and shared with another section. If the name | |||
414 | // isn't the default, provide this in the YAML. | |||
415 | if (ShStrTabIndex && *ShStrTabIndex != ELF::SHN_UNDEF && | |||
416 | *ShStrTabIndex < Sections.size()) { | |||
417 | StringRef ShStrtabName; | |||
418 | if (SymTab && SymTab->sh_link == *ShStrTabIndex) { | |||
419 | // Section header string table is shared with the symbol table. Use that | |||
420 | // section's name (usually .strtab). | |||
421 | ShStrtabName = cantFail(Obj.getSectionName(Sections[SymTab->sh_link])); | |||
422 | } else if (DynSymTab && DynSymTab->sh_link == *ShStrTabIndex) { | |||
423 | // Section header string table is shared with the dynamic symbol table. | |||
424 | // Use that section's name (usually .dynstr). | |||
425 | ShStrtabName = cantFail(Obj.getSectionName(Sections[DynSymTab->sh_link])); | |||
426 | } else { | |||
427 | // Otherwise, the section name potentially needs uniquifying. | |||
428 | ShStrtabName = cantFail(getUniquedSectionName(Sections[*ShStrTabIndex])); | |||
429 | } | |||
430 | if (ShStrtabName != ".shstrtab") | |||
431 | Y->Header.SectionHeaderStringTable = ShStrtabName; | |||
432 | } | |||
433 | ||||
434 | Y->Chunks = std::move(Chunks); | |||
435 | return Y.release(); | |||
436 | } | |||
437 | ||||
438 | template <class ELFT> | |||
439 | static bool isInSegment(const ELFYAML::Section &Sec, | |||
440 | const typename ELFT::Shdr &SHdr, | |||
441 | const typename ELFT::Phdr &Phdr) { | |||
442 | if (Sec.Type == ELF::SHT_NULL) | |||
443 | return false; | |||
444 | ||||
445 | // A section is within a segment when its location in a file is within the | |||
446 | // [p_offset, p_offset + p_filesz] region. | |||
447 | bool FileOffsetsMatch = | |||
448 | SHdr.sh_offset >= Phdr.p_offset && | |||
449 | (SHdr.sh_offset + SHdr.sh_size <= Phdr.p_offset + Phdr.p_filesz); | |||
450 | ||||
451 | bool VirtualAddressesMatch = SHdr.sh_addr >= Phdr.p_vaddr && | |||
452 | SHdr.sh_addr <= Phdr.p_vaddr + Phdr.p_memsz; | |||
453 | ||||
454 | if (FileOffsetsMatch) { | |||
455 | // An empty section on the edges of a program header can be outside of the | |||
456 | // virtual address space of the segment. This means it is not included in | |||
457 | // the segment and we should ignore it. | |||
458 | if (SHdr.sh_size == 0 && (SHdr.sh_offset == Phdr.p_offset || | |||
459 | SHdr.sh_offset == Phdr.p_offset + Phdr.p_filesz)) | |||
460 | return VirtualAddressesMatch; | |||
461 | return true; | |||
462 | } | |||
463 | ||||
464 | // SHT_NOBITS sections usually occupy no physical space in a file. Such | |||
465 | // sections belong to a segment when they reside in the segment's virtual | |||
466 | // address space. | |||
467 | if (Sec.Type != ELF::SHT_NOBITS) | |||
468 | return false; | |||
469 | return VirtualAddressesMatch; | |||
470 | } | |||
471 | ||||
472 | template <class ELFT> | |||
473 | Expected<std::vector<ELFYAML::ProgramHeader>> | |||
474 | ELFDumper<ELFT>::dumpProgramHeaders( | |||
475 | ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Chunks) { | |||
476 | std::vector<ELFYAML::ProgramHeader> Ret; | |||
477 | Expected<typename ELFT::PhdrRange> PhdrsOrErr = Obj.program_headers(); | |||
478 | if (!PhdrsOrErr) | |||
479 | return PhdrsOrErr.takeError(); | |||
480 | ||||
481 | for (const typename ELFT::Phdr &Phdr : *PhdrsOrErr) { | |||
482 | ELFYAML::ProgramHeader PH; | |||
483 | PH.Type = Phdr.p_type; | |||
484 | PH.Flags = Phdr.p_flags; | |||
485 | PH.VAddr = Phdr.p_vaddr; | |||
486 | PH.PAddr = Phdr.p_paddr; | |||
487 | ||||
488 | // yaml2obj sets the alignment of a segment to 1 by default. | |||
489 | // We do not print the default alignment to reduce noise in the output. | |||
490 | if (Phdr.p_align != 1) | |||
491 | PH.Align = static_cast<llvm::yaml::Hex64>(Phdr.p_align); | |||
492 | ||||
493 | // Here we match sections with segments. | |||
494 | // It is not possible to have a non-Section chunk, because | |||
495 | // obj2yaml does not create Fill chunks. | |||
496 | for (const std::unique_ptr<ELFYAML::Chunk> &C : Chunks) { | |||
497 | ELFYAML::Section &S = cast<ELFYAML::Section>(*C); | |||
498 | if (isInSegment<ELFT>(S, Sections[S.OriginalSecNdx], Phdr)) { | |||
499 | if (!PH.FirstSec) | |||
500 | PH.FirstSec = S.Name; | |||
501 | PH.LastSec = S.Name; | |||
502 | PH.Chunks.push_back(C.get()); | |||
503 | } | |||
504 | } | |||
505 | ||||
506 | Ret.push_back(PH); | |||
507 | } | |||
508 | ||||
509 | return Ret; | |||
510 | } | |||
511 | ||||
512 | template <class ELFT> | |||
513 | std::optional<DWARFYAML::Data> ELFDumper<ELFT>::dumpDWARFSections( | |||
514 | std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections) { | |||
515 | DWARFYAML::Data DWARF; | |||
516 | for (std::unique_ptr<ELFYAML::Chunk> &C : Sections) { | |||
517 | if (!C->Name.startswith(".debug_")) | |||
518 | continue; | |||
519 | ||||
520 | if (ELFYAML::RawContentSection *RawSec = | |||
521 | dyn_cast<ELFYAML::RawContentSection>(C.get())) { | |||
522 | // FIXME: The dumpDebug* functions should take the content as stored in | |||
523 | // RawSec. Currently, they just use the last section with the matching | |||
524 | // name, which defeats this attempt to skip reading a section header | |||
525 | // string table with the same name as a DWARF section. | |||
526 | if (ShStrTabIndex && RawSec->OriginalSecNdx == *ShStrTabIndex) | |||
527 | continue; | |||
528 | Error Err = Error::success(); | |||
529 | cantFail(std::move(Err)); | |||
530 | ||||
531 | if (RawSec->Name == ".debug_aranges") | |||
532 | Err = dumpDebugARanges(*DWARFCtx, DWARF); | |||
533 | else if (RawSec->Name == ".debug_str") | |||
534 | Err = dumpDebugStrings(*DWARFCtx, DWARF); | |||
535 | else if (RawSec->Name == ".debug_ranges") | |||
536 | Err = dumpDebugRanges(*DWARFCtx, DWARF); | |||
537 | else if (RawSec->Name == ".debug_addr") | |||
538 | Err = dumpDebugAddr(*DWARFCtx, DWARF); | |||
539 | else | |||
540 | continue; | |||
541 | ||||
542 | // If the DWARF section cannot be successfully parsed, emit raw content | |||
543 | // instead of an entry in the DWARF section of the YAML. | |||
544 | if (Err) | |||
545 | consumeError(std::move(Err)); | |||
546 | else | |||
547 | RawSec->Content.reset(); | |||
548 | } | |||
549 | } | |||
550 | ||||
551 | if (DWARF.getNonEmptySectionNames().empty()) | |||
552 | return std::nullopt; | |||
553 | return DWARF; | |||
554 | } | |||
555 | ||||
556 | template <class ELFT> | |||
557 | Expected<ELFYAML::RawContentSection *> | |||
558 | ELFDumper<ELFT>::dumpPlaceholderSection(const Elf_Shdr *Shdr) { | |||
559 | auto S = std::make_unique<ELFYAML::RawContentSection>(); | |||
560 | if (Error E = dumpCommonSection(Shdr, *S.get())) | |||
561 | return std::move(E); | |||
562 | ||||
563 | // Normally symbol tables should not be empty. We dump the "Size" | |||
564 | // key when they are. | |||
565 | if ((Shdr->sh_type == ELF::SHT_SYMTAB || Shdr->sh_type == ELF::SHT_DYNSYM) && | |||
566 | !Shdr->sh_size) | |||
567 | S->Size.emplace(); | |||
568 | ||||
569 | return S.release(); | |||
570 | } | |||
571 | ||||
572 | template <class ELFT> | |||
573 | Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> | |||
574 | ELFDumper<ELFT>::dumpSections() { | |||
575 | std::vector<std::unique_ptr<ELFYAML::Chunk>> Ret; | |||
576 | auto Add = [&](Expected<ELFYAML::Chunk *> SecOrErr) -> Error { | |||
577 | if (!SecOrErr) | |||
578 | return SecOrErr.takeError(); | |||
579 | Ret.emplace_back(*SecOrErr); | |||
580 | return Error::success(); | |||
581 | }; | |||
582 | ||||
583 | auto GetDumper = [this](unsigned Type) | |||
584 | -> std::function<Expected<ELFYAML::Chunk *>(const Elf_Shdr *)> { | |||
585 | if (Obj.getHeader().e_machine == ELF::EM_ARM && Type == ELF::SHT_ARM_EXIDX) | |||
586 | return [this](const Elf_Shdr *S) { return dumpARMIndexTableSection(S); }; | |||
587 | ||||
588 | if (Obj.getHeader().e_machine == ELF::EM_MIPS && | |||
589 | Type == ELF::SHT_MIPS_ABIFLAGS) | |||
590 | return [this](const Elf_Shdr *S) { return dumpMipsABIFlags(S); }; | |||
591 | ||||
592 | switch (Type) { | |||
593 | case ELF::SHT_DYNAMIC: | |||
594 | return [this](const Elf_Shdr *S) { return dumpDynamicSection(S); }; | |||
595 | case ELF::SHT_SYMTAB_SHNDX: | |||
596 | return [this](const Elf_Shdr *S) { return dumpSymtabShndxSection(S); }; | |||
597 | case ELF::SHT_REL: | |||
598 | case ELF::SHT_RELA: | |||
599 | return [this](const Elf_Shdr *S) { return dumpRelocSection(S); }; | |||
600 | case ELF::SHT_RELR: | |||
601 | return [this](const Elf_Shdr *S) { return dumpRelrSection(S); }; | |||
602 | case ELF::SHT_GROUP: | |||
603 | return [this](const Elf_Shdr *S) { return dumpGroupSection(S); }; | |||
604 | case ELF::SHT_NOBITS: | |||
605 | return [this](const Elf_Shdr *S) { return dumpNoBitsSection(S); }; | |||
606 | case ELF::SHT_NOTE: | |||
607 | return [this](const Elf_Shdr *S) { return dumpNoteSection(S); }; | |||
608 | case ELF::SHT_HASH: | |||
609 | return [this](const Elf_Shdr *S) { return dumpHashSection(S); }; | |||
610 | case ELF::SHT_GNU_HASH: | |||
611 | return [this](const Elf_Shdr *S) { return dumpGnuHashSection(S); }; | |||
612 | case ELF::SHT_GNU_verdef: | |||
613 | return [this](const Elf_Shdr *S) { return dumpVerdefSection(S); }; | |||
614 | case ELF::SHT_GNU_versym: | |||
615 | return [this](const Elf_Shdr *S) { return dumpSymverSection(S); }; | |||
616 | case ELF::SHT_GNU_verneed: | |||
617 | return [this](const Elf_Shdr *S) { return dumpVerneedSection(S); }; | |||
618 | case ELF::SHT_LLVM_ADDRSIG: | |||
619 | return [this](const Elf_Shdr *S) { return dumpAddrsigSection(S); }; | |||
620 | case ELF::SHT_LLVM_LINKER_OPTIONS: | |||
621 | return [this](const Elf_Shdr *S) { return dumpLinkerOptionsSection(S); }; | |||
622 | case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: | |||
623 | return [this](const Elf_Shdr *S) { | |||
624 | return dumpDependentLibrariesSection(S); | |||
625 | }; | |||
626 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: | |||
627 | return | |||
628 | [this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(S); }; | |||
| ||||
629 | case ELF::SHT_LLVM_BB_ADDR_MAP_V0: | |||
630 | case ELF::SHT_LLVM_BB_ADDR_MAP: | |||
631 | return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(S); }; | |||
632 | case ELF::SHT_STRTAB: | |||
633 | case ELF::SHT_SYMTAB: | |||
634 | case ELF::SHT_DYNSYM: | |||
635 | // The contents of these sections are described by other parts of the YAML | |||
636 | // file. But we still want to dump them, because their properties can be | |||
637 | // important. See comments for 'shouldPrintSection()' for more details. | |||
638 | return [this](const Elf_Shdr *S) { return dumpPlaceholderSection(S); }; | |||
639 | default: | |||
640 | return nullptr; | |||
641 | } | |||
642 | }; | |||
643 | ||||
644 | for (const Elf_Shdr &Sec : Sections) { | |||
645 | // We have dedicated dumping functions for most of the section types. | |||
646 | // Try to use one of them first. | |||
647 | if (std::function<Expected<ELFYAML::Chunk *>(const Elf_Shdr *)> DumpFn = | |||
648 | GetDumper(Sec.sh_type)) { | |||
649 | if (Error E = Add(DumpFn(&Sec))) | |||
650 | return std::move(E); | |||
651 | continue; | |||
652 | } | |||
653 | ||||
654 | // Recognize some special SHT_PROGBITS sections by name. | |||
655 | if (Sec.sh_type == ELF::SHT_PROGBITS) { | |||
656 | auto NameOrErr = Obj.getSectionName(Sec); | |||
657 | if (!NameOrErr) | |||
658 | return NameOrErr.takeError(); | |||
659 | ||||
660 | if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr)) { | |||
661 | if (Error E = Add(dumpStackSizesSection(&Sec))) | |||
662 | return std::move(E); | |||
663 | continue; | |||
664 | } | |||
665 | } | |||
666 | ||||
667 | if (Error E = Add(dumpContentSection(&Sec))) | |||
668 | return std::move(E); | |||
669 | } | |||
670 | ||||
671 | return std::move(Ret); | |||
672 | } | |||
673 | ||||
674 | template <class ELFT> | |||
675 | Error ELFDumper<ELFT>::dumpSymbols( | |||
676 | const Elf_Shdr *Symtab, | |||
677 | std::optional<std::vector<ELFYAML::Symbol>> &Symbols) { | |||
678 | if (!Symtab) | |||
679 | return Error::success(); | |||
680 | ||||
681 | auto SymtabOrErr = Obj.symbols(Symtab); | |||
682 | if (!SymtabOrErr) | |||
683 | return SymtabOrErr.takeError(); | |||
684 | ||||
685 | if (SymtabOrErr->empty()) | |||
686 | return Error::success(); | |||
687 | ||||
688 | auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab); | |||
689 | if (!StrTableOrErr) | |||
690 | return StrTableOrErr.takeError(); | |||
691 | ||||
692 | if (Symtab->sh_type == ELF::SHT_SYMTAB) { | |||
693 | SymTable = *SymtabOrErr; | |||
694 | SymbolNames.resize(SymTable.size()); | |||
695 | } | |||
696 | ||||
697 | Symbols.emplace(); | |||
698 | for (const auto &Sym : (*SymtabOrErr).drop_front()) { | |||
699 | ELFYAML::Symbol S; | |||
700 | if (auto EC = dumpSymbol(&Sym, Symtab, *StrTableOrErr, S)) | |||
701 | return EC; | |||
702 | Symbols->push_back(S); | |||
703 | } | |||
704 | ||||
705 | return Error::success(); | |||
706 | } | |||
707 | ||||
708 | template <class ELFT> | |||
709 | Error ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, | |||
710 | StringRef StrTable, ELFYAML::Symbol &S) { | |||
711 | S.Type = Sym->getType(); | |||
712 | if (Sym->st_value) | |||
713 | S.Value = (yaml::Hex64)Sym->st_value; | |||
714 | if (Sym->st_size) | |||
715 | S.Size = (yaml::Hex64)Sym->st_size; | |||
716 | S.Other = Sym->st_other; | |||
717 | S.Binding = Sym->getBinding(); | |||
718 | ||||
719 | Expected<StringRef> SymbolNameOrErr = | |||
720 | getUniquedSymbolName(Sym, StrTable, SymTab); | |||
721 | if (!SymbolNameOrErr) | |||
722 | return SymbolNameOrErr.takeError(); | |||
723 | S.Name = SymbolNameOrErr.get(); | |||
724 | ||||
725 | if (Sym->st_shndx >= ELF::SHN_LORESERVE) { | |||
726 | S.Index = (ELFYAML::ELF_SHN)Sym->st_shndx; | |||
727 | return Error::success(); | |||
728 | } | |||
729 | ||||
730 | auto ShdrOrErr = Obj.getSection(*Sym, SymTab, ShndxTables.lookup(SymTab)); | |||
731 | if (!ShdrOrErr) | |||
732 | return ShdrOrErr.takeError(); | |||
733 | const Elf_Shdr *Shdr = *ShdrOrErr; | |||
734 | if (!Shdr) | |||
735 | return Error::success(); | |||
736 | ||||
737 | auto NameOrErr = getUniquedSectionName(*Shdr); | |||
738 | if (!NameOrErr) | |||
739 | return NameOrErr.takeError(); | |||
740 | S.Section = NameOrErr.get(); | |||
741 | ||||
742 | return Error::success(); | |||
743 | } | |||
744 | ||||
745 | template <class ELFT> | |||
746 | template <class RelT> | |||
747 | Error ELFDumper<ELFT>::dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab, | |||
748 | ELFYAML::Relocation &R) { | |||
749 | R.Type = Rel->getType(Obj.isMips64EL()); | |||
750 | R.Offset = Rel->r_offset; | |||
751 | R.Addend = 0; | |||
752 | ||||
753 | auto SymOrErr = Obj.getRelocationSymbol(*Rel, SymTab); | |||
754 | if (!SymOrErr) | |||
755 | return SymOrErr.takeError(); | |||
756 | ||||
757 | // We have might have a relocation with symbol index 0, | |||
758 | // e.g. R_X86_64_NONE or R_X86_64_GOTPC32. | |||
759 | const Elf_Sym *Sym = *SymOrErr; | |||
760 | if (!Sym) | |||
761 | return Error::success(); | |||
762 | ||||
763 | auto StrTabSec = Obj.getSection(SymTab->sh_link); | |||
764 | if (!StrTabSec) | |||
765 | return StrTabSec.takeError(); | |||
766 | auto StrTabOrErr = Obj.getStringTable(**StrTabSec); | |||
767 | if (!StrTabOrErr) | |||
768 | return StrTabOrErr.takeError(); | |||
769 | ||||
770 | Expected<StringRef> NameOrErr = | |||
771 | getUniquedSymbolName(Sym, *StrTabOrErr, SymTab); | |||
772 | if (!NameOrErr) | |||
773 | return NameOrErr.takeError(); | |||
774 | R.Symbol = NameOrErr.get(); | |||
775 | ||||
776 | return Error::success(); | |||
777 | } | |||
778 | ||||
779 | template <class ELFT> | |||
780 | Error ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr, | |||
781 | ELFYAML::Section &S) { | |||
782 | // Dump fields. We do not dump the ShOffset field. When not explicitly | |||
783 | // set, the value is set by yaml2obj automatically. | |||
784 | S.Type = Shdr->sh_type; | |||
785 | if (Shdr->sh_flags) | |||
786 | S.Flags = static_cast<ELFYAML::ELF_SHF>(Shdr->sh_flags); | |||
787 | if (Shdr->sh_addr) | |||
788 | S.Address = static_cast<uint64_t>(Shdr->sh_addr); | |||
789 | S.AddressAlign = Shdr->sh_addralign; | |||
790 | ||||
791 | S.OriginalSecNdx = Shdr - &Sections[0]; | |||
792 | ||||
793 | Expected<StringRef> NameOrErr = getUniquedSectionName(*Shdr); | |||
794 | if (!NameOrErr) | |||
795 | return NameOrErr.takeError(); | |||
796 | S.Name = NameOrErr.get(); | |||
797 | ||||
798 | if (Shdr->sh_entsize != ELFYAML::getDefaultShEntSize<ELFT>( | |||
799 | Obj.getHeader().e_machine, S.Type, S.Name)) | |||
800 | S.EntSize = static_cast<llvm::yaml::Hex64>(Shdr->sh_entsize); | |||
801 | ||||
802 | if (Shdr->sh_link != ELF::SHN_UNDEF) { | |||
803 | Expected<const Elf_Shdr *> LinkSection = Obj.getSection(Shdr->sh_link); | |||
804 | if (!LinkSection) | |||
805 | return make_error<StringError>( | |||
806 | "unable to resolve sh_link reference in section '" + S.Name + | |||
807 | "': " + toString(LinkSection.takeError()), | |||
808 | inconvertibleErrorCode()); | |||
809 | ||||
810 | NameOrErr = getUniquedSectionName(**LinkSection); | |||
811 | if (!NameOrErr) | |||
812 | return NameOrErr.takeError(); | |||
813 | S.Link = NameOrErr.get(); | |||
814 | } | |||
815 | ||||
816 | return Error::success(); | |||
817 | } | |||
818 | ||||
819 | template <class ELFT> | |||
820 | Error ELFDumper<ELFT>::dumpCommonRelocationSection( | |||
821 | const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S) { | |||
822 | if (Error E = dumpCommonSection(Shdr, S)) | |||
823 | return E; | |||
824 | ||||
825 | // Having a zero sh_info field is normal: .rela.dyn is a dynamic | |||
826 | // relocation section that normally has no value in this field. | |||
827 | if (!Shdr->sh_info) | |||
828 | return Error::success(); | |||
829 | ||||
830 | auto InfoSection = Obj.getSection(Shdr->sh_info); | |||
831 | if (!InfoSection) | |||
832 | return InfoSection.takeError(); | |||
833 | ||||
834 | Expected<StringRef> NameOrErr = getUniquedSectionName(**InfoSection); | |||
835 | if (!NameOrErr) | |||
836 | return NameOrErr.takeError(); | |||
837 | S.RelocatableSec = NameOrErr.get(); | |||
838 | ||||
839 | return Error::success(); | |||
840 | } | |||
841 | ||||
842 | template <class ELFT> | |||
843 | Expected<ELFYAML::StackSizesSection *> | |||
844 | ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) { | |||
845 | auto S = std::make_unique<ELFYAML::StackSizesSection>(); | |||
846 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
847 | return std::move(E); | |||
848 | ||||
849 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
850 | if (!ContentOrErr) | |||
851 | return ContentOrErr.takeError(); | |||
852 | ||||
853 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
854 | DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4); | |||
855 | ||||
856 | std::vector<ELFYAML::StackSizeEntry> Entries; | |||
857 | DataExtractor::Cursor Cur(0); | |||
858 | while (Cur && Cur.tell() < Content.size()) { | |||
859 | uint64_t Address = Data.getAddress(Cur); | |||
860 | uint64_t Size = Data.getULEB128(Cur); | |||
861 | Entries.push_back({Address, Size}); | |||
862 | } | |||
863 | ||||
864 | if (Content.empty() || !Cur) { | |||
865 | // If .stack_sizes cannot be decoded, we dump it as an array of bytes. | |||
866 | consumeError(Cur.takeError()); | |||
867 | S->Content = yaml::BinaryRef(Content); | |||
868 | } else { | |||
869 | S->Entries = std::move(Entries); | |||
870 | } | |||
871 | ||||
872 | return S.release(); | |||
873 | } | |||
874 | ||||
875 | template <class ELFT> | |||
876 | Expected<ELFYAML::BBAddrMapSection *> | |||
877 | ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) { | |||
878 | auto S = std::make_unique<ELFYAML::BBAddrMapSection>(); | |||
879 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
880 | return std::move(E); | |||
881 | ||||
882 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
883 | if (!ContentOrErr) | |||
884 | return ContentOrErr.takeError(); | |||
885 | ||||
886 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
887 | if (Content.empty()) | |||
888 | return S.release(); | |||
889 | ||||
890 | DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4); | |||
891 | ||||
892 | std::vector<ELFYAML::BBAddrMapEntry> Entries; | |||
893 | DataExtractor::Cursor Cur(0); | |||
894 | uint8_t Version = 0; | |||
895 | uint8_t Feature = 0; | |||
896 | while (Cur && Cur.tell() < Content.size()) { | |||
897 | if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) { | |||
898 | Version = Data.getU8(Cur); | |||
899 | if (Cur && Version > 2) | |||
900 | return createStringError( | |||
901 | errc::invalid_argument, | |||
902 | "invalid SHT_LLVM_BB_ADDR_MAP section version: " + | |||
903 | Twine(static_cast<int>(Version))); | |||
904 | Feature = Data.getU8(Cur); | |||
905 | } | |||
906 | uint64_t Address = Data.getAddress(Cur); | |||
907 | uint64_t NumBlocks = Data.getULEB128(Cur); | |||
908 | std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries; | |||
909 | // Read the specified number of BB entries, or until decoding fails. | |||
910 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks; ++BlockIndex) { | |||
911 | uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex; | |||
912 | uint64_t Offset = Data.getULEB128(Cur); | |||
913 | uint64_t Size = Data.getULEB128(Cur); | |||
914 | uint64_t Metadata = Data.getULEB128(Cur); | |||
915 | BBEntries.push_back({ID, Offset, Size, Metadata}); | |||
916 | } | |||
917 | Entries.push_back( | |||
918 | {Version, Feature, Address, /*NumBlocks=*/{}, std::move(BBEntries)}); | |||
919 | } | |||
920 | ||||
921 | if (!Cur) { | |||
922 | // If the section cannot be decoded, we dump it as an array of bytes. | |||
923 | consumeError(Cur.takeError()); | |||
924 | S->Content = yaml::BinaryRef(Content); | |||
925 | } else { | |||
926 | S->Entries = std::move(Entries); | |||
927 | } | |||
928 | ||||
929 | return S.release(); | |||
930 | } | |||
931 | ||||
932 | template <class ELFT> | |||
933 | Expected<ELFYAML::AddrsigSection *> | |||
934 | ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) { | |||
935 | auto S = std::make_unique<ELFYAML::AddrsigSection>(); | |||
936 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
937 | return std::move(E); | |||
938 | ||||
939 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
940 | if (!ContentOrErr) | |||
941 | return ContentOrErr.takeError(); | |||
942 | ||||
943 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
944 | DataExtractor::Cursor Cur(0); | |||
945 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); | |||
946 | std::vector<ELFYAML::YAMLFlowString> Symbols; | |||
947 | while (Cur && Cur.tell() < Content.size()) { | |||
948 | uint64_t SymNdx = Data.getULEB128(Cur); | |||
949 | if (!Cur) | |||
950 | break; | |||
951 | ||||
952 | Expected<StringRef> SymbolName = getSymbolName(Shdr->sh_link, SymNdx); | |||
953 | if (!SymbolName || SymbolName->empty()) { | |||
954 | consumeError(SymbolName.takeError()); | |||
955 | Symbols.emplace_back( | |||
956 | StringRef(std::to_string(SymNdx)).copy(StringAllocator)); | |||
957 | continue; | |||
958 | } | |||
959 | ||||
960 | Symbols.emplace_back(*SymbolName); | |||
961 | } | |||
962 | ||||
963 | if (Cur) { | |||
964 | S->Symbols = std::move(Symbols); | |||
965 | return S.release(); | |||
966 | } | |||
967 | ||||
968 | consumeError(Cur.takeError()); | |||
969 | S->Content = yaml::BinaryRef(Content); | |||
970 | return S.release(); | |||
971 | } | |||
972 | ||||
973 | template <class ELFT> | |||
974 | Expected<ELFYAML::LinkerOptionsSection *> | |||
975 | ELFDumper<ELFT>::dumpLinkerOptionsSection(const Elf_Shdr *Shdr) { | |||
976 | auto S = std::make_unique<ELFYAML::LinkerOptionsSection>(); | |||
977 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
978 | return std::move(E); | |||
979 | ||||
980 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
981 | if (!ContentOrErr) | |||
982 | return ContentOrErr.takeError(); | |||
983 | ||||
984 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
985 | if (Content.empty() || Content.back() != 0) { | |||
986 | S->Content = Content; | |||
987 | return S.release(); | |||
988 | } | |||
989 | ||||
990 | SmallVector<StringRef, 16> Strings; | |||
991 | toStringRef(Content.drop_back()).split(Strings, '\0'); | |||
992 | if (Strings.size() % 2 != 0) { | |||
993 | S->Content = Content; | |||
994 | return S.release(); | |||
995 | } | |||
996 | ||||
997 | S->Options.emplace(); | |||
998 | for (size_t I = 0, E = Strings.size(); I != E; I += 2) | |||
999 | S->Options->push_back({Strings[I], Strings[I + 1]}); | |||
1000 | ||||
1001 | return S.release(); | |||
1002 | } | |||
1003 | ||||
1004 | template <class ELFT> | |||
1005 | Expected<ELFYAML::DependentLibrariesSection *> | |||
1006 | ELFDumper<ELFT>::dumpDependentLibrariesSection(const Elf_Shdr *Shdr) { | |||
1007 | auto DL = std::make_unique<ELFYAML::DependentLibrariesSection>(); | |||
1008 | if (Error E = dumpCommonSection(Shdr, *DL)) | |||
1009 | return std::move(E); | |||
1010 | ||||
1011 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1012 | if (!ContentOrErr) | |||
1013 | return ContentOrErr.takeError(); | |||
1014 | ||||
1015 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1016 | if (!Content.empty() && Content.back() != 0) { | |||
1017 | DL->Content = Content; | |||
1018 | return DL.release(); | |||
1019 | } | |||
1020 | ||||
1021 | DL->Libs.emplace(); | |||
1022 | for (const uint8_t *I = Content.begin(), *E = Content.end(); I < E;) { | |||
1023 | StringRef Lib((const char *)I); | |||
1024 | DL->Libs->emplace_back(Lib); | |||
1025 | I += Lib.size() + 1; | |||
1026 | } | |||
1027 | ||||
1028 | return DL.release(); | |||
1029 | } | |||
1030 | ||||
1031 | template <class ELFT> | |||
1032 | Expected<ELFYAML::CallGraphProfileSection *> | |||
1033 | ELFDumper<ELFT>::dumpCallGraphProfileSection(const Elf_Shdr *Shdr) { | |||
1034 | auto S = std::make_unique<ELFYAML::CallGraphProfileSection>(); | |||
1035 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1036 | return std::move(E); | |||
1037 | ||||
1038 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1039 | if (!ContentOrErr) | |||
1040 | return ContentOrErr.takeError(); | |||
1041 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1042 | const uint32_t SizeOfEntry = ELFYAML::getDefaultShEntSize<ELFT>( | |||
1043 | Obj.getHeader().e_machine, S->Type, S->Name); | |||
1044 | // Dump the section by using the Content key when it is truncated. | |||
1045 | // There is no need to create either "Content" or "Entries" fields when the | |||
1046 | // section is empty. | |||
1047 | if (Content.empty() || Content.size() % SizeOfEntry != 0) { | |||
| ||||
1048 | if (!Content.empty()) | |||
1049 | S->Content = yaml::BinaryRef(Content); | |||
1050 | return S.release(); | |||
1051 | } | |||
1052 | ||||
1053 | std::vector<ELFYAML::CallGraphEntryWeight> Entries(Content.size() / | |||
1054 | SizeOfEntry); | |||
1055 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); | |||
1056 | DataExtractor::Cursor Cur(0); | |||
1057 | auto ReadEntry = [&](ELFYAML::CallGraphEntryWeight &E) { | |||
1058 | E.Weight = Data.getU64(Cur); | |||
1059 | if (!Cur) { | |||
1060 | consumeError(Cur.takeError()); | |||
1061 | return false; | |||
1062 | } | |||
1063 | return true; | |||
1064 | }; | |||
1065 | ||||
1066 | for (ELFYAML::CallGraphEntryWeight &E : Entries) { | |||
1067 | if (ReadEntry(E)) | |||
1068 | continue; | |||
1069 | S->Content = yaml::BinaryRef(Content); | |||
1070 | return S.release(); | |||
1071 | } | |||
1072 | ||||
1073 | S->Entries = std::move(Entries); | |||
1074 | return S.release(); | |||
1075 | } | |||
1076 | ||||
1077 | template <class ELFT> | |||
1078 | Expected<ELFYAML::DynamicSection *> | |||
1079 | ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) { | |||
1080 | auto S = std::make_unique<ELFYAML::DynamicSection>(); | |||
1081 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1082 | return std::move(E); | |||
1083 | ||||
1084 | auto DynTagsOrErr = Obj.template getSectionContentsAsArray<Elf_Dyn>(*Shdr); | |||
1085 | if (!DynTagsOrErr) | |||
1086 | return DynTagsOrErr.takeError(); | |||
1087 | ||||
1088 | S->Entries.emplace(); | |||
1089 | for (const Elf_Dyn &Dyn : *DynTagsOrErr) | |||
1090 | S->Entries->push_back({(ELFYAML::ELF_DYNTAG)Dyn.getTag(), Dyn.getVal()}); | |||
1091 | ||||
1092 | return S.release(); | |||
1093 | } | |||
1094 | ||||
1095 | template <class ELFT> | |||
1096 | Expected<ELFYAML::RelocationSection *> | |||
1097 | ELFDumper<ELFT>::dumpRelocSection(const Elf_Shdr *Shdr) { | |||
1098 | auto S = std::make_unique<ELFYAML::RelocationSection>(); | |||
1099 | if (auto E = dumpCommonRelocationSection(Shdr, *S)) | |||
1100 | return std::move(E); | |||
1101 | ||||
1102 | auto SymTabOrErr = Obj.getSection(Shdr->sh_link); | |||
1103 | if (!SymTabOrErr) | |||
1104 | return SymTabOrErr.takeError(); | |||
1105 | ||||
1106 | if (Shdr->sh_size != 0) | |||
1107 | S->Relocations.emplace(); | |||
1108 | ||||
1109 | if (Shdr->sh_type == ELF::SHT_REL) { | |||
1110 | auto Rels = Obj.rels(*Shdr); | |||
1111 | if (!Rels) | |||
1112 | return Rels.takeError(); | |||
1113 | for (const Elf_Rel &Rel : *Rels) { | |||
1114 | ELFYAML::Relocation R; | |||
1115 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) | |||
1116 | return std::move(E); | |||
1117 | S->Relocations->push_back(R); | |||
1118 | } | |||
1119 | } else { | |||
1120 | auto Rels = Obj.relas(*Shdr); | |||
1121 | if (!Rels) | |||
1122 | return Rels.takeError(); | |||
1123 | for (const Elf_Rela &Rel : *Rels) { | |||
1124 | ELFYAML::Relocation R; | |||
1125 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) | |||
1126 | return std::move(E); | |||
1127 | R.Addend = Rel.r_addend; | |||
1128 | S->Relocations->push_back(R); | |||
1129 | } | |||
1130 | } | |||
1131 | ||||
1132 | return S.release(); | |||
1133 | } | |||
1134 | ||||
1135 | template <class ELFT> | |||
1136 | Expected<ELFYAML::RelrSection *> | |||
1137 | ELFDumper<ELFT>::dumpRelrSection(const Elf_Shdr *Shdr) { | |||
1138 | auto S = std::make_unique<ELFYAML::RelrSection>(); | |||
1139 | if (auto E = dumpCommonSection(Shdr, *S)) | |||
1140 | return std::move(E); | |||
1141 | ||||
1142 | if (Expected<ArrayRef<Elf_Relr>> Relrs = Obj.relrs(*Shdr)) { | |||
1143 | S->Entries.emplace(); | |||
1144 | for (Elf_Relr Rel : *Relrs) | |||
1145 | S->Entries->emplace_back(Rel); | |||
1146 | return S.release(); | |||
1147 | } else { | |||
1148 | // Ignore. We are going to dump the data as raw content below. | |||
1149 | consumeError(Relrs.takeError()); | |||
1150 | } | |||
1151 | ||||
1152 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1153 | if (!ContentOrErr) | |||
1154 | return ContentOrErr.takeError(); | |||
1155 | S->Content = *ContentOrErr; | |||
1156 | return S.release(); | |||
1157 | } | |||
1158 | ||||
1159 | template <class ELFT> | |||
1160 | Expected<ELFYAML::RawContentSection *> | |||
1161 | ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { | |||
1162 | auto S = std::make_unique<ELFYAML::RawContentSection>(); | |||
1163 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1164 | return std::move(E); | |||
1165 | ||||
1166 | unsigned SecIndex = Shdr - &Sections[0]; | |||
1167 | if (SecIndex != 0 || Shdr->sh_type != ELF::SHT_NULL) { | |||
1168 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1169 | if (!ContentOrErr) | |||
1170 | return ContentOrErr.takeError(); | |||
1171 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1172 | if (!Content.empty()) | |||
1173 | S->Content = yaml::BinaryRef(Content); | |||
1174 | } else { | |||
1175 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); | |||
1176 | } | |||
1177 | ||||
1178 | if (Shdr->sh_info) | |||
1179 | S->Info = static_cast<llvm::yaml::Hex64>(Shdr->sh_info); | |||
1180 | return S.release(); | |||
1181 | } | |||
1182 | ||||
1183 | template <class ELFT> | |||
1184 | Expected<ELFYAML::SymtabShndxSection *> | |||
1185 | ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) { | |||
1186 | auto S = std::make_unique<ELFYAML::SymtabShndxSection>(); | |||
1187 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1188 | return std::move(E); | |||
1189 | ||||
1190 | auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); | |||
1191 | if (!EntriesOrErr) | |||
1192 | return EntriesOrErr.takeError(); | |||
1193 | ||||
1194 | S->Entries.emplace(); | |||
1195 | for (const Elf_Word &E : *EntriesOrErr) | |||
1196 | S->Entries->push_back(E); | |||
1197 | return S.release(); | |||
1198 | } | |||
1199 | ||||
1200 | template <class ELFT> | |||
1201 | Expected<ELFYAML::NoBitsSection *> | |||
1202 | ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { | |||
1203 | auto S = std::make_unique<ELFYAML::NoBitsSection>(); | |||
1204 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1205 | return std::move(E); | |||
1206 | if (Shdr->sh_size) | |||
1207 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); | |||
1208 | return S.release(); | |||
1209 | } | |||
1210 | ||||
1211 | template <class ELFT> | |||
1212 | Expected<ELFYAML::NoteSection *> | |||
1213 | ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) { | |||
1214 | auto S = std::make_unique<ELFYAML::NoteSection>(); | |||
1215 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1216 | return std::move(E); | |||
1217 | ||||
1218 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1219 | if (!ContentOrErr) | |||
1220 | return ContentOrErr.takeError(); | |||
1221 | ||||
1222 | std::vector<ELFYAML::NoteEntry> Entries; | |||
1223 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1224 | while (!Content.empty()) { | |||
1225 | if (Content.size() < sizeof(Elf_Nhdr)) { | |||
1226 | S->Content = yaml::BinaryRef(*ContentOrErr); | |||
1227 | return S.release(); | |||
1228 | } | |||
1229 | ||||
1230 | const Elf_Nhdr *Header = reinterpret_cast<const Elf_Nhdr *>(Content.data()); | |||
1231 | if (Content.size() < Header->getSize()) { | |||
1232 | S->Content = yaml::BinaryRef(*ContentOrErr); | |||
1233 | return S.release(); | |||
1234 | } | |||
1235 | ||||
1236 | Elf_Note Note(*Header); | |||
1237 | Entries.push_back( | |||
1238 | {Note.getName(), Note.getDesc(), (ELFYAML::ELF_NT)Note.getType()}); | |||
1239 | ||||
1240 | Content = Content.drop_front(Header->getSize()); | |||
1241 | } | |||
1242 | ||||
1243 | S->Notes = std::move(Entries); | |||
1244 | return S.release(); | |||
1245 | } | |||
1246 | ||||
1247 | template <class ELFT> | |||
1248 | Expected<ELFYAML::HashSection *> | |||
1249 | ELFDumper<ELFT>::dumpHashSection(const Elf_Shdr *Shdr) { | |||
1250 | auto S = std::make_unique<ELFYAML::HashSection>(); | |||
1251 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1252 | return std::move(E); | |||
1253 | ||||
1254 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1255 | if (!ContentOrErr) | |||
1256 | return ContentOrErr.takeError(); | |||
1257 | ||||
1258 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1259 | if (Content.size() % 4 != 0 || Content.size() < 8) { | |||
1260 | S->Content = yaml::BinaryRef(Content); | |||
1261 | return S.release(); | |||
1262 | } | |||
1263 | ||||
1264 | DataExtractor::Cursor Cur(0); | |||
1265 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); | |||
1266 | uint64_t NBucket = Data.getU32(Cur); | |||
1267 | uint64_t NChain = Data.getU32(Cur); | |||
1268 | if (Content.size() != (2 + NBucket + NChain) * 4) { | |||
1269 | S->Content = yaml::BinaryRef(Content); | |||
1270 | if (Cur) | |||
1271 | return S.release(); | |||
1272 | llvm_unreachable("entries were not read correctly")::llvm::llvm_unreachable_internal("entries were not read correctly" , "llvm/tools/obj2yaml/elf2yaml.cpp", 1272); | |||
1273 | } | |||
1274 | ||||
1275 | S->Bucket.emplace(NBucket); | |||
1276 | for (uint32_t &V : *S->Bucket) | |||
1277 | V = Data.getU32(Cur); | |||
1278 | ||||
1279 | S->Chain.emplace(NChain); | |||
1280 | for (uint32_t &V : *S->Chain) | |||
1281 | V = Data.getU32(Cur); | |||
1282 | ||||
1283 | if (Cur) | |||
1284 | return S.release(); | |||
1285 | llvm_unreachable("entries were not read correctly")::llvm::llvm_unreachable_internal("entries were not read correctly" , "llvm/tools/obj2yaml/elf2yaml.cpp", 1285); | |||
1286 | } | |||
1287 | ||||
1288 | template <class ELFT> | |||
1289 | Expected<ELFYAML::GnuHashSection *> | |||
1290 | ELFDumper<ELFT>::dumpGnuHashSection(const Elf_Shdr *Shdr) { | |||
1291 | auto S = std::make_unique<ELFYAML::GnuHashSection>(); | |||
1292 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1293 | return std::move(E); | |||
1294 | ||||
1295 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1296 | if (!ContentOrErr) | |||
1297 | return ContentOrErr.takeError(); | |||
1298 | ||||
1299 | unsigned AddrSize = ELFT::Is64Bits ? 8 : 4; | |||
1300 | ArrayRef<uint8_t> Content = *ContentOrErr; | |||
1301 | DataExtractor Data(Content, Obj.isLE(), AddrSize); | |||
1302 | ||||
1303 | ELFYAML::GnuHashHeader Header; | |||
1304 | DataExtractor::Cursor Cur(0); | |||
1305 | uint64_t NBuckets = Data.getU32(Cur); | |||
1306 | Header.SymNdx = Data.getU32(Cur); | |||
1307 | uint64_t MaskWords = Data.getU32(Cur); | |||
1308 | Header.Shift2 = Data.getU32(Cur); | |||
1309 | ||||
1310 | // Set just the raw binary content if we were unable to read the header | |||
1311 | // or when the section data is truncated or malformed. | |||
1312 | uint64_t Size = Data.getData().size() - Cur.tell(); | |||
1313 | if (!Cur || (Size < MaskWords * AddrSize + NBuckets * 4) || | |||
1314 | (Size % 4 != 0)) { | |||
1315 | consumeError(Cur.takeError()); | |||
1316 | S->Content = yaml::BinaryRef(Content); | |||
1317 | return S.release(); | |||
1318 | } | |||
1319 | ||||
1320 | S->Header = Header; | |||
1321 | ||||
1322 | S->BloomFilter.emplace(MaskWords); | |||
1323 | for (llvm::yaml::Hex64 &Val : *S->BloomFilter) | |||
1324 | Val = Data.getAddress(Cur); | |||
1325 | ||||
1326 | S->HashBuckets.emplace(NBuckets); | |||
1327 | for (llvm::yaml::Hex32 &Val : *S->HashBuckets) | |||
1328 | Val = Data.getU32(Cur); | |||
1329 | ||||
1330 | S->HashValues.emplace((Data.getData().size() - Cur.tell()) / 4); | |||
1331 | for (llvm::yaml::Hex32 &Val : *S->HashValues) | |||
1332 | Val = Data.getU32(Cur); | |||
1333 | ||||
1334 | if (Cur) | |||
1335 | return S.release(); | |||
1336 | llvm_unreachable("GnuHashSection was not read correctly")::llvm::llvm_unreachable_internal("GnuHashSection was not read correctly" , "llvm/tools/obj2yaml/elf2yaml.cpp", 1336); | |||
1337 | } | |||
1338 | ||||
1339 | template <class ELFT> | |||
1340 | Expected<ELFYAML::VerdefSection *> | |||
1341 | ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) { | |||
1342 | auto S = std::make_unique<ELFYAML::VerdefSection>(); | |||
1343 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1344 | return std::move(E); | |||
1345 | ||||
1346 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); | |||
1347 | if (!StringTableShdrOrErr) | |||
1348 | return StringTableShdrOrErr.takeError(); | |||
1349 | ||||
1350 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); | |||
1351 | if (!StringTableOrErr) | |||
1352 | return StringTableOrErr.takeError(); | |||
1353 | ||||
1354 | auto Contents = Obj.getSectionContents(*Shdr); | |||
1355 | if (!Contents) | |||
1356 | return Contents.takeError(); | |||
1357 | ||||
1358 | S->Entries.emplace(); | |||
1359 | ||||
1360 | llvm::ArrayRef<uint8_t> Data = *Contents; | |||
1361 | const uint8_t *Buf = Data.data(); | |||
1362 | while (Buf) { | |||
1363 | const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); | |||
1364 | ELFYAML::VerdefEntry Entry; | |||
1365 | if (Verdef->vd_version != 1) | |||
1366 | return createStringError(errc::invalid_argument, | |||
1367 | "invalid SHT_GNU_verdef section version: " + | |||
1368 | Twine(Verdef->vd_version)); | |||
1369 | ||||
1370 | if (Verdef->vd_flags != 0) | |||
1371 | Entry.Flags = Verdef->vd_flags; | |||
1372 | ||||
1373 | if (Verdef->vd_ndx != 0) | |||
1374 | Entry.VersionNdx = Verdef->vd_ndx; | |||
1375 | ||||
1376 | if (Verdef->vd_hash != 0) | |||
1377 | Entry.Hash = Verdef->vd_hash; | |||
1378 | ||||
1379 | const uint8_t *BufAux = Buf + Verdef->vd_aux; | |||
1380 | while (BufAux) { | |||
1381 | const Elf_Verdaux *Verdaux = | |||
1382 | reinterpret_cast<const Elf_Verdaux *>(BufAux); | |||
1383 | Entry.VerNames.push_back( | |||
1384 | StringTableOrErr->drop_front(Verdaux->vda_name).data()); | |||
1385 | BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; | |||
1386 | } | |||
1387 | ||||
1388 | S->Entries->push_back(Entry); | |||
1389 | Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; | |||
1390 | } | |||
1391 | ||||
1392 | if (Shdr->sh_info != S->Entries->size()) | |||
1393 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; | |||
1394 | ||||
1395 | return S.release(); | |||
1396 | } | |||
1397 | ||||
1398 | template <class ELFT> | |||
1399 | Expected<ELFYAML::SymverSection *> | |||
1400 | ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { | |||
1401 | auto S = std::make_unique<ELFYAML::SymverSection>(); | |||
1402 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1403 | return std::move(E); | |||
1404 | ||||
1405 | auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(*Shdr); | |||
1406 | if (!VersionsOrErr) | |||
1407 | return VersionsOrErr.takeError(); | |||
1408 | ||||
1409 | S->Entries.emplace(); | |||
1410 | for (const Elf_Half &E : *VersionsOrErr) | |||
1411 | S->Entries->push_back(E); | |||
1412 | ||||
1413 | return S.release(); | |||
1414 | } | |||
1415 | ||||
1416 | template <class ELFT> | |||
1417 | Expected<ELFYAML::VerneedSection *> | |||
1418 | ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { | |||
1419 | auto S = std::make_unique<ELFYAML::VerneedSection>(); | |||
1420 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1421 | return std::move(E); | |||
1422 | ||||
1423 | auto Contents = Obj.getSectionContents(*Shdr); | |||
1424 | if (!Contents) | |||
1425 | return Contents.takeError(); | |||
1426 | ||||
1427 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); | |||
1428 | if (!StringTableShdrOrErr) | |||
1429 | return StringTableShdrOrErr.takeError(); | |||
1430 | ||||
1431 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); | |||
1432 | if (!StringTableOrErr) | |||
1433 | return StringTableOrErr.takeError(); | |||
1434 | ||||
1435 | S->VerneedV.emplace(); | |||
1436 | ||||
1437 | llvm::ArrayRef<uint8_t> Data = *Contents; | |||
1438 | const uint8_t *Buf = Data.data(); | |||
1439 | while (Buf) { | |||
1440 | const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); | |||
1441 | ||||
1442 | ELFYAML::VerneedEntry Entry; | |||
1443 | Entry.Version = Verneed->vn_version; | |||
1444 | Entry.File = | |||
1445 | StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data()); | |||
1446 | ||||
1447 | const uint8_t *BufAux = Buf + Verneed->vn_aux; | |||
1448 | while (BufAux) { | |||
1449 | const Elf_Vernaux *Vernaux = | |||
1450 | reinterpret_cast<const Elf_Vernaux *>(BufAux); | |||
1451 | ||||
1452 | ELFYAML::VernauxEntry Aux; | |||
1453 | Aux.Hash = Vernaux->vna_hash; | |||
1454 | Aux.Flags = Vernaux->vna_flags; | |||
1455 | Aux.Other = Vernaux->vna_other; | |||
1456 | Aux.Name = | |||
1457 | StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data()); | |||
1458 | ||||
1459 | Entry.AuxV.push_back(Aux); | |||
1460 | BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; | |||
1461 | } | |||
1462 | ||||
1463 | S->VerneedV->push_back(Entry); | |||
1464 | Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; | |||
1465 | } | |||
1466 | ||||
1467 | if (Shdr->sh_info != S->VerneedV->size()) | |||
1468 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; | |||
1469 | ||||
1470 | return S.release(); | |||
1471 | } | |||
1472 | ||||
1473 | template <class ELFT> | |||
1474 | Expected<StringRef> ELFDumper<ELFT>::getSymbolName(uint32_t SymtabNdx, | |||
1475 | uint32_t SymbolNdx) { | |||
1476 | auto SymtabOrErr = Obj.getSection(SymtabNdx); | |||
1477 | if (!SymtabOrErr) | |||
1478 | return SymtabOrErr.takeError(); | |||
1479 | ||||
1480 | const Elf_Shdr *Symtab = *SymtabOrErr; | |||
1481 | auto SymOrErr = Obj.getSymbol(Symtab, SymbolNdx); | |||
1482 | if (!SymOrErr) | |||
1483 | return SymOrErr.takeError(); | |||
1484 | ||||
1485 | auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab); | |||
1486 | if (!StrTabOrErr) | |||
1487 | return StrTabOrErr.takeError(); | |||
1488 | return getUniquedSymbolName(*SymOrErr, *StrTabOrErr, Symtab); | |||
1489 | } | |||
1490 | ||||
1491 | template <class ELFT> | |||
1492 | Expected<ELFYAML::GroupSection *> | |||
1493 | ELFDumper<ELFT>::dumpGroupSection(const Elf_Shdr *Shdr) { | |||
1494 | auto S = std::make_unique<ELFYAML::GroupSection>(); | |||
1495 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1496 | return std::move(E); | |||
1497 | ||||
1498 | // Get symbol with index sh_info. This symbol's name is the signature of the group. | |||
1499 | Expected<StringRef> SymbolName = getSymbolName(Shdr->sh_link, Shdr->sh_info); | |||
1500 | if (!SymbolName) | |||
1501 | return SymbolName.takeError(); | |||
1502 | S->Signature = *SymbolName; | |||
1503 | ||||
1504 | auto MembersOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); | |||
1505 | if (!MembersOrErr) | |||
1506 | return MembersOrErr.takeError(); | |||
1507 | ||||
1508 | S->Members.emplace(); | |||
1509 | for (Elf_Word Member : *MembersOrErr) { | |||
1510 | if (Member == llvm::ELF::GRP_COMDAT) { | |||
1511 | S->Members->push_back({"GRP_COMDAT"}); | |||
1512 | continue; | |||
1513 | } | |||
1514 | ||||
1515 | Expected<const Elf_Shdr *> SHdrOrErr = Obj.getSection(Member); | |||
1516 | if (!SHdrOrErr) | |||
1517 | return SHdrOrErr.takeError(); | |||
1518 | Expected<StringRef> NameOrErr = getUniquedSectionName(**SHdrOrErr); | |||
1519 | if (!NameOrErr) | |||
1520 | return NameOrErr.takeError(); | |||
1521 | S->Members->push_back({*NameOrErr}); | |||
1522 | } | |||
1523 | return S.release(); | |||
1524 | } | |||
1525 | ||||
1526 | template <class ELFT> | |||
1527 | Expected<ELFYAML::ARMIndexTableSection *> | |||
1528 | ELFDumper<ELFT>::dumpARMIndexTableSection(const Elf_Shdr *Shdr) { | |||
1529 | auto S = std::make_unique<ELFYAML::ARMIndexTableSection>(); | |||
1530 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1531 | return std::move(E); | |||
1532 | ||||
1533 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1534 | if (!ContentOrErr) | |||
1535 | return ContentOrErr.takeError(); | |||
1536 | ||||
1537 | if (ContentOrErr->size() % (sizeof(Elf_Word) * 2) != 0) { | |||
1538 | S->Content = yaml::BinaryRef(*ContentOrErr); | |||
1539 | return S.release(); | |||
1540 | } | |||
1541 | ||||
1542 | ArrayRef<Elf_Word> Words( | |||
1543 | reinterpret_cast<const Elf_Word *>(ContentOrErr->data()), | |||
1544 | ContentOrErr->size() / sizeof(Elf_Word)); | |||
1545 | ||||
1546 | S->Entries.emplace(); | |||
1547 | for (size_t I = 0, E = Words.size(); I != E; I += 2) | |||
1548 | S->Entries->push_back({(yaml::Hex32)Words[I], (yaml::Hex32)Words[I + 1]}); | |||
1549 | ||||
1550 | return S.release(); | |||
1551 | } | |||
1552 | ||||
1553 | template <class ELFT> | |||
1554 | Expected<ELFYAML::MipsABIFlags *> | |||
1555 | ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) { | |||
1556 | assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS &&(static_cast <bool> (Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && "Section type is not SHT_MIPS_ABIFLAGS") ? void ( 0) : __assert_fail ("Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && \"Section type is not SHT_MIPS_ABIFLAGS\"" , "llvm/tools/obj2yaml/elf2yaml.cpp", 1557, __extension__ __PRETTY_FUNCTION__ )) | |||
1557 | "Section type is not SHT_MIPS_ABIFLAGS")(static_cast <bool> (Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && "Section type is not SHT_MIPS_ABIFLAGS") ? void ( 0) : __assert_fail ("Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && \"Section type is not SHT_MIPS_ABIFLAGS\"" , "llvm/tools/obj2yaml/elf2yaml.cpp", 1557, __extension__ __PRETTY_FUNCTION__ )); | |||
1558 | auto S = std::make_unique<ELFYAML::MipsABIFlags>(); | |||
1559 | if (Error E = dumpCommonSection(Shdr, *S)) | |||
1560 | return std::move(E); | |||
1561 | ||||
1562 | auto ContentOrErr = Obj.getSectionContents(*Shdr); | |||
1563 | if (!ContentOrErr) | |||
1564 | return ContentOrErr.takeError(); | |||
1565 | ||||
1566 | auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>( | |||
1567 | ContentOrErr.get().data()); | |||
1568 | S->Version = Flags->version; | |||
1569 | S->ISALevel = Flags->isa_level; | |||
1570 | S->ISARevision = Flags->isa_rev; | |||
1571 | S->GPRSize = Flags->gpr_size; | |||
1572 | S->CPR1Size = Flags->cpr1_size; | |||
1573 | S->CPR2Size = Flags->cpr2_size; | |||
1574 | S->FpABI = Flags->fp_abi; | |||
1575 | S->ISAExtension = Flags->isa_ext; | |||
1576 | S->ASEs = Flags->ases; | |||
1577 | S->Flags1 = Flags->flags1; | |||
1578 | S->Flags2 = Flags->flags2; | |||
1579 | return S.release(); | |||
1580 | } | |||
1581 | ||||
1582 | template <class ELFT> | |||
1583 | static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj, | |||
1584 | std::unique_ptr<DWARFContext> DWARFCtx) { | |||
1585 | ELFDumper<ELFT> Dumper(Obj, std::move(DWARFCtx)); | |||
1586 | Expected<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); | |||
1587 | if (!YAMLOrErr) | |||
1588 | return YAMLOrErr.takeError(); | |||
1589 | ||||
1590 | std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); | |||
1591 | yaml::Output Yout(Out); | |||
1592 | Yout << *YAML; | |||
1593 | ||||
1594 | return Error::success(); | |||
1595 | } | |||
1596 | ||||
1597 | Error elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { | |||
1598 | std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); | |||
1599 | if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj)) | |||
1600 | return elf2yaml(Out, ELFObj->getELFFile(), std::move(DWARFCtx)); | |||
1601 | ||||
1602 | if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(&Obj)) | |||
1603 | return elf2yaml(Out, ELFObj->getELFFile(), std::move(DWARFCtx)); | |||
1604 | ||||
1605 | if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(&Obj)) | |||
1606 | return elf2yaml(Out, ELFObj->getELFFile(), std::move(DWARFCtx)); | |||
1607 | ||||
1608 | if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj)) | |||
1609 | return elf2yaml(Out, ELFObj->getELFFile(), std::move(DWARFCtx)); | |||
1610 | ||||
1611 | llvm_unreachable("unknown ELF file format")::llvm::llvm_unreachable_internal("unknown ELF file format", "llvm/tools/obj2yaml/elf2yaml.cpp" , 1611); | |||
1612 | } |
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)struct ELF_ET { ELF_ET() = default; ELF_ET(const uint16_t v) : value(v) {} ELF_ET(const ELF_ET &v) = default; ELF_ET & operator=(const ELF_ET &rhs) = default; ELF_ET &operator =(const uint16_t &rhs) { value = rhs; return *this; } operator const uint16_t & () const { return value; } bool operator ==(const ELF_ET &rhs) const { return value == rhs.value; } bool operator==(const uint16_t &rhs) const { return value == rhs; } bool operator<(const ELF_ET &rhs) const { return value < rhs.value; } uint16_t value; using BaseType = uint16_t ; }; |
46 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PT)struct ELF_PT { ELF_PT() = default; ELF_PT(const uint32_t v) : value(v) {} ELF_PT(const ELF_PT &v) = default; ELF_PT & operator=(const ELF_PT &rhs) = default; ELF_PT &operator =(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator ==(const ELF_PT &rhs) const { return value == rhs.value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_PT &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t ; }; |
47 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM)struct ELF_EM { ELF_EM() = default; ELF_EM(const uint32_t v) : value(v) {} ELF_EM(const ELF_EM &v) = default; ELF_EM & operator=(const ELF_EM &rhs) = default; ELF_EM &operator =(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator ==(const ELF_EM &rhs) const { return value == rhs.value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_EM &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t ; }; |
48 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS)struct ELF_ELFCLASS { ELF_ELFCLASS() = default; ELF_ELFCLASS( const uint8_t v) : value(v) {} ELF_ELFCLASS(const ELF_ELFCLASS &v) = default; ELF_ELFCLASS &operator=(const ELF_ELFCLASS &rhs) = default; ELF_ELFCLASS &operator=(const uint8_t &rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const ELF_ELFCLASS &rhs) const { return value == rhs.value; } bool operator ==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_ELFCLASS &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; } ; |
49 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA)struct ELF_ELFDATA { ELF_ELFDATA() = default; ELF_ELFDATA(const uint8_t v) : value(v) {} ELF_ELFDATA(const ELF_ELFDATA & v) = default; ELF_ELFDATA &operator=(const ELF_ELFDATA & rhs) = default; ELF_ELFDATA &operator=(const uint8_t & rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const ELF_ELFDATA &rhs) const { return value == rhs.value; } bool operator ==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_ELFDATA &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; } ; |
50 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI)struct ELF_ELFOSABI { ELF_ELFOSABI() = default; ELF_ELFOSABI( const uint8_t v) : value(v) {} ELF_ELFOSABI(const ELF_ELFOSABI &v) = default; ELF_ELFOSABI &operator=(const ELF_ELFOSABI &rhs) = default; ELF_ELFOSABI &operator=(const uint8_t &rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const ELF_ELFOSABI &rhs) const { return value == rhs.value; } bool operator ==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_ELFOSABI &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; } ; |
51 | // Just use 64, since it can hold 32-bit values too. |
52 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)struct ELF_EF { ELF_EF() = default; ELF_EF(const uint64_t v) : value(v) {} ELF_EF(const ELF_EF &v) = default; ELF_EF & operator=(const ELF_EF &rhs) = default; ELF_EF &operator =(const uint64_t &rhs) { value = rhs; return *this; } operator const uint64_t & () const { return value; } bool operator ==(const ELF_EF &rhs) const { return value == rhs.value; } bool operator==(const uint64_t &rhs) const { return value == rhs; } bool operator<(const ELF_EF &rhs) const { return value < rhs.value; } uint64_t value; using BaseType = uint64_t ; }; |
53 | // Just use 64, since it can hold 32-bit values too. |
54 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_DYNTAG)struct ELF_DYNTAG { ELF_DYNTAG() = default; ELF_DYNTAG(const uint64_t v) : value(v) {} ELF_DYNTAG(const ELF_DYNTAG &v) = default ; ELF_DYNTAG &operator=(const ELF_DYNTAG &rhs) = default ; ELF_DYNTAG &operator=(const uint64_t &rhs) { value = rhs; return *this; } operator const uint64_t & () const { return value; } bool operator==(const ELF_DYNTAG &rhs) const { return value == rhs.value; } bool operator==(const uint64_t &rhs) const { return value == rhs; } bool operator<(const ELF_DYNTAG &rhs) const { return value < rhs.value; } uint64_t value; using BaseType = uint64_t; }; |
55 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF)struct ELF_PF { ELF_PF() = default; ELF_PF(const uint32_t v) : value(v) {} ELF_PF(const ELF_PF &v) = default; ELF_PF & operator=(const ELF_PF &rhs) = default; ELF_PF &operator =(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator ==(const ELF_PF &rhs) const { return value == rhs.value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_PF &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t ; }; |
56 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)struct ELF_SHT { ELF_SHT() = default; ELF_SHT(const uint32_t v ) : value(v) {} ELF_SHT(const ELF_SHT &v) = default; ELF_SHT &operator=(const ELF_SHT &rhs) = default; ELF_SHT & operator=(const uint32_t &rhs) { value = rhs; return *this ; } operator const uint32_t & () const { return value; } bool operator==(const ELF_SHT &rhs) const { return value == rhs .value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_SHT &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
57 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)struct ELF_REL { ELF_REL() = default; ELF_REL(const uint32_t v ) : value(v) {} ELF_REL(const ELF_REL &v) = default; ELF_REL &operator=(const ELF_REL &rhs) = default; ELF_REL & operator=(const uint32_t &rhs) { value = rhs; return *this ; } operator const uint32_t & () const { return value; } bool operator==(const ELF_REL &rhs) const { return value == rhs .value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_REL &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
58 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)struct ELF_RSS { ELF_RSS() = default; ELF_RSS(const uint8_t v ) : value(v) {} ELF_RSS(const ELF_RSS &v) = default; ELF_RSS &operator=(const ELF_RSS &rhs) = default; ELF_RSS & operator=(const uint8_t &rhs) { value = rhs; return *this ; } operator const uint8_t & () const { return value; } bool operator==(const ELF_RSS &rhs) const { return value == rhs .value; } bool operator==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_RSS &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; }; |
59 | // Just use 64, since it can hold 32-bit values too. |
60 | LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)struct ELF_SHF { ELF_SHF() = default; ELF_SHF(const uint64_t v ) : value(v) {} ELF_SHF(const ELF_SHF &v) = default; ELF_SHF &operator=(const ELF_SHF &rhs) = default; ELF_SHF & operator=(const uint64_t &rhs) { value = rhs; return *this ; } operator const uint64_t & () const { return value; } bool operator==(const ELF_SHF &rhs) const { return value == rhs .value; } bool operator==(const uint64_t &rhs) const { return value == rhs; } bool operator<(const ELF_SHF &rhs) const { return value < rhs.value; } uint64_t value; using BaseType = uint64_t; }; |
61 | LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_SHN)struct ELF_SHN { ELF_SHN() = default; ELF_SHN(const uint16_t v ) : value(v) {} ELF_SHN(const ELF_SHN &v) = default; ELF_SHN &operator=(const ELF_SHN &rhs) = default; ELF_SHN & operator=(const uint16_t &rhs) { value = rhs; return *this ; } operator const uint16_t & () const { return value; } bool operator==(const ELF_SHN &rhs) const { return value == rhs .value; } bool operator==(const uint16_t &rhs) const { return value == rhs; } bool operator<(const ELF_SHN &rhs) const { return value < rhs.value; } uint16_t value; using BaseType = uint16_t; }; |
62 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB)struct ELF_STB { ELF_STB() = default; ELF_STB(const uint8_t v ) : value(v) {} ELF_STB(const ELF_STB &v) = default; ELF_STB &operator=(const ELF_STB &rhs) = default; ELF_STB & operator=(const uint8_t &rhs) { value = rhs; return *this ; } operator const uint8_t & () const { return value; } bool operator==(const ELF_STB &rhs) const { return value == rhs .value; } bool operator==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_STB &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; }; |
63 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)struct ELF_STT { ELF_STT() = default; ELF_STT(const uint8_t v ) : value(v) {} ELF_STT(const ELF_STT &v) = default; ELF_STT &operator=(const ELF_STT &rhs) = default; ELF_STT & operator=(const uint8_t &rhs) { value = rhs; return *this ; } operator const uint8_t & () const { return value; } bool operator==(const ELF_STT &rhs) const { return value == rhs .value; } bool operator==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const ELF_STT &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; }; |
64 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_NT)struct ELF_NT { ELF_NT() = default; ELF_NT(const uint32_t v) : value(v) {} ELF_NT(const ELF_NT &v) = default; ELF_NT & operator=(const ELF_NT &rhs) = default; ELF_NT &operator =(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator ==(const ELF_NT &rhs) const { return value == rhs.value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const ELF_NT &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t ; }; |
65 | |
66 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG)struct MIPS_AFL_REG { MIPS_AFL_REG() = default; MIPS_AFL_REG( const uint8_t v) : value(v) {} MIPS_AFL_REG(const MIPS_AFL_REG &v) = default; MIPS_AFL_REG &operator=(const MIPS_AFL_REG &rhs) = default; MIPS_AFL_REG &operator=(const uint8_t &rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const MIPS_AFL_REG &rhs) const { return value == rhs.value; } bool operator ==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const MIPS_AFL_REG &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; } ; |
67 | LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP)struct MIPS_ABI_FP { MIPS_ABI_FP() = default; MIPS_ABI_FP(const uint8_t v) : value(v) {} MIPS_ABI_FP(const MIPS_ABI_FP & v) = default; MIPS_ABI_FP &operator=(const MIPS_ABI_FP & rhs) = default; MIPS_ABI_FP &operator=(const uint8_t & rhs) { value = rhs; return *this; } operator const uint8_t & () const { return value; } bool operator==(const MIPS_ABI_FP &rhs) const { return value == rhs.value; } bool operator ==(const uint8_t &rhs) const { return value == rhs; } bool operator<(const MIPS_ABI_FP &rhs) const { return value < rhs.value; } uint8_t value; using BaseType = uint8_t; } ; |
68 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT)struct MIPS_AFL_EXT { MIPS_AFL_EXT() = default; MIPS_AFL_EXT( const uint32_t v) : value(v) {} MIPS_AFL_EXT(const MIPS_AFL_EXT &v) = default; MIPS_AFL_EXT &operator=(const MIPS_AFL_EXT &rhs) = default; MIPS_AFL_EXT &operator=(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator==(const MIPS_AFL_EXT &rhs) const { return value == rhs.value; } bool operator ==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const MIPS_AFL_EXT &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
69 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE)struct MIPS_AFL_ASE { MIPS_AFL_ASE() = default; MIPS_AFL_ASE( const uint32_t v) : value(v) {} MIPS_AFL_ASE(const MIPS_AFL_ASE &v) = default; MIPS_AFL_ASE &operator=(const MIPS_AFL_ASE &rhs) = default; MIPS_AFL_ASE &operator=(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator==(const MIPS_AFL_ASE &rhs) const { return value == rhs.value; } bool operator ==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const MIPS_AFL_ASE &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
70 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1)struct MIPS_AFL_FLAGS1 { MIPS_AFL_FLAGS1() = default; MIPS_AFL_FLAGS1 (const uint32_t v) : value(v) {} MIPS_AFL_FLAGS1(const MIPS_AFL_FLAGS1 &v) = default; MIPS_AFL_FLAGS1 &operator=(const MIPS_AFL_FLAGS1 &rhs) = default; MIPS_AFL_FLAGS1 &operator=(const uint32_t &rhs) { value = rhs; return *this; } operator const uint32_t & () const { return value; } bool operator==(const MIPS_AFL_FLAGS1 &rhs) const { return value == rhs.value; } bool operator ==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const MIPS_AFL_FLAGS1 &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
71 | LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA)struct MIPS_ISA { MIPS_ISA() = default; MIPS_ISA(const uint32_t v) : value(v) {} MIPS_ISA(const MIPS_ISA &v) = default; MIPS_ISA &operator=(const MIPS_ISA &rhs) = default; MIPS_ISA & operator=(const uint32_t &rhs) { value = rhs; return *this ; } operator const uint32_t & () const { return value; } bool operator==(const MIPS_ISA &rhs) const { return value == rhs .value; } bool operator==(const uint32_t &rhs) const { return value == rhs; } bool operator<(const MIPS_ISA &rhs) const { return value < rhs.value; } uint32_t value; using BaseType = uint32_t; }; |
72 | |
73 | LLVM_YAML_STRONG_TYPEDEF(StringRef, YAMLFlowString)struct YAMLFlowString { YAMLFlowString() = default; YAMLFlowString (const StringRef v) : value(v) {} YAMLFlowString(const YAMLFlowString &v) = default; YAMLFlowString &operator=(const YAMLFlowString &rhs) = default; YAMLFlowString &operator=(const StringRef &rhs) { value = rhs; return *this; } operator const StringRef & () const { return value; } bool operator==(const YAMLFlowString &rhs) const { return value == rhs.value; } bool operator ==(const StringRef &rhs) const { return value == rhs; } bool operator<(const YAMLFlowString &rhs) const { return value < rhs.value; } StringRef value; using BaseType = StringRef ; }; |
74 | LLVM_YAML_STRONG_TYPEDEF(int64_t, YAMLIntUInt)struct YAMLIntUInt { YAMLIntUInt() = default; YAMLIntUInt(const int64_t v) : value(v) {} YAMLIntUInt(const YAMLIntUInt & v) = default; YAMLIntUInt &operator=(const YAMLIntUInt & rhs) = default; YAMLIntUInt &operator=(const int64_t & rhs) { value = rhs; return *this; } operator const int64_t & () const { return value; } bool operator==(const YAMLIntUInt &rhs) const { return value == rhs.value; } bool operator ==(const int64_t &rhs) const { return value == rhs; } bool operator<(const YAMLIntUInt &rhs) const { return value < rhs.value; } int64_t value; using BaseType = int64_t; } ; |
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 FileHeader { |
114 | ELF_ELFCLASS Class; |
115 | ELF_ELFDATA Data; |
116 | ELF_ELFOSABI OSABI; |
117 | llvm::yaml::Hex8 ABIVersion; |
118 | ELF_ET Type; |
119 | std::optional<ELF_EM> Machine; |
120 | ELF_EF Flags; |
121 | llvm::yaml::Hex64 Entry; |
122 | std::optional<StringRef> SectionHeaderStringTable; |
123 | |
124 | std::optional<llvm::yaml::Hex64> EPhOff; |
125 | std::optional<llvm::yaml::Hex16> EPhEntSize; |
126 | std::optional<llvm::yaml::Hex16> EPhNum; |
127 | std::optional<llvm::yaml::Hex16> EShEntSize; |
128 | std::optional<llvm::yaml::Hex64> EShOff; |
129 | std::optional<llvm::yaml::Hex16> EShNum; |
130 | std::optional<llvm::yaml::Hex16> EShStrNdx; |
131 | }; |
132 | |
133 | struct SectionHeader { |
134 | StringRef Name; |
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 | llvm::yaml::Hex64 Address; |
169 | std::optional<uint64_t> NumBlocks; |
170 | std::optional<std::vector<BBEntry>> BBEntries; |
171 | }; |
172 | |
173 | struct StackSizeEntry { |
174 | llvm::yaml::Hex64 Address; |
175 | llvm::yaml::Hex64 Size; |
176 | }; |
177 | |
178 | struct NoteEntry { |
179 | StringRef Name; |
180 | yaml::BinaryRef Desc; |
181 | ELF_NT Type; |
182 | }; |
183 | |
184 | struct Chunk { |
185 | enum class ChunkKind { |
186 | Dynamic, |
187 | Group, |
188 | RawContent, |
189 | Relocation, |
190 | Relr, |
191 | NoBits, |
192 | Note, |
193 | Hash, |
194 | GnuHash, |
195 | Verdef, |
196 | Verneed, |
197 | StackSizes, |
198 | SymtabShndxSection, |
199 | Symver, |
200 | ARMIndexTable, |
201 | MipsABIFlags, |
202 | Addrsig, |
203 | LinkerOptions, |
204 | DependentLibraries, |
205 | CallGraphProfile, |
206 | BBAddrMap, |
207 | |
208 | // Special chunks. |
209 | SpecialChunksStart, |
210 | Fill = SpecialChunksStart, |
211 | SectionHeaderTable, |
212 | }; |
213 | |
214 | ChunkKind Kind; |
215 | StringRef Name; |
216 | std::optional<llvm::yaml::Hex64> Offset; |
217 | |
218 | // Usually chunks are not created implicitly, but rather loaded from YAML. |
219 | // This flag is used to signal whether this is the case or not. |
220 | bool IsImplicit; |
221 | |
222 | Chunk(ChunkKind K, bool Implicit) : Kind(K), IsImplicit(Implicit) {} |
223 | virtual ~Chunk(); |
224 | }; |
225 | |
226 | struct Section : public Chunk { |
227 | ELF_SHT Type; |
228 | std::optional<ELF_SHF> Flags; |
229 | std::optional<llvm::yaml::Hex64> Address; |
230 | std::optional<StringRef> Link; |
231 | llvm::yaml::Hex64 AddressAlign; |
232 | std::optional<llvm::yaml::Hex64> EntSize; |
233 | |
234 | std::optional<yaml::BinaryRef> Content; |
235 | std::optional<llvm::yaml::Hex64> Size; |
236 | |
237 | // Holds the original section index. |
238 | unsigned OriginalSecNdx; |
239 | |
240 | Section(ChunkKind Kind, bool IsImplicit = false) : Chunk(Kind, IsImplicit) {} |
241 | |
242 | static bool classof(const Chunk *S) { |
243 | return S->Kind < ChunkKind::SpecialChunksStart; |
244 | } |
245 | |
246 | // Some derived sections might have their own special entries. This method |
247 | // returns a vector of <entry name, is used> pairs. It is used for section |
248 | // validation. |
249 | virtual std::vector<std::pair<StringRef, bool>> getEntries() const { |
250 | return {}; |
251 | }; |
252 | |
253 | // The following members are used to override section fields which is |
254 | // useful for creating invalid objects. |
255 | |
256 | // This can be used to override the sh_addralign field. |
257 | std::optional<llvm::yaml::Hex64> ShAddrAlign; |
258 | |
259 | // This can be used to override the offset stored in the sh_name field. |
260 | // It does not affect the name stored in the string table. |
261 | std::optional<llvm::yaml::Hex64> ShName; |
262 | |
263 | // This can be used to override the sh_offset field. It does not place the |
264 | // section data at the offset specified. |
265 | std::optional<llvm::yaml::Hex64> ShOffset; |
266 | |
267 | // This can be used to override the sh_size field. It does not affect the |
268 | // content written. |
269 | std::optional<llvm::yaml::Hex64> ShSize; |
270 | |
271 | // This can be used to override the sh_flags field. |
272 | std::optional<llvm::yaml::Hex64> ShFlags; |
273 | |
274 | // This can be used to override the sh_type field. It is useful when we |
275 | // want to use specific YAML keys for a section of a particular type to |
276 | // describe the content, but still want to have a different final type |
277 | // for the section. |
278 | std::optional<ELF_SHT> ShType; |
279 | }; |
280 | |
281 | // Fill is a block of data which is placed outside of sections. It is |
282 | // not present in the sections header table, but it might affect the output file |
283 | // size and program headers produced. |
284 | struct Fill : Chunk { |
285 | std::optional<yaml::BinaryRef> Pattern; |
286 | llvm::yaml::Hex64 Size; |
287 | |
288 | Fill() : Chunk(ChunkKind::Fill, /*Implicit=*/false) {} |
289 | |
290 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; } |
291 | }; |
292 | |
293 | struct SectionHeaderTable : Chunk { |
294 | SectionHeaderTable(bool IsImplicit) |
295 | : Chunk(ChunkKind::SectionHeaderTable, IsImplicit) {} |
296 | |
297 | static bool classof(const Chunk *S) { |
298 | return S->Kind == ChunkKind::SectionHeaderTable; |
299 | } |
300 | |
301 | std::optional<std::vector<SectionHeader>> Sections; |
302 | std::optional<std::vector<SectionHeader>> Excluded; |
303 | std::optional<bool> NoHeaders; |
304 | |
305 | size_t getNumHeaders(size_t SectionsNum) const { |
306 | if (IsImplicit || isDefault()) |
307 | return SectionsNum; |
308 | if (NoHeaders) |
309 | return (*NoHeaders) ? 0 : SectionsNum; |
310 | return (Sections ? Sections->size() : 0) + /*Null section*/ 1; |
311 | } |
312 | |
313 | bool isDefault() const { return !Sections && !Excluded && !NoHeaders; } |
314 | |
315 | static constexpr StringRef TypeStr = "SectionHeaderTable"; |
316 | }; |
317 | |
318 | struct BBAddrMapSection : Section { |
319 | std::optional<std::vector<BBAddrMapEntry>> Entries; |
320 | |
321 | BBAddrMapSection() : Section(ChunkKind::BBAddrMap) {} |
322 | |
323 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
324 | return {{"Entries", Entries.has_value()}}; |
325 | }; |
326 | |
327 | static bool classof(const Chunk *S) { |
328 | return S->Kind == ChunkKind::BBAddrMap; |
329 | } |
330 | }; |
331 | |
332 | struct StackSizesSection : Section { |
333 | std::optional<std::vector<StackSizeEntry>> Entries; |
334 | |
335 | StackSizesSection() : Section(ChunkKind::StackSizes) {} |
336 | |
337 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
338 | return {{"Entries", Entries.has_value()}}; |
339 | }; |
340 | |
341 | static bool classof(const Chunk *S) { |
342 | return S->Kind == ChunkKind::StackSizes; |
343 | } |
344 | |
345 | static bool nameMatches(StringRef Name) { |
346 | return Name == ".stack_sizes"; |
347 | } |
348 | }; |
349 | |
350 | struct DynamicSection : Section { |
351 | std::optional<std::vector<DynamicEntry>> Entries; |
352 | |
353 | DynamicSection() : Section(ChunkKind::Dynamic) {} |
354 | |
355 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
356 | return {{"Entries", Entries.has_value()}}; |
357 | }; |
358 | |
359 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Dynamic; } |
360 | }; |
361 | |
362 | struct RawContentSection : Section { |
363 | std::optional<llvm::yaml::Hex64> Info; |
364 | |
365 | RawContentSection() : Section(ChunkKind::RawContent) {} |
366 | |
367 | static bool classof(const Chunk *S) { |
368 | return S->Kind == ChunkKind::RawContent; |
369 | } |
370 | |
371 | // Is used when a content is read as an array of bytes. |
372 | std::optional<std::vector<uint8_t>> ContentBuf; |
373 | }; |
374 | |
375 | struct NoBitsSection : Section { |
376 | NoBitsSection() : Section(ChunkKind::NoBits) {} |
377 | |
378 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::NoBits; } |
379 | }; |
380 | |
381 | struct NoteSection : Section { |
382 | std::optional<std::vector<ELFYAML::NoteEntry>> Notes; |
383 | |
384 | NoteSection() : Section(ChunkKind::Note) {} |
385 | |
386 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
387 | return {{"Notes", Notes.has_value()}}; |
388 | }; |
389 | |
390 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Note; } |
391 | }; |
392 | |
393 | struct HashSection : Section { |
394 | std::optional<std::vector<uint32_t>> Bucket; |
395 | std::optional<std::vector<uint32_t>> Chain; |
396 | |
397 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
398 | return {{"Bucket", Bucket.has_value()}, {"Chain", Chain.has_value()}}; |
399 | }; |
400 | |
401 | // The following members are used to override section fields. |
402 | // This is useful for creating invalid objects. |
403 | std::optional<llvm::yaml::Hex64> NBucket; |
404 | std::optional<llvm::yaml::Hex64> NChain; |
405 | |
406 | HashSection() : Section(ChunkKind::Hash) {} |
407 | |
408 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Hash; } |
409 | }; |
410 | |
411 | struct GnuHashHeader { |
412 | // The number of hash buckets. |
413 | // Not used when dumping the object, but can be used to override |
414 | // the real number of buckets when emiting an object from a YAML document. |
415 | std::optional<llvm::yaml::Hex32> NBuckets; |
416 | |
417 | // Index of the first symbol in the dynamic symbol table |
418 | // included in the hash table. |
419 | llvm::yaml::Hex32 SymNdx; |
420 | |
421 | // The number of words in the Bloom filter. |
422 | // Not used when dumping the object, but can be used to override the real |
423 | // number of words in the Bloom filter when emiting an object from a YAML |
424 | // document. |
425 | std::optional<llvm::yaml::Hex32> MaskWords; |
426 | |
427 | // A shift constant used by the Bloom filter. |
428 | llvm::yaml::Hex32 Shift2; |
429 | }; |
430 | |
431 | struct GnuHashSection : Section { |
432 | std::optional<GnuHashHeader> Header; |
433 | std::optional<std::vector<llvm::yaml::Hex64>> BloomFilter; |
434 | std::optional<std::vector<llvm::yaml::Hex32>> HashBuckets; |
435 | std::optional<std::vector<llvm::yaml::Hex32>> HashValues; |
436 | |
437 | GnuHashSection() : Section(ChunkKind::GnuHash) {} |
438 | |
439 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
440 | return {{"Header", Header.has_value()}, |
441 | {"BloomFilter", BloomFilter.has_value()}, |
442 | {"HashBuckets", HashBuckets.has_value()}, |
443 | {"HashValues", HashValues.has_value()}}; |
444 | }; |
445 | |
446 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::GnuHash; } |
447 | }; |
448 | |
449 | struct VernauxEntry { |
450 | uint32_t Hash; |
451 | uint16_t Flags; |
452 | uint16_t Other; |
453 | StringRef Name; |
454 | }; |
455 | |
456 | struct VerneedEntry { |
457 | uint16_t Version; |
458 | StringRef File; |
459 | std::vector<VernauxEntry> AuxV; |
460 | }; |
461 | |
462 | struct VerneedSection : Section { |
463 | std::optional<std::vector<VerneedEntry>> VerneedV; |
464 | std::optional<llvm::yaml::Hex64> Info; |
465 | |
466 | VerneedSection() : Section(ChunkKind::Verneed) {} |
467 | |
468 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
469 | return {{"Dependencies", VerneedV.has_value()}}; |
470 | }; |
471 | |
472 | static bool classof(const Chunk *S) { |
473 | return S->Kind == ChunkKind::Verneed; |
474 | } |
475 | }; |
476 | |
477 | struct AddrsigSection : Section { |
478 | std::optional<std::vector<YAMLFlowString>> Symbols; |
479 | |
480 | AddrsigSection() : Section(ChunkKind::Addrsig) {} |
481 | |
482 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
483 | return {{"Symbols", Symbols.has_value()}}; |
484 | }; |
485 | |
486 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Addrsig; } |
487 | }; |
488 | |
489 | struct LinkerOption { |
490 | StringRef Key; |
491 | StringRef Value; |
492 | }; |
493 | |
494 | struct LinkerOptionsSection : Section { |
495 | std::optional<std::vector<LinkerOption>> Options; |
496 | |
497 | LinkerOptionsSection() : Section(ChunkKind::LinkerOptions) {} |
498 | |
499 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
500 | return {{"Options", Options.has_value()}}; |
501 | }; |
502 | |
503 | static bool classof(const Chunk *S) { |
504 | return S->Kind == ChunkKind::LinkerOptions; |
505 | } |
506 | }; |
507 | |
508 | struct DependentLibrariesSection : Section { |
509 | std::optional<std::vector<YAMLFlowString>> Libs; |
510 | |
511 | DependentLibrariesSection() : Section(ChunkKind::DependentLibraries) {} |
512 | |
513 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
514 | return {{"Libraries", Libs.has_value()}}; |
515 | }; |
516 | |
517 | static bool classof(const Chunk *S) { |
518 | return S->Kind == ChunkKind::DependentLibraries; |
519 | } |
520 | }; |
521 | |
522 | // Represents the call graph profile section entry. |
523 | struct CallGraphEntryWeight { |
524 | // The weight of the edge. |
525 | uint64_t Weight; |
526 | }; |
527 | |
528 | struct CallGraphProfileSection : Section { |
529 | std::optional<std::vector<CallGraphEntryWeight>> Entries; |
530 | |
531 | CallGraphProfileSection() : Section(ChunkKind::CallGraphProfile) {} |
532 | |
533 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
534 | return {{"Entries", Entries.has_value()}}; |
535 | }; |
536 | |
537 | static bool classof(const Chunk *S) { |
538 | return S->Kind == ChunkKind::CallGraphProfile; |
539 | } |
540 | }; |
541 | |
542 | struct SymverSection : Section { |
543 | std::optional<std::vector<uint16_t>> Entries; |
544 | |
545 | SymverSection() : Section(ChunkKind::Symver) {} |
546 | |
547 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
548 | return {{"Entries", Entries.has_value()}}; |
549 | }; |
550 | |
551 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Symver; } |
552 | }; |
553 | |
554 | struct VerdefEntry { |
555 | std::optional<uint16_t> Version; |
556 | std::optional<uint16_t> Flags; |
557 | std::optional<uint16_t> VersionNdx; |
558 | std::optional<uint32_t> Hash; |
559 | std::vector<StringRef> VerNames; |
560 | }; |
561 | |
562 | struct VerdefSection : Section { |
563 | std::optional<std::vector<VerdefEntry>> Entries; |
564 | std::optional<llvm::yaml::Hex64> Info; |
565 | |
566 | VerdefSection() : Section(ChunkKind::Verdef) {} |
567 | |
568 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
569 | return {{"Entries", Entries.has_value()}}; |
570 | }; |
571 | |
572 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Verdef; } |
573 | }; |
574 | |
575 | struct GroupSection : Section { |
576 | // Members of a group contain a flag and a list of section indices |
577 | // that are part of the group. |
578 | std::optional<std::vector<SectionOrType>> Members; |
579 | std::optional<StringRef> Signature; /* Info */ |
580 | |
581 | GroupSection() : Section(ChunkKind::Group) {} |
582 | |
583 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
584 | return {{"Members", Members.has_value()}}; |
585 | }; |
586 | |
587 | static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Group; } |
588 | }; |
589 | |
590 | struct Relocation { |
591 | llvm::yaml::Hex64 Offset; |
592 | YAMLIntUInt Addend; |
593 | ELF_REL Type; |
594 | std::optional<StringRef> Symbol; |
595 | }; |
596 | |
597 | struct RelocationSection : Section { |
598 | std::optional<std::vector<Relocation>> Relocations; |
599 | StringRef RelocatableSec; /* Info */ |
600 | |
601 | RelocationSection() : Section(ChunkKind::Relocation) {} |
602 | |
603 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
604 | return {{"Relocations", Relocations.has_value()}}; |
605 | }; |
606 | |
607 | static bool classof(const Chunk *S) { |
608 | return S->Kind == ChunkKind::Relocation; |
609 | } |
610 | }; |
611 | |
612 | struct RelrSection : Section { |
613 | std::optional<std::vector<llvm::yaml::Hex64>> Entries; |
614 | |
615 | RelrSection() : Section(ChunkKind::Relr) {} |
616 | |
617 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
618 | return {{"Entries", Entries.has_value()}}; |
619 | }; |
620 | |
621 | static bool classof(const Chunk *S) { |
622 | return S->Kind == ChunkKind::Relr; |
623 | } |
624 | }; |
625 | |
626 | struct SymtabShndxSection : Section { |
627 | std::optional<std::vector<uint32_t>> Entries; |
628 | |
629 | SymtabShndxSection() : Section(ChunkKind::SymtabShndxSection) {} |
630 | |
631 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
632 | return {{"Entries", Entries.has_value()}}; |
633 | }; |
634 | |
635 | static bool classof(const Chunk *S) { |
636 | return S->Kind == ChunkKind::SymtabShndxSection; |
637 | } |
638 | }; |
639 | |
640 | struct ARMIndexTableEntry { |
641 | llvm::yaml::Hex32 Offset; |
642 | llvm::yaml::Hex32 Value; |
643 | }; |
644 | |
645 | struct ARMIndexTableSection : Section { |
646 | std::optional<std::vector<ARMIndexTableEntry>> Entries; |
647 | |
648 | ARMIndexTableSection() : Section(ChunkKind::ARMIndexTable) {} |
649 | |
650 | std::vector<std::pair<StringRef, bool>> getEntries() const override { |
651 | return {{"Entries", Entries.has_value()}}; |
652 | }; |
653 | |
654 | static bool classof(const Chunk *S) { |
655 | return S->Kind == ChunkKind::ARMIndexTable; |
656 | } |
657 | }; |
658 | |
659 | // Represents .MIPS.abiflags section |
660 | struct MipsABIFlags : Section { |
661 | llvm::yaml::Hex16 Version; |
662 | MIPS_ISA ISALevel; |
663 | llvm::yaml::Hex8 ISARevision; |
664 | MIPS_AFL_REG GPRSize; |
665 | MIPS_AFL_REG CPR1Size; |
666 | MIPS_AFL_REG CPR2Size; |
667 | MIPS_ABI_FP FpABI; |
668 | MIPS_AFL_EXT ISAExtension; |
669 | MIPS_AFL_ASE ASEs; |
670 | MIPS_AFL_FLAGS1 Flags1; |
671 | llvm::yaml::Hex32 Flags2; |
672 | |
673 | MipsABIFlags() : Section(ChunkKind::MipsABIFlags) {} |
674 | |
675 | static bool classof(const Chunk *S) { |
676 | return S->Kind == ChunkKind::MipsABIFlags; |
677 | } |
678 | }; |
679 | |
680 | struct ProgramHeader { |
681 | ELF_PT Type; |
682 | ELF_PF Flags; |
683 | llvm::yaml::Hex64 VAddr; |
684 | llvm::yaml::Hex64 PAddr; |
685 | std::optional<llvm::yaml::Hex64> Align; |
686 | std::optional<llvm::yaml::Hex64> FileSize; |
687 | std::optional<llvm::yaml::Hex64> MemSize; |
688 | std::optional<llvm::yaml::Hex64> Offset; |
689 | std::optional<StringRef> FirstSec; |
690 | std::optional<StringRef> LastSec; |
691 | |
692 | // This vector contains all chunks from [FirstSec, LastSec]. |
693 | std::vector<Chunk *> Chunks; |
694 | }; |
695 | |
696 | struct Object { |
697 | FileHeader Header; |
698 | std::vector<ProgramHeader> ProgramHeaders; |
699 | |
700 | // An object might contain output section descriptions as well as |
701 | // custom data that does not belong to any section. |
702 | std::vector<std::unique_ptr<Chunk>> Chunks; |
703 | |
704 | // Although in reality the symbols reside in a section, it is a lot |
705 | // cleaner and nicer if we read them from the YAML as a separate |
706 | // top-level key, which automatically ensures that invariants like there |
707 | // being a single SHT_SYMTAB section are upheld. |
708 | std::optional<std::vector<Symbol>> Symbols; |
709 | std::optional<std::vector<Symbol>> DynamicSymbols; |
710 | std::optional<DWARFYAML::Data> DWARF; |
711 | |
712 | std::vector<Section *> getSections() { |
713 | std::vector<Section *> Ret; |
714 | for (const std::unique_ptr<Chunk> &Sec : Chunks) |
715 | if (auto S = dyn_cast<ELFYAML::Section>(Sec.get())) |
716 | Ret.push_back(S); |
717 | return Ret; |
718 | } |
719 | |
720 | const SectionHeaderTable &getSectionHeaderTable() const { |
721 | for (const std::unique_ptr<Chunk> &C : Chunks) |
722 | if (auto *S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) |
723 | return *S; |
724 | llvm_unreachable("the section header table chunk must always be present")::llvm::llvm_unreachable_internal("the section header table chunk must always be present" , "llvm/include/llvm/ObjectYAML/ELFYAML.h", 724); |
725 | } |
726 | |
727 | ELF_ELFOSABI getOSAbi() const; |
728 | unsigned getMachine() const; |
729 | }; |
730 | |
731 | bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs, |
732 | const NoBitsSection &S); |
733 | |
734 | } // end namespace ELFYAML |
735 | } // end namespace llvm |
736 | |
737 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::StackSizeEntry> && !std::is_same_v <llvm::ELFYAML::StackSizeEntry, std::string> && !std::is_same_v<llvm::ELFYAML::StackSizeEntry, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::StackSizeEntry> { static const bool flow = false; }; } } |
738 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::BBAddrMapEntry> && !std::is_same_v <llvm::ELFYAML::BBAddrMapEntry, std::string> && !std::is_same_v<llvm::ELFYAML::BBAddrMapEntry, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::BBAddrMapEntry> { static const bool flow = false; }; } } |
739 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry::BBEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::BBAddrMapEntry::BBEntry> && !std ::is_same_v<llvm::ELFYAML::BBAddrMapEntry::BBEntry, std::string > && !std::is_same_v<llvm::ELFYAML::BBAddrMapEntry ::BBEntry, llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::BBAddrMapEntry::BBEntry> { static const bool flow = false ; }; } } |
740 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::DynamicEntry> && !std::is_same_v <llvm::ELFYAML::DynamicEntry, std::string> && ! std::is_same_v<llvm::ELFYAML::DynamicEntry, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::DynamicEntry> { static const bool flow = false; }; } } |
741 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::LinkerOption)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::LinkerOption> && !std::is_same_v <llvm::ELFYAML::LinkerOption, std::string> && ! std::is_same_v<llvm::ELFYAML::LinkerOption, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::LinkerOption> { static const bool flow = false; }; } } |
742 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::CallGraphEntryWeight)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::CallGraphEntryWeight> && !std:: is_same_v<llvm::ELFYAML::CallGraphEntryWeight, std::string > && !std::is_same_v<llvm::ELFYAML::CallGraphEntryWeight , llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::CallGraphEntryWeight> { static const bool flow = false; } ; } } |
743 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::NoteEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::NoteEntry> && !std::is_same_v< llvm::ELFYAML::NoteEntry, std::string> && !std::is_same_v <llvm::ELFYAML::NoteEntry, llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::NoteEntry> { static const bool flow = false; }; } } |
744 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::ProgramHeader> && !std::is_same_v <llvm::ELFYAML::ProgramHeader, std::string> && ! std::is_same_v<llvm::ELFYAML::ProgramHeader, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::ProgramHeader> { static const bool flow = false; }; } } |
745 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionHeader)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::SectionHeader> && !std::is_same_v <llvm::ELFYAML::SectionHeader, std::string> && ! std::is_same_v<llvm::ELFYAML::SectionHeader, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::SectionHeader> { static const bool flow = false; }; } } |
746 | LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Chunk>)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <std::unique_ptr<llvm::ELFYAML::Chunk> > && !std::is_same_v<std::unique_ptr<llvm::ELFYAML::Chunk> , std::string> && !std::is_same_v<std::unique_ptr <llvm::ELFYAML::Chunk>, llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<std::unique_ptr <llvm::ELFYAML::Chunk> > { static const bool flow = false ; }; } } |
747 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::Symbol> && !std::is_same_v<llvm ::ELFYAML::Symbol, std::string> && !std::is_same_v <llvm::ELFYAML::Symbol, llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::Symbol> { static const bool flow = false; }; } } |
748 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::VerdefEntry> && !std::is_same_v <llvm::ELFYAML::VerdefEntry, std::string> && !std ::is_same_v<llvm::ELFYAML::VerdefEntry, llvm::StringRef> , "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::VerdefEntry> { static const bool flow = false; }; } } |
749 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::VernauxEntry> && !std::is_same_v <llvm::ELFYAML::VernauxEntry, std::string> && ! std::is_same_v<llvm::ELFYAML::VernauxEntry, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::VernauxEntry> { static const bool flow = false; }; } } |
750 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::VerneedEntry> && !std::is_same_v <llvm::ELFYAML::VerneedEntry, std::string> && ! std::is_same_v<llvm::ELFYAML::VerneedEntry, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::VerneedEntry> { static const bool flow = false; }; } } |
751 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::Relocation> && !std::is_same_v< llvm::ELFYAML::Relocation, std::string> && !std::is_same_v <llvm::ELFYAML::Relocation, llvm::StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::Relocation> { static const bool flow = false; }; } } |
752 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::SectionOrType> && !std::is_same_v <llvm::ELFYAML::SectionOrType, std::string> && ! std::is_same_v<llvm::ELFYAML::SectionOrType, llvm::StringRef >, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::SectionOrType> { static const bool flow = false; }; } } |
753 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ARMIndexTableEntry)namespace llvm { namespace yaml { static_assert( !std::is_fundamental_v <llvm::ELFYAML::ARMIndexTableEntry> && !std::is_same_v <llvm::ELFYAML::ARMIndexTableEntry, std::string> && !std::is_same_v<llvm::ELFYAML::ARMIndexTableEntry, llvm:: StringRef>, "only use LLVM_YAML_IS_SEQUENCE_VECTOR for types you control" ); template <> struct SequenceElementTraits<llvm::ELFYAML ::ARMIndexTableEntry> { static const bool flow = false; }; } } |
754 | |
755 | namespace llvm { |
756 | namespace yaml { |
757 | |
758 | template <> struct ScalarTraits<ELFYAML::YAMLIntUInt> { |
759 | static void output(const ELFYAML::YAMLIntUInt &Val, void *Ctx, |
760 | raw_ostream &Out); |
761 | static StringRef input(StringRef Scalar, void *Ctx, |
762 | ELFYAML::YAMLIntUInt &Val); |
763 | static QuotingType mustQuote(StringRef) { return QuotingType::None; } |
764 | }; |
765 | |
766 | template <> |
767 | struct ScalarEnumerationTraits<ELFYAML::ELF_ET> { |
768 | static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); |
769 | }; |
770 | |
771 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_PT> { |
772 | static void enumeration(IO &IO, ELFYAML::ELF_PT &Value); |
773 | }; |
774 | |
775 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_NT> { |
776 | static void enumeration(IO &IO, ELFYAML::ELF_NT &Value); |
777 | }; |
778 | |
779 | template <> |
780 | struct ScalarEnumerationTraits<ELFYAML::ELF_EM> { |
781 | static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); |
782 | }; |
783 | |
784 | template <> |
785 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS> { |
786 | static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value); |
787 | }; |
788 | |
789 | template <> |
790 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA> { |
791 | static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value); |
792 | }; |
793 | |
794 | template <> |
795 | struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { |
796 | static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); |
797 | }; |
798 | |
799 | template <> |
800 | struct ScalarBitSetTraits<ELFYAML::ELF_EF> { |
801 | static void bitset(IO &IO, ELFYAML::ELF_EF &Value); |
802 | }; |
803 | |
804 | template <> struct ScalarBitSetTraits<ELFYAML::ELF_PF> { |
805 | static void bitset(IO &IO, ELFYAML::ELF_PF &Value); |
806 | }; |
807 | |
808 | template <> |
809 | struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> { |
810 | static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); |
811 | }; |
812 | |
813 | template <> |
814 | struct ScalarBitSetTraits<ELFYAML::ELF_SHF> { |
815 | static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); |
816 | }; |
817 | |
818 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_SHN> { |
819 | static void enumeration(IO &IO, ELFYAML::ELF_SHN &Value); |
820 | }; |
821 | |
822 | template <> struct ScalarEnumerationTraits<ELFYAML::ELF_STB> { |
823 | static void enumeration(IO &IO, ELFYAML::ELF_STB &Value); |
824 | }; |
825 | |
826 | template <> |
827 | struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { |
828 | static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); |
829 | }; |
830 | |
831 | template <> |
832 | struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { |
833 | static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); |
834 | }; |
835 | |
836 | template <> |
837 | struct ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG> { |
838 | static void enumeration(IO &IO, ELFYAML::ELF_DYNTAG &Value); |
839 | }; |
840 | |
841 | template <> |
842 | struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { |
843 | static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); |
844 | }; |
845 | |
846 | template <> |
847 | struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> { |
848 | static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); |
849 | }; |
850 | |
851 | template <> |
852 | struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> { |
853 | static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); |
854 | }; |
855 | |
856 | template <> |
857 | struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> { |
858 | static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); |
859 | }; |
860 | |
861 | template <> |
862 | struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> { |
863 | static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); |
864 | }; |
865 | |
866 | template <> |
867 | struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> { |
868 | static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); |
869 | }; |
870 | |
871 | template <> |
872 | struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> { |
873 | static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); |
874 | }; |
875 | |
876 | template <> |
877 | struct MappingTraits<ELFYAML::FileHeader> { |
878 | static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); |
879 | }; |
880 | |
881 | template <> struct MappingTraits<ELFYAML::SectionHeader> { |
882 | static void mapping(IO &IO, ELFYAML::SectionHeader &SHdr); |
883 | }; |
884 | |
885 | template <> struct MappingTraits<ELFYAML::ProgramHeader> { |
886 | static void mapping(IO &IO, ELFYAML::ProgramHeader &FileHdr); |
887 | static std::string validate(IO &IO, ELFYAML::ProgramHeader &FileHdr); |
888 | }; |
889 | |
890 | template <> |
891 | struct MappingTraits<ELFYAML::Symbol> { |
892 | static void mapping(IO &IO, ELFYAML::Symbol &Symbol); |
893 | static std::string validate(IO &IO, ELFYAML::Symbol &Symbol); |
894 | }; |
895 | |
896 | template <> struct MappingTraits<ELFYAML::StackSizeEntry> { |
897 | static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel); |
898 | }; |
899 | |
900 | template <> struct MappingTraits<ELFYAML::BBAddrMapEntry> { |
901 | static void mapping(IO &IO, ELFYAML::BBAddrMapEntry &Rel); |
902 | }; |
903 | |
904 | template <> struct MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry> { |
905 | static void mapping(IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &Rel); |
906 | }; |
907 | |
908 | template <> struct MappingTraits<ELFYAML::GnuHashHeader> { |
909 | static void mapping(IO &IO, ELFYAML::GnuHashHeader &Rel); |
910 | }; |
911 | |
912 | template <> struct MappingTraits<ELFYAML::DynamicEntry> { |
913 | static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); |
914 | }; |
915 | |
916 | template <> struct MappingTraits<ELFYAML::NoteEntry> { |
917 | static void mapping(IO &IO, ELFYAML::NoteEntry &N); |
918 | }; |
919 | |
920 | template <> struct MappingTraits<ELFYAML::VerdefEntry> { |
921 | static void mapping(IO &IO, ELFYAML::VerdefEntry &E); |
922 | }; |
923 | |
924 | template <> struct MappingTraits<ELFYAML::VerneedEntry> { |
925 | static void mapping(IO &IO, ELFYAML::VerneedEntry &E); |
926 | }; |
927 | |
928 | template <> struct MappingTraits<ELFYAML::VernauxEntry> { |
929 | static void mapping(IO &IO, ELFYAML::VernauxEntry &E); |
930 | }; |
931 | |
932 | template <> struct MappingTraits<ELFYAML::LinkerOption> { |
933 | static void mapping(IO &IO, ELFYAML::LinkerOption &Sym); |
934 | }; |
935 | |
936 | template <> struct MappingTraits<ELFYAML::CallGraphEntryWeight> { |
937 | static void mapping(IO &IO, ELFYAML::CallGraphEntryWeight &E); |
938 | }; |
939 | |
940 | template <> struct MappingTraits<ELFYAML::Relocation> { |
941 | static void mapping(IO &IO, ELFYAML::Relocation &Rel); |
942 | }; |
943 | |
944 | template <> struct MappingTraits<ELFYAML::ARMIndexTableEntry> { |
945 | static void mapping(IO &IO, ELFYAML::ARMIndexTableEntry &E); |
946 | }; |
947 | |
948 | template <> struct MappingTraits<std::unique_ptr<ELFYAML::Chunk>> { |
949 | static void mapping(IO &IO, std::unique_ptr<ELFYAML::Chunk> &C); |
950 | static std::string validate(IO &io, std::unique_ptr<ELFYAML::Chunk> &C); |
951 | }; |
952 | |
953 | template <> |
954 | struct MappingTraits<ELFYAML::Object> { |
955 | static void mapping(IO &IO, ELFYAML::Object &Object); |
956 | }; |
957 | |
958 | template <> struct MappingTraits<ELFYAML::SectionOrType> { |
959 | static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); |
960 | }; |
961 | |
962 | } // end namespace yaml |
963 | } // end namespace llvm |
964 | |
965 | #endif // LLVM_OBJECTYAML_ELFYAML_H |