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/STLExtras.h" |
11 | #include "llvm/ADT/Twine.h" |
12 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
13 | #include "llvm/Object/ELFObjectFile.h" |
14 | #include "llvm/ObjectYAML/DWARFYAML.h" |
15 | #include "llvm/ObjectYAML/ELFYAML.h" |
16 | #include "llvm/Support/DataExtractor.h" |
17 | #include "llvm/Support/Errc.h" |
18 | #include "llvm/Support/ErrorHandling.h" |
19 | #include "llvm/Support/YAMLTraits.h" |
20 | #include <optional> |
21 | |
22 | using namespace llvm; |
23 | |
24 | namespace { |
25 | |
26 | template <class ELFT> |
27 | class ELFDumper { |
28 | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
29 | |
30 | ArrayRef<Elf_Shdr> Sections; |
31 | ArrayRef<Elf_Sym> SymTable; |
32 | |
33 | DenseMap<StringRef, uint32_t> UsedSectionNames; |
34 | std::vector<std::string> SectionNames; |
35 | std::optional<uint32_t> ShStrTabIndex; |
36 | |
37 | DenseMap<StringRef, uint32_t> UsedSymbolNames; |
38 | std::vector<std::string> SymbolNames; |
39 | |
40 | BumpPtrAllocator StringAllocator; |
41 | |
42 | Expected<StringRef> getUniquedSectionName(const Elf_Shdr &Sec); |
43 | Expected<StringRef> getUniquedSymbolName(const Elf_Sym *Sym, |
44 | StringRef StrTable, |
45 | const Elf_Shdr *SymTab); |
46 | Expected<StringRef> getSymbolName(uint32_t SymtabNdx, uint32_t SymbolNdx); |
47 | |
48 | const object::ELFFile<ELFT> &Obj; |
49 | std::unique_ptr<DWARFContext> DWARFCtx; |
50 | |
51 | DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables; |
52 | |
53 | Expected<std::vector<ELFYAML::ProgramHeader>> |
54 | dumpProgramHeaders(ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Sections); |
55 | |
56 | std::optional<DWARFYAML::Data> |
57 | dumpDWARFSections(std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections); |
58 | |
59 | Error dumpSymbols(const Elf_Shdr *Symtab, |
60 | std::optional<std::vector<ELFYAML::Symbol>> &Symbols); |
61 | Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, |
62 | StringRef StrTable, ELFYAML::Symbol &S); |
63 | Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> dumpSections(); |
64 | Error dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S); |
65 | Error dumpCommonRelocationSection(const Elf_Shdr *Shdr, |
66 | ELFYAML::RelocationSection &S); |
67 | template <class RelT> |
68 | Error dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab, |
69 | ELFYAML::Relocation &R); |
70 | |
71 | Expected<ELFYAML::AddrsigSection *> dumpAddrsigSection(const Elf_Shdr *Shdr); |
72 | Expected<ELFYAML::LinkerOptionsSection *> |
73 | dumpLinkerOptionsSection(const Elf_Shdr *Shdr); |
74 | Expected<ELFYAML::DependentLibrariesSection *> |
75 | dumpDependentLibrariesSection(const Elf_Shdr *Shdr); |
76 | Expected<ELFYAML::CallGraphProfileSection *> |
77 | dumpCallGraphProfileSection(const Elf_Shdr *Shdr); |
78 | Expected<ELFYAML::DynamicSection *> dumpDynamicSection(const Elf_Shdr *Shdr); |
79 | Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr); |
80 | Expected<ELFYAML::RelrSection *> dumpRelrSection(const Elf_Shdr *Shdr); |
81 | Expected<ELFYAML::RawContentSection *> |
82 | dumpContentSection(const Elf_Shdr *Shdr); |
83 | Expected<ELFYAML::SymtabShndxSection *> |
84 | dumpSymtabShndxSection(const Elf_Shdr *Shdr); |
85 | Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr); |
86 | Expected<ELFYAML::HashSection *> dumpHashSection(const Elf_Shdr *Shdr); |
87 | Expected<ELFYAML::NoteSection *> dumpNoteSection(const Elf_Shdr *Shdr); |
88 | Expected<ELFYAML::GnuHashSection *> dumpGnuHashSection(const Elf_Shdr *Shdr); |
89 | Expected<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr); |
90 | Expected<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr); |
91 | Expected<ELFYAML::VerneedSection *> dumpVerneedSection(const Elf_Shdr *Shdr); |
92 | Expected<ELFYAML::GroupSection *> dumpGroupSection(const Elf_Shdr *Shdr); |
93 | Expected<ELFYAML::ARMIndexTableSection *> |
94 | dumpARMIndexTableSection(const Elf_Shdr *Shdr); |
95 | Expected<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr); |
96 | Expected<ELFYAML::StackSizesSection *> |
97 | dumpStackSizesSection(const Elf_Shdr *Shdr); |
98 | Expected<ELFYAML::BBAddrMapSection *> |
99 | dumpBBAddrMapSection(const Elf_Shdr *Shdr); |
100 | Expected<ELFYAML::RawContentSection *> |
101 | dumpPlaceholderSection(const Elf_Shdr *Shdr); |
102 | |
103 | bool shouldPrintSection(const ELFYAML::Section &S, const Elf_Shdr &SHdr, |
104 | std::optional<DWARFYAML::Data> DWARF); |
105 | |
106 | public: |
107 | ELFDumper(const object::ELFFile<ELFT> &O, std::unique_ptr<DWARFContext> DCtx); |
108 | Expected<ELFYAML::Object *> dump(); |
109 | }; |
110 | |
111 | } |
112 | |
113 | template <class ELFT> |
114 | ELFDumper<ELFT>::ELFDumper(const object::ELFFile<ELFT> &O, |
115 | std::unique_ptr<DWARFContext> DCtx) |
116 | : Obj(O), DWARFCtx(std::move(DCtx)) {} |
117 | |
118 | template <class ELFT> |
119 | Expected<StringRef> |
120 | ELFDumper<ELFT>::getUniquedSectionName(const Elf_Shdr &Sec) { |
121 | unsigned SecIndex = &Sec - &Sections[0]; |
122 | if (!SectionNames[SecIndex].empty()) |
123 | return SectionNames[SecIndex]; |
124 | |
125 | auto NameOrErr = Obj.getSectionName(Sec); |
126 | if (!NameOrErr) |
127 | return NameOrErr; |
128 | StringRef Name = *NameOrErr; |
129 | // In some specific cases we might have more than one section without a |
130 | // name (sh_name == 0). It normally doesn't happen, but when we have this case |
131 | // it doesn't make sense to uniquify their names and add noise to the output. |
132 | if (Name.empty()) |
133 | return "" ; |
134 | |
135 | std::string &Ret = SectionNames[SecIndex]; |
136 | |
137 | auto It = UsedSectionNames.insert(KV: {Name, 0}); |
138 | if (!It.second) |
139 | Ret = ELFYAML::appendUniqueSuffix(Name, Msg: Twine(++It.first->second)); |
140 | else |
141 | Ret = std::string(Name); |
142 | return Ret; |
143 | } |
144 | |
145 | template <class ELFT> |
146 | Expected<StringRef> |
147 | ELFDumper<ELFT>::getUniquedSymbolName(const Elf_Sym *Sym, StringRef StrTable, |
148 | const Elf_Shdr *SymTab) { |
149 | Expected<StringRef> SymbolNameOrErr = Sym->getName(StrTable); |
150 | if (!SymbolNameOrErr) |
151 | return SymbolNameOrErr; |
152 | StringRef Name = *SymbolNameOrErr; |
153 | if (Name.empty() && Sym->getType() == ELF::STT_SECTION) { |
154 | Expected<const Elf_Shdr *> ShdrOrErr = |
155 | Obj.getSection(*Sym, SymTab, ShndxTables.lookup(SymTab)); |
156 | if (!ShdrOrErr) |
157 | return ShdrOrErr.takeError(); |
158 | // The null section has no name. |
159 | return (*ShdrOrErr == nullptr) ? "" : getUniquedSectionName(Sec: **ShdrOrErr); |
160 | } |
161 | |
162 | // Symbols in .symtab can have duplicate names. For example, it is a common |
163 | // situation for local symbols in a relocatable object. Here we assign unique |
164 | // suffixes for such symbols so that we can differentiate them. |
165 | if (SymTab->sh_type == ELF::SHT_SYMTAB) { |
166 | unsigned Index = Sym - SymTable.data(); |
167 | if (!SymbolNames[Index].empty()) |
168 | return SymbolNames[Index]; |
169 | |
170 | auto It = UsedSymbolNames.insert(KV: {Name, 0}); |
171 | if (!It.second) |
172 | SymbolNames[Index] = |
173 | ELFYAML::appendUniqueSuffix(Name, Msg: Twine(++It.first->second)); |
174 | else |
175 | SymbolNames[Index] = std::string(Name); |
176 | return SymbolNames[Index]; |
177 | } |
178 | |
179 | return Name; |
180 | } |
181 | |
182 | template <class ELFT> |
183 | bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S, |
184 | const Elf_Shdr &SHdr, |
185 | std::optional<DWARFYAML::Data> DWARF) { |
186 | // We only print the SHT_NULL section at index 0 when it |
187 | // has at least one non-null field, because yaml2obj |
188 | // normally creates the zero section at index 0 implicitly. |
189 | if (S.Type == ELF::SHT_NULL && (&SHdr == &Sections[0])) { |
190 | const uint8_t *Begin = reinterpret_cast<const uint8_t *>(&SHdr); |
191 | const uint8_t *End = Begin + sizeof(Elf_Shdr); |
192 | return std::any_of(Begin, End, [](uint8_t V) { return V != 0; }); |
193 | } |
194 | |
195 | // Normally we use "DWARF:" to describe contents of DWARF sections. Sometimes |
196 | // the content of DWARF sections can be successfully parsed into the "DWARF:" |
197 | // entry but their section headers may have special flags, entry size, address |
198 | // alignment, etc. We will preserve the header for them under such |
199 | // circumstances. |
200 | StringRef SecName = S.Name.substr(Start: 1); |
201 | if (DWARF && DWARF->getNonEmptySectionNames().count(key: SecName)) { |
202 | if (const ELFYAML::RawContentSection *RawSec = |
203 | dyn_cast<const ELFYAML::RawContentSection>(Val: &S)) { |
204 | if (RawSec->Type != ELF::SHT_PROGBITS || RawSec->Link || RawSec->Info || |
205 | RawSec->AddressAlign != yaml::Hex64{1} || RawSec->Address || |
206 | RawSec->EntSize) |
207 | return true; |
208 | |
209 | ELFYAML::ELF_SHF ShFlags = RawSec->Flags.value_or(u: ELFYAML::ELF_SHF(0)); |
210 | |
211 | if (SecName == "debug_str" ) |
212 | return ShFlags != ELFYAML::ELF_SHF(ELF::SHF_MERGE | ELF::SHF_STRINGS); |
213 | |
214 | return ShFlags != ELFYAML::ELF_SHF{0}; |
215 | } |
216 | } |
217 | |
218 | // Normally we use "Symbols:" and "DynamicSymbols:" to describe contents of |
219 | // symbol tables. We also build and emit corresponding string tables |
220 | // implicitly. But sometimes it is important to preserve positions and virtual |
221 | // addresses of allocatable sections, e.g. for creating program headers. |
222 | // Generally we are trying to reduce noise in the YAML output. Because |
223 | // of that we do not print non-allocatable versions of such sections and |
224 | // assume they are placed at the end. |
225 | // We also dump symbol tables when the Size field is set. It happens when they |
226 | // are empty, which should not normally happen. |
227 | if (S.Type == ELF::SHT_STRTAB || S.Type == ELF::SHT_SYMTAB || |
228 | S.Type == ELF::SHT_DYNSYM) { |
229 | return S.Size || S.Flags.value_or(u: ELFYAML::ELF_SHF(0)) & ELF::SHF_ALLOC; |
230 | } |
231 | |
232 | return true; |
233 | } |
234 | |
235 | template <class ELFT> |
236 | static void (const typename ELFT::Ehdr &, |
237 | ArrayRef<ELFYAML::ProgramHeader> Phdrs, |
238 | std::vector<std::unique_ptr<ELFYAML::Chunk>> &V, |
239 | ArrayRef<typename ELFT::Shdr> S) { |
240 | if (V.empty()) |
241 | return; |
242 | |
243 | uint64_t ExpectedOffset; |
244 | if (Header.e_phoff > 0) |
245 | ExpectedOffset = Header.e_phoff + Header.e_phentsize * Header.e_phnum; |
246 | else |
247 | ExpectedOffset = sizeof(typename ELFT::Ehdr); |
248 | |
249 | for (const std::unique_ptr<ELFYAML::Chunk> &C : ArrayRef(V).drop_front()) { |
250 | ELFYAML::Section &Sec = *cast<ELFYAML::Section>(Val: C.get()); |
251 | const typename ELFT::Shdr &SecHdr = S[Sec.OriginalSecNdx]; |
252 | |
253 | ExpectedOffset = alignTo(ExpectedOffset, |
254 | SecHdr.sh_addralign ? SecHdr.sh_addralign : 1uLL); |
255 | |
256 | // We only set the "Offset" field when it can't be naturally derived |
257 | // from the offset and size of the previous section. This reduces |
258 | // the noise in the YAML output. |
259 | if (SecHdr.sh_offset != ExpectedOffset) |
260 | Sec.Offset = (yaml::Hex64)SecHdr.sh_offset; |
261 | |
262 | if (Sec.Type == ELF::SHT_NOBITS && |
263 | !ELFYAML::shouldAllocateFileSpace(Phdrs, |
264 | S: *cast<ELFYAML::NoBitsSection>(Val: &Sec))) |
265 | ExpectedOffset = SecHdr.sh_offset; |
266 | else |
267 | ExpectedOffset = SecHdr.sh_offset + SecHdr.sh_size; |
268 | } |
269 | } |
270 | |
271 | template <class ELFT> Expected<ELFYAML::Object *> ELFDumper<ELFT>::dump() { |
272 | auto Y = std::make_unique<ELFYAML::Object>(); |
273 | |
274 | // Dump header. We do not dump EPh* and ESh* fields. When not explicitly set, |
275 | // the values are set by yaml2obj automatically and there is no need to dump |
276 | // them here. |
277 | Y->Header.Class = ELFYAML::ELF_ELFCLASS(Obj.getHeader().getFileClass()); |
278 | Y->Header.Data = ELFYAML::ELF_ELFDATA(Obj.getHeader().getDataEncoding()); |
279 | Y->Header.OSABI = Obj.getHeader().e_ident[ELF::EI_OSABI]; |
280 | Y->Header.ABIVersion = Obj.getHeader().e_ident[ELF::EI_ABIVERSION]; |
281 | Y->Header.Type = Obj.getHeader().e_type; |
282 | if (Obj.getHeader().e_machine != 0) |
283 | Y->Header.Machine = ELFYAML::ELF_EM(Obj.getHeader().e_machine); |
284 | Y->Header.Flags = Obj.getHeader().e_flags; |
285 | Y->Header.Entry = Obj.getHeader().e_entry; |
286 | |
287 | // Dump sections |
288 | auto SectionsOrErr = Obj.sections(); |
289 | if (!SectionsOrErr) |
290 | return SectionsOrErr.takeError(); |
291 | Sections = *SectionsOrErr; |
292 | SectionNames.resize(Sections.size()); |
293 | |
294 | if (Sections.size() > 0) { |
295 | ShStrTabIndex = Obj.getHeader().e_shstrndx; |
296 | if (*ShStrTabIndex == ELF::SHN_XINDEX) |
297 | ShStrTabIndex = Sections[0].sh_link; |
298 | // TODO: Set EShStrndx if the value doesn't represent a real section. |
299 | } |
300 | |
301 | // Normally an object that does not have sections has e_shnum == 0. |
302 | // Also, e_shnum might be 0, when the number of entries in the section |
303 | // header table is larger than or equal to SHN_LORESERVE (0xff00). In this |
304 | // case the real number of entries is held in the sh_size member of the |
305 | // initial entry. We have a section header table when `e_shoff` is not 0. |
306 | if (Obj.getHeader().e_shoff != 0 && Obj.getHeader().e_shnum == 0) |
307 | Y->Header.EShNum = 0; |
308 | |
309 | // Dump symbols. We need to do this early because other sections might want |
310 | // to access the deduplicated symbol names that we also create here. |
311 | const Elf_Shdr *SymTab = nullptr; |
312 | const Elf_Shdr *DynSymTab = nullptr; |
313 | |
314 | for (const Elf_Shdr &Sec : Sections) { |
315 | if (Sec.sh_type == ELF::SHT_SYMTAB) { |
316 | SymTab = &Sec; |
317 | } else if (Sec.sh_type == ELF::SHT_DYNSYM) { |
318 | DynSymTab = &Sec; |
319 | } else if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) { |
320 | // We need to locate SHT_SYMTAB_SHNDX sections early, because they |
321 | // might be needed for dumping symbols. |
322 | if (Expected<ArrayRef<Elf_Word>> TableOrErr = Obj.getSHNDXTable(Sec)) { |
323 | // The `getSHNDXTable` calls the `getSection` internally when validates |
324 | // the symbol table section linked to the SHT_SYMTAB_SHNDX section. |
325 | const Elf_Shdr *LinkedSymTab = cantFail(Obj.getSection(Sec.sh_link)); |
326 | if (!ShndxTables.insert({LinkedSymTab, *TableOrErr}).second) |
327 | return createStringError( |
328 | EC: errc::invalid_argument, |
329 | S: "multiple SHT_SYMTAB_SHNDX sections are " |
330 | "linked to the same symbol table with index " + |
331 | Twine(Sec.sh_link)); |
332 | } else { |
333 | return createStringError(errc::invalid_argument, |
334 | "unable to read extended section indexes: " + |
335 | toString(TableOrErr.takeError())); |
336 | } |
337 | } |
338 | } |
339 | |
340 | if (SymTab) |
341 | if (Error E = dumpSymbols(Symtab: SymTab, Symbols&: Y->Symbols)) |
342 | return std::move(E); |
343 | |
344 | if (DynSymTab) |
345 | if (Error E = dumpSymbols(Symtab: DynSymTab, Symbols&: Y->DynamicSymbols)) |
346 | return std::move(E); |
347 | |
348 | // We dump all sections first. It is simple and allows us to verify that all |
349 | // sections are valid and also to generalize the code. But we are not going to |
350 | // keep all of them in the final output (see comments for |
351 | // 'shouldPrintSection()'). Undesired chunks will be removed later. |
352 | Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> ChunksOrErr = |
353 | dumpSections(); |
354 | if (!ChunksOrErr) |
355 | return ChunksOrErr.takeError(); |
356 | std::vector<std::unique_ptr<ELFYAML::Chunk>> Chunks = std::move(*ChunksOrErr); |
357 | |
358 | std::vector<ELFYAML::Section *> OriginalOrder; |
359 | if (!Chunks.empty()) |
360 | for (const std::unique_ptr<ELFYAML::Chunk> &C : |
361 | ArrayRef(Chunks).drop_front()) |
362 | OriginalOrder.push_back(x: cast<ELFYAML::Section>(Val: C.get())); |
363 | |
364 | // Sometimes the order of sections in the section header table does not match |
365 | // their actual order. Here we sort sections by the file offset. |
366 | llvm::stable_sort(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A, |
367 | const std::unique_ptr<ELFYAML::Chunk> &B) { |
368 | return Sections[cast<ELFYAML::Section>(Val: A.get())->OriginalSecNdx].sh_offset < |
369 | Sections[cast<ELFYAML::Section>(Val: B.get())->OriginalSecNdx].sh_offset; |
370 | }); |
371 | |
372 | // Dump program headers. |
373 | Expected<std::vector<ELFYAML::ProgramHeader>> PhdrsOrErr = |
374 | dumpProgramHeaders(Sections: Chunks); |
375 | if (!PhdrsOrErr) |
376 | return PhdrsOrErr.takeError(); |
377 | Y->ProgramHeaders = std::move(*PhdrsOrErr); |
378 | |
379 | dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks, |
380 | Sections); |
381 | |
382 | // Dump DWARF sections. |
383 | Y->DWARF = dumpDWARFSections(Sections&: Chunks); |
384 | |
385 | // We emit the "SectionHeaderTable" key when the order of sections in the |
386 | // sections header table doesn't match the file order. |
387 | const bool SectionsSorted = |
388 | llvm::is_sorted(Chunks, [&](const std::unique_ptr<ELFYAML::Chunk> &A, |
389 | const std::unique_ptr<ELFYAML::Chunk> &B) { |
390 | return cast<ELFYAML::Section>(Val: A.get())->OriginalSecNdx < |
391 | cast<ELFYAML::Section>(Val: B.get())->OriginalSecNdx; |
392 | }); |
393 | if (!SectionsSorted) { |
394 | std::unique_ptr<ELFYAML::SectionHeaderTable> SHT = |
395 | std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/args: false); |
396 | SHT->Sections.emplace(); |
397 | for (ELFYAML::Section *S : OriginalOrder) |
398 | SHT->Sections->push_back(x: {.Name: S->Name}); |
399 | Chunks.push_back(x: std::move(SHT)); |
400 | } |
401 | |
402 | llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) { |
403 | if (isa<ELFYAML::SectionHeaderTable>(Val: *C)) |
404 | return false; |
405 | |
406 | const ELFYAML::Section &S = cast<ELFYAML::Section>(Val&: *C); |
407 | return !shouldPrintSection(S, SHdr: Sections[S.OriginalSecNdx], DWARF: Y->DWARF); |
408 | }); |
409 | |
410 | // The section header string table by default is assumed to be called |
411 | // ".shstrtab" and be in its own unique section. However, it's possible for it |
412 | // to be called something else and shared with another section. If the name |
413 | // isn't the default, provide this in the YAML. |
414 | if (ShStrTabIndex && *ShStrTabIndex != ELF::SHN_UNDEF && |
415 | *ShStrTabIndex < Sections.size()) { |
416 | StringRef ShStrtabName; |
417 | if (SymTab && SymTab->sh_link == *ShStrTabIndex) { |
418 | // Section header string table is shared with the symbol table. Use that |
419 | // section's name (usually .strtab). |
420 | ShStrtabName = cantFail(Obj.getSectionName(Sections[SymTab->sh_link])); |
421 | } else if (DynSymTab && DynSymTab->sh_link == *ShStrTabIndex) { |
422 | // Section header string table is shared with the dynamic symbol table. |
423 | // Use that section's name (usually .dynstr). |
424 | ShStrtabName = cantFail(Obj.getSectionName(Sections[DynSymTab->sh_link])); |
425 | } else { |
426 | // Otherwise, the section name potentially needs uniquifying. |
427 | ShStrtabName = cantFail(getUniquedSectionName(Sec: Sections[*ShStrTabIndex])); |
428 | } |
429 | if (ShStrtabName != ".shstrtab" ) |
430 | Y->Header.SectionHeaderStringTable = ShStrtabName; |
431 | } |
432 | |
433 | Y->Chunks = std::move(Chunks); |
434 | return Y.release(); |
435 | } |
436 | |
437 | template <class ELFT> |
438 | static bool isInSegment(const ELFYAML::Section &Sec, |
439 | const typename ELFT::Shdr &SHdr, |
440 | const typename ELFT::Phdr &Phdr) { |
441 | if (Sec.Type == ELF::SHT_NULL) |
442 | return false; |
443 | |
444 | // A section is within a segment when its location in a file is within the |
445 | // [p_offset, p_offset + p_filesz] region. |
446 | bool FileOffsetsMatch = |
447 | SHdr.sh_offset >= Phdr.p_offset && |
448 | (SHdr.sh_offset + SHdr.sh_size <= Phdr.p_offset + Phdr.p_filesz); |
449 | |
450 | bool VirtualAddressesMatch = SHdr.sh_addr >= Phdr.p_vaddr && |
451 | SHdr.sh_addr <= Phdr.p_vaddr + Phdr.p_memsz; |
452 | |
453 | if (FileOffsetsMatch) { |
454 | // An empty section on the edges of a program header can be outside of the |
455 | // virtual address space of the segment. This means it is not included in |
456 | // the segment and we should ignore it. |
457 | if (SHdr.sh_size == 0 && (SHdr.sh_offset == Phdr.p_offset || |
458 | SHdr.sh_offset == Phdr.p_offset + Phdr.p_filesz)) |
459 | return VirtualAddressesMatch; |
460 | return true; |
461 | } |
462 | |
463 | // SHT_NOBITS sections usually occupy no physical space in a file. Such |
464 | // sections belong to a segment when they reside in the segment's virtual |
465 | // address space. |
466 | if (Sec.Type != ELF::SHT_NOBITS) |
467 | return false; |
468 | return VirtualAddressesMatch; |
469 | } |
470 | |
471 | template <class ELFT> |
472 | Expected<std::vector<ELFYAML::ProgramHeader>> |
473 | ELFDumper<ELFT>::( |
474 | ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Chunks) { |
475 | std::vector<ELFYAML::ProgramHeader> Ret; |
476 | Expected<typename ELFT::PhdrRange> PhdrsOrErr = Obj.program_headers(); |
477 | if (!PhdrsOrErr) |
478 | return PhdrsOrErr.takeError(); |
479 | |
480 | for (const typename ELFT::Phdr &Phdr : *PhdrsOrErr) { |
481 | ELFYAML::ProgramHeader PH; |
482 | PH.Type = Phdr.p_type; |
483 | PH.Flags = Phdr.p_flags; |
484 | PH.VAddr = Phdr.p_vaddr; |
485 | PH.PAddr = Phdr.p_paddr; |
486 | PH.Offset = Phdr.p_offset; |
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>(Val&: *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(x: C.get()); |
503 | } |
504 | } |
505 | |
506 | Ret.push_back(x: 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.starts_with(Prefix: ".debug_" )) |
518 | continue; |
519 | |
520 | if (ELFYAML::RawContentSection *RawSec = |
521 | dyn_cast<ELFYAML::RawContentSection>(Val: 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(Err: std::move(Err)); |
530 | |
531 | if (RawSec->Name == ".debug_aranges" ) |
532 | Err = dumpDebugARanges(DCtx&: *DWARFCtx, Y&: DWARF); |
533 | else if (RawSec->Name == ".debug_str" ) |
534 | Err = dumpDebugStrings(DCtx&: *DWARFCtx, Y&: DWARF); |
535 | else if (RawSec->Name == ".debug_ranges" ) |
536 | Err = dumpDebugRanges(DCtx&: *DWARFCtx, Y&: DWARF); |
537 | else if (RawSec->Name == ".debug_addr" ) |
538 | Err = dumpDebugAddr(DCtx&: *DWARFCtx, Y&: 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(Err: 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&: *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(args&: *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(Shdr: 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(Shdr: S); }; |
591 | |
592 | switch (Type) { |
593 | case ELF::SHT_DYNAMIC: |
594 | return [this](const Elf_Shdr *S) { return dumpDynamicSection(Shdr: S); }; |
595 | case ELF::SHT_SYMTAB_SHNDX: |
596 | return [this](const Elf_Shdr *S) { return dumpSymtabShndxSection(Shdr: S); }; |
597 | case ELF::SHT_REL: |
598 | case ELF::SHT_RELA: |
599 | case ELF::SHT_CREL: |
600 | return [this](const Elf_Shdr *S) { return dumpRelocSection(Shdr: S); }; |
601 | case ELF::SHT_RELR: |
602 | return [this](const Elf_Shdr *S) { return dumpRelrSection(Shdr: S); }; |
603 | case ELF::SHT_GROUP: |
604 | return [this](const Elf_Shdr *S) { return dumpGroupSection(Shdr: S); }; |
605 | case ELF::SHT_NOBITS: |
606 | return [this](const Elf_Shdr *S) { return dumpNoBitsSection(Shdr: S); }; |
607 | case ELF::SHT_NOTE: |
608 | return [this](const Elf_Shdr *S) { return dumpNoteSection(Shdr: S); }; |
609 | case ELF::SHT_HASH: |
610 | return [this](const Elf_Shdr *S) { return dumpHashSection(Shdr: S); }; |
611 | case ELF::SHT_GNU_HASH: |
612 | return [this](const Elf_Shdr *S) { return dumpGnuHashSection(Shdr: S); }; |
613 | case ELF::SHT_GNU_verdef: |
614 | return [this](const Elf_Shdr *S) { return dumpVerdefSection(Shdr: S); }; |
615 | case ELF::SHT_GNU_versym: |
616 | return [this](const Elf_Shdr *S) { return dumpSymverSection(Shdr: S); }; |
617 | case ELF::SHT_GNU_verneed: |
618 | return [this](const Elf_Shdr *S) { return dumpVerneedSection(Shdr: S); }; |
619 | case ELF::SHT_LLVM_ADDRSIG: |
620 | return [this](const Elf_Shdr *S) { return dumpAddrsigSection(Shdr: S); }; |
621 | case ELF::SHT_LLVM_LINKER_OPTIONS: |
622 | return [this](const Elf_Shdr *S) { return dumpLinkerOptionsSection(Shdr: S); }; |
623 | case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: |
624 | return [this](const Elf_Shdr *S) { |
625 | return dumpDependentLibrariesSection(Shdr: S); |
626 | }; |
627 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: |
628 | return |
629 | [this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(Shdr: S); }; |
630 | case ELF::SHT_LLVM_BB_ADDR_MAP: |
631 | return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(Shdr: 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(Shdr: 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(Name: *NameOrErr)) { |
661 | if (Error E = Add(dumpStackSizesSection(Shdr: &Sec))) |
662 | return std::move(E); |
663 | continue; |
664 | } |
665 | } |
666 | |
667 | if (Error E = Add(dumpContentSection(Shdr: &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: &Sym, SymTab: Symtab, StrTable: *StrTableOrErr, S)) |
701 | return EC; |
702 | Symbols->push_back(x: 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(Sec: *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, StrTable: *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(Sec: *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(Sec: **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(Sec: **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&: *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(C&: Cur); |
860 | uint64_t Size = Data.getULEB128(C&: Cur); |
861 | Entries.push_back(x: {.Address: Address, .Size: 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(Err: 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&: *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 | bool HasAnyPGOAnalysisMapEntry = false; |
894 | std::vector<ELFYAML::PGOAnalysisMapEntry> PGOAnalyses; |
895 | DataExtractor::Cursor Cur(0); |
896 | uint8_t Version = 0; |
897 | uint8_t Feature = 0; |
898 | uint64_t Address = 0; |
899 | while (Cur && Cur.tell() < Content.size()) { |
900 | if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) { |
901 | Version = Data.getU8(C&: Cur); |
902 | if (Cur && Version > 2) |
903 | return createStringError( |
904 | EC: errc::invalid_argument, |
905 | S: "invalid SHT_LLVM_BB_ADDR_MAP section version: " + |
906 | Twine(static_cast<int>(Version))); |
907 | Feature = Data.getU8(C&: Cur); |
908 | } |
909 | uint64_t NumBBRanges = 1; |
910 | uint64_t NumBlocks = 0; |
911 | uint32_t TotalNumBlocks = 0; |
912 | auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Val: Feature); |
913 | if (!FeatureOrErr) |
914 | return FeatureOrErr.takeError(); |
915 | if (FeatureOrErr->MultiBBRange) { |
916 | NumBBRanges = Data.getULEB128(C&: Cur); |
917 | } else { |
918 | Address = Data.getAddress(C&: Cur); |
919 | NumBlocks = Data.getULEB128(C&: Cur); |
920 | } |
921 | std::vector<ELFYAML::BBAddrMapEntry::BBRangeEntry> BBRanges; |
922 | uint64_t BaseAddress = 0; |
923 | for (uint64_t BBRangeN = 0; Cur && BBRangeN != NumBBRanges; ++BBRangeN) { |
924 | if (FeatureOrErr->MultiBBRange) { |
925 | BaseAddress = Data.getAddress(C&: Cur); |
926 | NumBlocks = Data.getULEB128(C&: Cur); |
927 | } else { |
928 | BaseAddress = Address; |
929 | } |
930 | |
931 | std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries; |
932 | // Read the specified number of BB entries, or until decoding fails. |
933 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks; |
934 | ++BlockIndex) { |
935 | uint32_t ID = Version >= 2 ? Data.getULEB128(C&: Cur) : BlockIndex; |
936 | uint64_t Offset = Data.getULEB128(C&: Cur); |
937 | uint64_t Size = Data.getULEB128(C&: Cur); |
938 | uint64_t Metadata = Data.getULEB128(C&: Cur); |
939 | BBEntries.push_back(x: {.ID: ID, .AddressOffset: Offset, .Size: Size, .Metadata: Metadata}); |
940 | } |
941 | TotalNumBlocks += BBEntries.size(); |
942 | BBRanges.push_back(x: {.BaseAddress: BaseAddress, /*NumBlocks=*/{}, .BBEntries: BBEntries}); |
943 | } |
944 | Entries.push_back( |
945 | x: {.Version: Version, .Feature: Feature, /*NumBBRanges=*/{}, .BBRanges: std::move(BBRanges)}); |
946 | |
947 | ELFYAML::PGOAnalysisMapEntry &PGOAnalysis = PGOAnalyses.emplace_back(); |
948 | if (FeatureOrErr->hasPGOAnalysis()) { |
949 | HasAnyPGOAnalysisMapEntry = true; |
950 | |
951 | if (FeatureOrErr->FuncEntryCount) |
952 | PGOAnalysis.FuncEntryCount = Data.getULEB128(C&: Cur); |
953 | |
954 | if (FeatureOrErr->hasPGOAnalysisBBData()) { |
955 | auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace(); |
956 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks; |
957 | ++BlockIndex) { |
958 | auto &PGOBBEntry = PGOBBEntries.emplace_back(); |
959 | if (FeatureOrErr->BBFreq) { |
960 | PGOBBEntry.BBFreq = Data.getULEB128(C&: Cur); |
961 | if (!Cur) |
962 | break; |
963 | } |
964 | |
965 | if (FeatureOrErr->BrProb) { |
966 | auto &SuccEntries = PGOBBEntry.Successors.emplace(); |
967 | uint64_t SuccCount = Data.getULEB128(C&: Cur); |
968 | for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) { |
969 | uint32_t ID = Data.getULEB128(C&: Cur); |
970 | uint32_t BrProb = Data.getULEB128(C&: Cur); |
971 | SuccEntries.push_back(x: {.ID: ID, .BrProb: BrProb}); |
972 | } |
973 | } |
974 | } |
975 | } |
976 | } |
977 | } |
978 | |
979 | if (!Cur) { |
980 | // If the section cannot be decoded, we dump it as an array of bytes. |
981 | consumeError(Err: Cur.takeError()); |
982 | S->Content = yaml::BinaryRef(Content); |
983 | } else { |
984 | S->Entries = std::move(Entries); |
985 | if (HasAnyPGOAnalysisMapEntry) |
986 | S->PGOAnalyses = std::move(PGOAnalyses); |
987 | } |
988 | |
989 | return S.release(); |
990 | } |
991 | |
992 | template <class ELFT> |
993 | Expected<ELFYAML::AddrsigSection *> |
994 | ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) { |
995 | auto S = std::make_unique<ELFYAML::AddrsigSection>(); |
996 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
997 | return std::move(E); |
998 | |
999 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1000 | if (!ContentOrErr) |
1001 | return ContentOrErr.takeError(); |
1002 | |
1003 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1004 | DataExtractor::Cursor Cur(0); |
1005 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1006 | std::vector<ELFYAML::YAMLFlowString> Symbols; |
1007 | while (Cur && Cur.tell() < Content.size()) { |
1008 | uint64_t SymNdx = Data.getULEB128(C&: Cur); |
1009 | if (!Cur) |
1010 | break; |
1011 | |
1012 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: SymNdx); |
1013 | if (!SymbolName || SymbolName->empty()) { |
1014 | consumeError(Err: SymbolName.takeError()); |
1015 | Symbols.emplace_back( |
1016 | args: StringRef(std::to_string(val: SymNdx)).copy(A&: StringAllocator)); |
1017 | continue; |
1018 | } |
1019 | |
1020 | Symbols.emplace_back(args&: *SymbolName); |
1021 | } |
1022 | |
1023 | if (Cur) { |
1024 | S->Symbols = std::move(Symbols); |
1025 | return S.release(); |
1026 | } |
1027 | |
1028 | consumeError(Err: Cur.takeError()); |
1029 | S->Content = yaml::BinaryRef(Content); |
1030 | return S.release(); |
1031 | } |
1032 | |
1033 | template <class ELFT> |
1034 | Expected<ELFYAML::LinkerOptionsSection *> |
1035 | ELFDumper<ELFT>::dumpLinkerOptionsSection(const Elf_Shdr *Shdr) { |
1036 | auto S = std::make_unique<ELFYAML::LinkerOptionsSection>(); |
1037 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1038 | return std::move(E); |
1039 | |
1040 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1041 | if (!ContentOrErr) |
1042 | return ContentOrErr.takeError(); |
1043 | |
1044 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1045 | if (Content.empty() || Content.back() != 0) { |
1046 | S->Content = Content; |
1047 | return S.release(); |
1048 | } |
1049 | |
1050 | SmallVector<StringRef, 16> Strings; |
1051 | toStringRef(Input: Content.drop_back()).split(A&: Strings, Separator: '\0'); |
1052 | if (Strings.size() % 2 != 0) { |
1053 | S->Content = Content; |
1054 | return S.release(); |
1055 | } |
1056 | |
1057 | S->Options.emplace(); |
1058 | for (size_t I = 0, E = Strings.size(); I != E; I += 2) |
1059 | S->Options->push_back(x: {.Key: Strings[I], .Value: Strings[I + 1]}); |
1060 | |
1061 | return S.release(); |
1062 | } |
1063 | |
1064 | template <class ELFT> |
1065 | Expected<ELFYAML::DependentLibrariesSection *> |
1066 | ELFDumper<ELFT>::dumpDependentLibrariesSection(const Elf_Shdr *Shdr) { |
1067 | auto DL = std::make_unique<ELFYAML::DependentLibrariesSection>(); |
1068 | if (Error E = dumpCommonSection(Shdr, S&: *DL)) |
1069 | return std::move(E); |
1070 | |
1071 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1072 | if (!ContentOrErr) |
1073 | return ContentOrErr.takeError(); |
1074 | |
1075 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1076 | if (!Content.empty() && Content.back() != 0) { |
1077 | DL->Content = Content; |
1078 | return DL.release(); |
1079 | } |
1080 | |
1081 | DL->Libs.emplace(); |
1082 | for (const uint8_t *I = Content.begin(), *E = Content.end(); I < E;) { |
1083 | StringRef Lib((const char *)I); |
1084 | DL->Libs->emplace_back(args&: Lib); |
1085 | I += Lib.size() + 1; |
1086 | } |
1087 | |
1088 | return DL.release(); |
1089 | } |
1090 | |
1091 | template <class ELFT> |
1092 | Expected<ELFYAML::CallGraphProfileSection *> |
1093 | ELFDumper<ELFT>::dumpCallGraphProfileSection(const Elf_Shdr *Shdr) { |
1094 | auto S = std::make_unique<ELFYAML::CallGraphProfileSection>(); |
1095 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1096 | return std::move(E); |
1097 | |
1098 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1099 | if (!ContentOrErr) |
1100 | return ContentOrErr.takeError(); |
1101 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1102 | const uint32_t SizeOfEntry = ELFYAML::getDefaultShEntSize<ELFT>( |
1103 | Obj.getHeader().e_machine, S->Type, S->Name); |
1104 | // Dump the section by using the Content key when it is truncated. |
1105 | // There is no need to create either "Content" or "Entries" fields when the |
1106 | // section is empty. |
1107 | if (Content.empty() || Content.size() % SizeOfEntry != 0) { |
1108 | if (!Content.empty()) |
1109 | S->Content = yaml::BinaryRef(Content); |
1110 | return S.release(); |
1111 | } |
1112 | |
1113 | std::vector<ELFYAML::CallGraphEntryWeight> Entries(Content.size() / |
1114 | SizeOfEntry); |
1115 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1116 | DataExtractor::Cursor Cur(0); |
1117 | auto ReadEntry = [&](ELFYAML::CallGraphEntryWeight &E) { |
1118 | E.Weight = Data.getU64(C&: Cur); |
1119 | if (!Cur) { |
1120 | consumeError(Err: Cur.takeError()); |
1121 | return false; |
1122 | } |
1123 | return true; |
1124 | }; |
1125 | |
1126 | for (ELFYAML::CallGraphEntryWeight &E : Entries) { |
1127 | if (ReadEntry(E)) |
1128 | continue; |
1129 | S->Content = yaml::BinaryRef(Content); |
1130 | return S.release(); |
1131 | } |
1132 | |
1133 | S->Entries = std::move(Entries); |
1134 | return S.release(); |
1135 | } |
1136 | |
1137 | template <class ELFT> |
1138 | Expected<ELFYAML::DynamicSection *> |
1139 | ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) { |
1140 | auto S = std::make_unique<ELFYAML::DynamicSection>(); |
1141 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1142 | return std::move(E); |
1143 | |
1144 | auto DynTagsOrErr = Obj.template getSectionContentsAsArray<Elf_Dyn>(*Shdr); |
1145 | if (!DynTagsOrErr) |
1146 | return DynTagsOrErr.takeError(); |
1147 | |
1148 | S->Entries.emplace(); |
1149 | for (const Elf_Dyn &Dyn : *DynTagsOrErr) |
1150 | S->Entries->push_back({(ELFYAML::ELF_DYNTAG)Dyn.getTag(), Dyn.getVal()}); |
1151 | |
1152 | return S.release(); |
1153 | } |
1154 | |
1155 | template <class ELFT> |
1156 | Expected<ELFYAML::RelocationSection *> |
1157 | ELFDumper<ELFT>::dumpRelocSection(const Elf_Shdr *Shdr) { |
1158 | auto S = std::make_unique<ELFYAML::RelocationSection>(); |
1159 | if (auto E = dumpCommonRelocationSection(Shdr, S&: *S)) |
1160 | return std::move(E); |
1161 | |
1162 | auto SymTabOrErr = Obj.getSection(Shdr->sh_link); |
1163 | if (!SymTabOrErr) |
1164 | return SymTabOrErr.takeError(); |
1165 | |
1166 | if (Shdr->sh_size != 0) |
1167 | S->Relocations.emplace(); |
1168 | |
1169 | std::vector<Elf_Rel> Rels; |
1170 | std::vector<Elf_Rela> Relas; |
1171 | if (Shdr->sh_type == ELF::SHT_CREL) { |
1172 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1173 | if (!ContentOrErr) |
1174 | return ContentOrErr.takeError(); |
1175 | auto Crel = Obj.decodeCrel(*ContentOrErr); |
1176 | if (!Crel) |
1177 | return Crel.takeError(); |
1178 | Rels = std::move(Crel->first); |
1179 | Relas = std::move(Crel->second); |
1180 | } else if (Shdr->sh_type == ELF::SHT_REL) { |
1181 | auto R = Obj.rels(*Shdr); |
1182 | if (!R) |
1183 | return R.takeError(); |
1184 | Rels = std::move(*R); |
1185 | } else { |
1186 | auto R = Obj.relas(*Shdr); |
1187 | if (!R) |
1188 | return R.takeError(); |
1189 | Relas = std::move(*R); |
1190 | } |
1191 | |
1192 | for (const Elf_Rel &Rel : Rels) { |
1193 | ELFYAML::Relocation R; |
1194 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
1195 | return std::move(E); |
1196 | S->Relocations->push_back(x: R); |
1197 | } |
1198 | for (const Elf_Rela &Rel : Relas) { |
1199 | ELFYAML::Relocation R; |
1200 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
1201 | return std::move(E); |
1202 | R.Addend = Rel.r_addend; |
1203 | S->Relocations->push_back(x: R); |
1204 | } |
1205 | |
1206 | return S.release(); |
1207 | } |
1208 | |
1209 | template <class ELFT> |
1210 | Expected<ELFYAML::RelrSection *> |
1211 | ELFDumper<ELFT>::dumpRelrSection(const Elf_Shdr *Shdr) { |
1212 | auto S = std::make_unique<ELFYAML::RelrSection>(); |
1213 | if (auto E = dumpCommonSection(Shdr, S&: *S)) |
1214 | return std::move(E); |
1215 | |
1216 | if (Expected<ArrayRef<Elf_Relr>> Relrs = Obj.relrs(*Shdr)) { |
1217 | S->Entries.emplace(); |
1218 | for (Elf_Relr Rel : *Relrs) |
1219 | S->Entries->emplace_back(Rel); |
1220 | return S.release(); |
1221 | } else { |
1222 | // Ignore. We are going to dump the data as raw content below. |
1223 | consumeError(Relrs.takeError()); |
1224 | } |
1225 | |
1226 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1227 | if (!ContentOrErr) |
1228 | return ContentOrErr.takeError(); |
1229 | S->Content = *ContentOrErr; |
1230 | return S.release(); |
1231 | } |
1232 | |
1233 | template <class ELFT> |
1234 | Expected<ELFYAML::RawContentSection *> |
1235 | ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { |
1236 | auto S = std::make_unique<ELFYAML::RawContentSection>(); |
1237 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1238 | return std::move(E); |
1239 | |
1240 | unsigned SecIndex = Shdr - &Sections[0]; |
1241 | if (SecIndex != 0 || Shdr->sh_type != ELF::SHT_NULL) { |
1242 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1243 | if (!ContentOrErr) |
1244 | return ContentOrErr.takeError(); |
1245 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1246 | if (!Content.empty()) |
1247 | S->Content = yaml::BinaryRef(Content); |
1248 | } else { |
1249 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
1250 | } |
1251 | |
1252 | if (Shdr->sh_info) |
1253 | S->Info = static_cast<llvm::yaml::Hex64>(Shdr->sh_info); |
1254 | return S.release(); |
1255 | } |
1256 | |
1257 | template <class ELFT> |
1258 | Expected<ELFYAML::SymtabShndxSection *> |
1259 | ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) { |
1260 | auto S = std::make_unique<ELFYAML::SymtabShndxSection>(); |
1261 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1262 | return std::move(E); |
1263 | |
1264 | auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
1265 | if (!EntriesOrErr) |
1266 | return EntriesOrErr.takeError(); |
1267 | |
1268 | S->Entries.emplace(); |
1269 | for (const Elf_Word &E : *EntriesOrErr) |
1270 | S->Entries->push_back(E); |
1271 | return S.release(); |
1272 | } |
1273 | |
1274 | template <class ELFT> |
1275 | Expected<ELFYAML::NoBitsSection *> |
1276 | ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { |
1277 | auto S = std::make_unique<ELFYAML::NoBitsSection>(); |
1278 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1279 | return std::move(E); |
1280 | if (Shdr->sh_size) |
1281 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
1282 | return S.release(); |
1283 | } |
1284 | |
1285 | template <class ELFT> |
1286 | Expected<ELFYAML::NoteSection *> |
1287 | ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) { |
1288 | auto S = std::make_unique<ELFYAML::NoteSection>(); |
1289 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1290 | return std::move(E); |
1291 | |
1292 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1293 | if (!ContentOrErr) |
1294 | return ContentOrErr.takeError(); |
1295 | |
1296 | std::vector<ELFYAML::NoteEntry> Entries; |
1297 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1298 | size_t Align = std::max<size_t>(Shdr->sh_addralign, 4); |
1299 | while (!Content.empty()) { |
1300 | if (Content.size() < sizeof(Elf_Nhdr)) { |
1301 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1302 | return S.release(); |
1303 | } |
1304 | |
1305 | const Elf_Nhdr * = reinterpret_cast<const Elf_Nhdr *>(Content.data()); |
1306 | if (Content.size() < Header->getSize(Align)) { |
1307 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1308 | return S.release(); |
1309 | } |
1310 | |
1311 | Elf_Note Note(*Header); |
1312 | Entries.push_back( |
1313 | {Note.getName(), Note.getDesc(Align), (ELFYAML::ELF_NT)Note.getType()}); |
1314 | |
1315 | Content = Content.drop_front(N: Header->getSize(Align)); |
1316 | } |
1317 | |
1318 | S->Notes = std::move(Entries); |
1319 | return S.release(); |
1320 | } |
1321 | |
1322 | template <class ELFT> |
1323 | Expected<ELFYAML::HashSection *> |
1324 | ELFDumper<ELFT>::dumpHashSection(const Elf_Shdr *Shdr) { |
1325 | auto S = std::make_unique<ELFYAML::HashSection>(); |
1326 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1327 | return std::move(E); |
1328 | |
1329 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1330 | if (!ContentOrErr) |
1331 | return ContentOrErr.takeError(); |
1332 | |
1333 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1334 | if (Content.size() % 4 != 0 || Content.size() < 8) { |
1335 | S->Content = yaml::BinaryRef(Content); |
1336 | return S.release(); |
1337 | } |
1338 | |
1339 | DataExtractor::Cursor Cur(0); |
1340 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1341 | uint64_t NBucket = Data.getU32(C&: Cur); |
1342 | uint64_t NChain = Data.getU32(C&: Cur); |
1343 | if (Content.size() != (2 + NBucket + NChain) * 4) { |
1344 | S->Content = yaml::BinaryRef(Content); |
1345 | if (Cur) |
1346 | return S.release(); |
1347 | llvm_unreachable("entries were not read correctly" ); |
1348 | } |
1349 | |
1350 | S->Bucket.emplace(args&: NBucket); |
1351 | for (uint32_t &V : *S->Bucket) |
1352 | V = Data.getU32(C&: Cur); |
1353 | |
1354 | S->Chain.emplace(args&: NChain); |
1355 | for (uint32_t &V : *S->Chain) |
1356 | V = Data.getU32(C&: Cur); |
1357 | |
1358 | if (Cur) |
1359 | return S.release(); |
1360 | llvm_unreachable("entries were not read correctly" ); |
1361 | } |
1362 | |
1363 | template <class ELFT> |
1364 | Expected<ELFYAML::GnuHashSection *> |
1365 | ELFDumper<ELFT>::dumpGnuHashSection(const Elf_Shdr *Shdr) { |
1366 | auto S = std::make_unique<ELFYAML::GnuHashSection>(); |
1367 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1368 | return std::move(E); |
1369 | |
1370 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1371 | if (!ContentOrErr) |
1372 | return ContentOrErr.takeError(); |
1373 | |
1374 | unsigned AddrSize = ELFT::Is64Bits ? 8 : 4; |
1375 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1376 | DataExtractor Data(Content, Obj.isLE(), AddrSize); |
1377 | |
1378 | ELFYAML::GnuHashHeader ; |
1379 | DataExtractor::Cursor Cur(0); |
1380 | uint64_t NBuckets = Data.getU32(C&: Cur); |
1381 | Header.SymNdx = Data.getU32(C&: Cur); |
1382 | uint64_t MaskWords = Data.getU32(C&: Cur); |
1383 | Header.Shift2 = Data.getU32(C&: Cur); |
1384 | |
1385 | // Set just the raw binary content if we were unable to read the header |
1386 | // or when the section data is truncated or malformed. |
1387 | uint64_t Size = Data.getData().size() - Cur.tell(); |
1388 | if (!Cur || (Size < MaskWords * AddrSize + NBuckets * 4) || |
1389 | (Size % 4 != 0)) { |
1390 | consumeError(Err: Cur.takeError()); |
1391 | S->Content = yaml::BinaryRef(Content); |
1392 | return S.release(); |
1393 | } |
1394 | |
1395 | S->Header = Header; |
1396 | |
1397 | S->BloomFilter.emplace(args&: MaskWords); |
1398 | for (llvm::yaml::Hex64 &Val : *S->BloomFilter) |
1399 | Val = Data.getAddress(C&: Cur); |
1400 | |
1401 | S->HashBuckets.emplace(args&: NBuckets); |
1402 | for (llvm::yaml::Hex32 &Val : *S->HashBuckets) |
1403 | Val = Data.getU32(C&: Cur); |
1404 | |
1405 | S->HashValues.emplace(args: (Data.getData().size() - Cur.tell()) / 4); |
1406 | for (llvm::yaml::Hex32 &Val : *S->HashValues) |
1407 | Val = Data.getU32(C&: Cur); |
1408 | |
1409 | if (Cur) |
1410 | return S.release(); |
1411 | llvm_unreachable("GnuHashSection was not read correctly" ); |
1412 | } |
1413 | |
1414 | template <class ELFT> |
1415 | Expected<ELFYAML::VerdefSection *> |
1416 | ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) { |
1417 | auto S = std::make_unique<ELFYAML::VerdefSection>(); |
1418 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1419 | return std::move(E); |
1420 | |
1421 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
1422 | if (!StringTableShdrOrErr) |
1423 | return StringTableShdrOrErr.takeError(); |
1424 | |
1425 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
1426 | if (!StringTableOrErr) |
1427 | return StringTableOrErr.takeError(); |
1428 | |
1429 | auto Contents = Obj.getSectionContents(*Shdr); |
1430 | if (!Contents) |
1431 | return Contents.takeError(); |
1432 | |
1433 | S->Entries.emplace(); |
1434 | |
1435 | llvm::ArrayRef<uint8_t> Data = *Contents; |
1436 | const uint8_t *Buf = Data.data(); |
1437 | while (Buf) { |
1438 | const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); |
1439 | ELFYAML::VerdefEntry Entry; |
1440 | if (Verdef->vd_version != 1) |
1441 | return createStringError(EC: errc::invalid_argument, |
1442 | S: "invalid SHT_GNU_verdef section version: " + |
1443 | Twine(Verdef->vd_version)); |
1444 | |
1445 | if (Verdef->vd_flags != 0) |
1446 | Entry.Flags = Verdef->vd_flags; |
1447 | |
1448 | if (Verdef->vd_ndx != 0) |
1449 | Entry.VersionNdx = Verdef->vd_ndx; |
1450 | |
1451 | if (Verdef->vd_hash != 0) |
1452 | Entry.Hash = Verdef->vd_hash; |
1453 | |
1454 | const uint8_t *BufAux = Buf + Verdef->vd_aux; |
1455 | while (BufAux) { |
1456 | const Elf_Verdaux *Verdaux = |
1457 | reinterpret_cast<const Elf_Verdaux *>(BufAux); |
1458 | Entry.VerNames.push_back( |
1459 | StringTableOrErr->drop_front(Verdaux->vda_name).data()); |
1460 | BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; |
1461 | } |
1462 | |
1463 | S->Entries->push_back(x: Entry); |
1464 | Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; |
1465 | } |
1466 | |
1467 | if (Shdr->sh_info != S->Entries->size()) |
1468 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
1469 | |
1470 | return S.release(); |
1471 | } |
1472 | |
1473 | template <class ELFT> |
1474 | Expected<ELFYAML::SymverSection *> |
1475 | ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { |
1476 | auto S = std::make_unique<ELFYAML::SymverSection>(); |
1477 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1478 | return std::move(E); |
1479 | |
1480 | auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(*Shdr); |
1481 | if (!VersionsOrErr) |
1482 | return VersionsOrErr.takeError(); |
1483 | |
1484 | S->Entries.emplace(); |
1485 | for (const Elf_Half &E : *VersionsOrErr) |
1486 | S->Entries->push_back(E); |
1487 | |
1488 | return S.release(); |
1489 | } |
1490 | |
1491 | template <class ELFT> |
1492 | Expected<ELFYAML::VerneedSection *> |
1493 | ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { |
1494 | auto S = std::make_unique<ELFYAML::VerneedSection>(); |
1495 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1496 | return std::move(E); |
1497 | |
1498 | auto Contents = Obj.getSectionContents(*Shdr); |
1499 | if (!Contents) |
1500 | return Contents.takeError(); |
1501 | |
1502 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
1503 | if (!StringTableShdrOrErr) |
1504 | return StringTableShdrOrErr.takeError(); |
1505 | |
1506 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
1507 | if (!StringTableOrErr) |
1508 | return StringTableOrErr.takeError(); |
1509 | |
1510 | S->VerneedV.emplace(); |
1511 | |
1512 | llvm::ArrayRef<uint8_t> Data = *Contents; |
1513 | const uint8_t *Buf = Data.data(); |
1514 | while (Buf) { |
1515 | const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); |
1516 | |
1517 | ELFYAML::VerneedEntry Entry; |
1518 | Entry.Version = Verneed->vn_version; |
1519 | Entry.File = |
1520 | StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data()); |
1521 | |
1522 | const uint8_t *BufAux = Buf + Verneed->vn_aux; |
1523 | while (BufAux) { |
1524 | const Elf_Vernaux *Vernaux = |
1525 | reinterpret_cast<const Elf_Vernaux *>(BufAux); |
1526 | |
1527 | ELFYAML::VernauxEntry Aux; |
1528 | Aux.Hash = Vernaux->vna_hash; |
1529 | Aux.Flags = Vernaux->vna_flags; |
1530 | Aux.Other = Vernaux->vna_other; |
1531 | Aux.Name = |
1532 | StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data()); |
1533 | |
1534 | Entry.AuxV.push_back(x: Aux); |
1535 | BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; |
1536 | } |
1537 | |
1538 | S->VerneedV->push_back(x: Entry); |
1539 | Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; |
1540 | } |
1541 | |
1542 | if (Shdr->sh_info != S->VerneedV->size()) |
1543 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
1544 | |
1545 | return S.release(); |
1546 | } |
1547 | |
1548 | template <class ELFT> |
1549 | Expected<StringRef> ELFDumper<ELFT>::getSymbolName(uint32_t SymtabNdx, |
1550 | uint32_t SymbolNdx) { |
1551 | auto SymtabOrErr = Obj.getSection(SymtabNdx); |
1552 | if (!SymtabOrErr) |
1553 | return SymtabOrErr.takeError(); |
1554 | |
1555 | const Elf_Shdr *Symtab = *SymtabOrErr; |
1556 | auto SymOrErr = Obj.getSymbol(Symtab, SymbolNdx); |
1557 | if (!SymOrErr) |
1558 | return SymOrErr.takeError(); |
1559 | |
1560 | auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab); |
1561 | if (!StrTabOrErr) |
1562 | return StrTabOrErr.takeError(); |
1563 | return getUniquedSymbolName(Sym: *SymOrErr, StrTable: *StrTabOrErr, SymTab: Symtab); |
1564 | } |
1565 | |
1566 | template <class ELFT> |
1567 | Expected<ELFYAML::GroupSection *> |
1568 | ELFDumper<ELFT>::dumpGroupSection(const Elf_Shdr *Shdr) { |
1569 | auto S = std::make_unique<ELFYAML::GroupSection>(); |
1570 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1571 | return std::move(E); |
1572 | |
1573 | // Get symbol with index sh_info. This symbol's name is the signature of the group. |
1574 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: Shdr->sh_info); |
1575 | if (!SymbolName) |
1576 | return SymbolName.takeError(); |
1577 | S->Signature = *SymbolName; |
1578 | |
1579 | auto MembersOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
1580 | if (!MembersOrErr) |
1581 | return MembersOrErr.takeError(); |
1582 | |
1583 | S->Members.emplace(); |
1584 | for (Elf_Word Member : *MembersOrErr) { |
1585 | if (Member == llvm::ELF::GRP_COMDAT) { |
1586 | S->Members->push_back(x: {.sectionNameOrType: "GRP_COMDAT" }); |
1587 | continue; |
1588 | } |
1589 | |
1590 | Expected<const Elf_Shdr *> SHdrOrErr = Obj.getSection(Member); |
1591 | if (!SHdrOrErr) |
1592 | return SHdrOrErr.takeError(); |
1593 | Expected<StringRef> NameOrErr = getUniquedSectionName(Sec: **SHdrOrErr); |
1594 | if (!NameOrErr) |
1595 | return NameOrErr.takeError(); |
1596 | S->Members->push_back(x: {.sectionNameOrType: *NameOrErr}); |
1597 | } |
1598 | return S.release(); |
1599 | } |
1600 | |
1601 | template <class ELFT> |
1602 | Expected<ELFYAML::ARMIndexTableSection *> |
1603 | ELFDumper<ELFT>::dumpARMIndexTableSection(const Elf_Shdr *Shdr) { |
1604 | auto S = std::make_unique<ELFYAML::ARMIndexTableSection>(); |
1605 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1606 | return std::move(E); |
1607 | |
1608 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1609 | if (!ContentOrErr) |
1610 | return ContentOrErr.takeError(); |
1611 | |
1612 | if (ContentOrErr->size() % (sizeof(Elf_Word) * 2) != 0) { |
1613 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1614 | return S.release(); |
1615 | } |
1616 | |
1617 | ArrayRef<Elf_Word> Words( |
1618 | reinterpret_cast<const Elf_Word *>(ContentOrErr->data()), |
1619 | ContentOrErr->size() / sizeof(Elf_Word)); |
1620 | |
1621 | S->Entries.emplace(); |
1622 | for (size_t I = 0, E = Words.size(); I != E; I += 2) |
1623 | S->Entries->push_back(x: {.Offset: (yaml::Hex32)Words[I], .Value: (yaml::Hex32)Words[I + 1]}); |
1624 | |
1625 | return S.release(); |
1626 | } |
1627 | |
1628 | template <class ELFT> |
1629 | Expected<ELFYAML::MipsABIFlags *> |
1630 | ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) { |
1631 | assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && |
1632 | "Section type is not SHT_MIPS_ABIFLAGS" ); |
1633 | auto S = std::make_unique<ELFYAML::MipsABIFlags>(); |
1634 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1635 | return std::move(E); |
1636 | |
1637 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1638 | if (!ContentOrErr) |
1639 | return ContentOrErr.takeError(); |
1640 | |
1641 | auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>( |
1642 | ContentOrErr.get().data()); |
1643 | S->Version = Flags->version; |
1644 | S->ISALevel = Flags->isa_level; |
1645 | S->ISARevision = Flags->isa_rev; |
1646 | S->GPRSize = Flags->gpr_size; |
1647 | S->CPR1Size = Flags->cpr1_size; |
1648 | S->CPR2Size = Flags->cpr2_size; |
1649 | S->FpABI = Flags->fp_abi; |
1650 | S->ISAExtension = Flags->isa_ext; |
1651 | S->ASEs = Flags->ases; |
1652 | S->Flags1 = Flags->flags1; |
1653 | S->Flags2 = Flags->flags2; |
1654 | return S.release(); |
1655 | } |
1656 | |
1657 | template <class ELFT> |
1658 | static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj, |
1659 | std::unique_ptr<DWARFContext> DWARFCtx) { |
1660 | ELFDumper<ELFT> Dumper(Obj, std::move(DWARFCtx)); |
1661 | Expected<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); |
1662 | if (!YAMLOrErr) |
1663 | return YAMLOrErr.takeError(); |
1664 | |
1665 | std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); |
1666 | yaml::Output Yout(Out); |
1667 | Yout << *YAML; |
1668 | |
1669 | return Error::success(); |
1670 | } |
1671 | |
1672 | Error elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { |
1673 | std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); |
1674 | if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(Val: &Obj)) |
1675 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1676 | |
1677 | if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(Val: &Obj)) |
1678 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1679 | |
1680 | if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(Val: &Obj)) |
1681 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1682 | |
1683 | if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(Val: &Obj)) |
1684 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1685 | |
1686 | llvm_unreachable("unknown ELF file format" ); |
1687 | } |
1688 | |