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 | return [this](const Elf_Shdr *S) { return dumpRelocSection(Shdr: S); }; |
600 | case ELF::SHT_RELR: |
601 | return [this](const Elf_Shdr *S) { return dumpRelrSection(Shdr: S); }; |
602 | case ELF::SHT_GROUP: |
603 | return [this](const Elf_Shdr *S) { return dumpGroupSection(Shdr: S); }; |
604 | case ELF::SHT_NOBITS: |
605 | return [this](const Elf_Shdr *S) { return dumpNoBitsSection(Shdr: S); }; |
606 | case ELF::SHT_NOTE: |
607 | return [this](const Elf_Shdr *S) { return dumpNoteSection(Shdr: S); }; |
608 | case ELF::SHT_HASH: |
609 | return [this](const Elf_Shdr *S) { return dumpHashSection(Shdr: S); }; |
610 | case ELF::SHT_GNU_HASH: |
611 | return [this](const Elf_Shdr *S) { return dumpGnuHashSection(Shdr: S); }; |
612 | case ELF::SHT_GNU_verdef: |
613 | return [this](const Elf_Shdr *S) { return dumpVerdefSection(Shdr: S); }; |
614 | case ELF::SHT_GNU_versym: |
615 | return [this](const Elf_Shdr *S) { return dumpSymverSection(Shdr: S); }; |
616 | case ELF::SHT_GNU_verneed: |
617 | return [this](const Elf_Shdr *S) { return dumpVerneedSection(Shdr: S); }; |
618 | case ELF::SHT_LLVM_ADDRSIG: |
619 | return [this](const Elf_Shdr *S) { return dumpAddrsigSection(Shdr: S); }; |
620 | case ELF::SHT_LLVM_LINKER_OPTIONS: |
621 | return [this](const Elf_Shdr *S) { return dumpLinkerOptionsSection(Shdr: S); }; |
622 | case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: |
623 | return [this](const Elf_Shdr *S) { |
624 | return dumpDependentLibrariesSection(Shdr: S); |
625 | }; |
626 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: |
627 | return |
628 | [this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(Shdr: S); }; |
629 | case ELF::SHT_LLVM_BB_ADDR_MAP: |
630 | return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(Shdr: S); }; |
631 | case ELF::SHT_STRTAB: |
632 | case ELF::SHT_SYMTAB: |
633 | case ELF::SHT_DYNSYM: |
634 | // The contents of these sections are described by other parts of the YAML |
635 | // file. But we still want to dump them, because their properties can be |
636 | // important. See comments for 'shouldPrintSection()' for more details. |
637 | return [this](const Elf_Shdr *S) { return dumpPlaceholderSection(Shdr: S); }; |
638 | default: |
639 | return nullptr; |
640 | } |
641 | }; |
642 | |
643 | for (const Elf_Shdr &Sec : Sections) { |
644 | // We have dedicated dumping functions for most of the section types. |
645 | // Try to use one of them first. |
646 | if (std::function<Expected<ELFYAML::Chunk *>(const Elf_Shdr *)> DumpFn = |
647 | GetDumper(Sec.sh_type)) { |
648 | if (Error E = Add(DumpFn(&Sec))) |
649 | return std::move(E); |
650 | continue; |
651 | } |
652 | |
653 | // Recognize some special SHT_PROGBITS sections by name. |
654 | if (Sec.sh_type == ELF::SHT_PROGBITS) { |
655 | auto NameOrErr = Obj.getSectionName(Sec); |
656 | if (!NameOrErr) |
657 | return NameOrErr.takeError(); |
658 | |
659 | if (ELFYAML::StackSizesSection::nameMatches(Name: *NameOrErr)) { |
660 | if (Error E = Add(dumpStackSizesSection(Shdr: &Sec))) |
661 | return std::move(E); |
662 | continue; |
663 | } |
664 | } |
665 | |
666 | if (Error E = Add(dumpContentSection(Shdr: &Sec))) |
667 | return std::move(E); |
668 | } |
669 | |
670 | return std::move(Ret); |
671 | } |
672 | |
673 | template <class ELFT> |
674 | Error ELFDumper<ELFT>::dumpSymbols( |
675 | const Elf_Shdr *Symtab, |
676 | std::optional<std::vector<ELFYAML::Symbol>> &Symbols) { |
677 | if (!Symtab) |
678 | return Error::success(); |
679 | |
680 | auto SymtabOrErr = Obj.symbols(Symtab); |
681 | if (!SymtabOrErr) |
682 | return SymtabOrErr.takeError(); |
683 | |
684 | if (SymtabOrErr->empty()) |
685 | return Error::success(); |
686 | |
687 | auto StrTableOrErr = Obj.getStringTableForSymtab(*Symtab); |
688 | if (!StrTableOrErr) |
689 | return StrTableOrErr.takeError(); |
690 | |
691 | if (Symtab->sh_type == ELF::SHT_SYMTAB) { |
692 | SymTable = *SymtabOrErr; |
693 | SymbolNames.resize(SymTable.size()); |
694 | } |
695 | |
696 | Symbols.emplace(); |
697 | for (const auto &Sym : (*SymtabOrErr).drop_front()) { |
698 | ELFYAML::Symbol S; |
699 | if (auto EC = dumpSymbol(Sym: &Sym, SymTab: Symtab, StrTable: *StrTableOrErr, S)) |
700 | return EC; |
701 | Symbols->push_back(x: S); |
702 | } |
703 | |
704 | return Error::success(); |
705 | } |
706 | |
707 | template <class ELFT> |
708 | Error ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, |
709 | StringRef StrTable, ELFYAML::Symbol &S) { |
710 | S.Type = Sym->getType(); |
711 | if (Sym->st_value) |
712 | S.Value = (yaml::Hex64)Sym->st_value; |
713 | if (Sym->st_size) |
714 | S.Size = (yaml::Hex64)Sym->st_size; |
715 | S.Other = Sym->st_other; |
716 | S.Binding = Sym->getBinding(); |
717 | |
718 | Expected<StringRef> SymbolNameOrErr = |
719 | getUniquedSymbolName(Sym, StrTable, SymTab); |
720 | if (!SymbolNameOrErr) |
721 | return SymbolNameOrErr.takeError(); |
722 | S.Name = SymbolNameOrErr.get(); |
723 | |
724 | if (Sym->st_shndx >= ELF::SHN_LORESERVE) { |
725 | S.Index = (ELFYAML::ELF_SHN)Sym->st_shndx; |
726 | return Error::success(); |
727 | } |
728 | |
729 | auto ShdrOrErr = Obj.getSection(*Sym, SymTab, ShndxTables.lookup(SymTab)); |
730 | if (!ShdrOrErr) |
731 | return ShdrOrErr.takeError(); |
732 | const Elf_Shdr *Shdr = *ShdrOrErr; |
733 | if (!Shdr) |
734 | return Error::success(); |
735 | |
736 | auto NameOrErr = getUniquedSectionName(Sec: *Shdr); |
737 | if (!NameOrErr) |
738 | return NameOrErr.takeError(); |
739 | S.Section = NameOrErr.get(); |
740 | |
741 | return Error::success(); |
742 | } |
743 | |
744 | template <class ELFT> |
745 | template <class RelT> |
746 | Error ELFDumper<ELFT>::dumpRelocation(const RelT *Rel, const Elf_Shdr *SymTab, |
747 | ELFYAML::Relocation &R) { |
748 | R.Type = Rel->getType(Obj.isMips64EL()); |
749 | R.Offset = Rel->r_offset; |
750 | R.Addend = 0; |
751 | |
752 | auto SymOrErr = Obj.getRelocationSymbol(*Rel, SymTab); |
753 | if (!SymOrErr) |
754 | return SymOrErr.takeError(); |
755 | |
756 | // We have might have a relocation with symbol index 0, |
757 | // e.g. R_X86_64_NONE or R_X86_64_GOTPC32. |
758 | const Elf_Sym *Sym = *SymOrErr; |
759 | if (!Sym) |
760 | return Error::success(); |
761 | |
762 | auto StrTabSec = Obj.getSection(SymTab->sh_link); |
763 | if (!StrTabSec) |
764 | return StrTabSec.takeError(); |
765 | auto StrTabOrErr = Obj.getStringTable(**StrTabSec); |
766 | if (!StrTabOrErr) |
767 | return StrTabOrErr.takeError(); |
768 | |
769 | Expected<StringRef> NameOrErr = |
770 | getUniquedSymbolName(Sym, StrTable: *StrTabOrErr, SymTab); |
771 | if (!NameOrErr) |
772 | return NameOrErr.takeError(); |
773 | R.Symbol = NameOrErr.get(); |
774 | |
775 | return Error::success(); |
776 | } |
777 | |
778 | template <class ELFT> |
779 | Error ELFDumper<ELFT>::dumpCommonSection(const Elf_Shdr *Shdr, |
780 | ELFYAML::Section &S) { |
781 | // Dump fields. We do not dump the ShOffset field. When not explicitly |
782 | // set, the value is set by yaml2obj automatically. |
783 | S.Type = Shdr->sh_type; |
784 | if (Shdr->sh_flags) |
785 | S.Flags = static_cast<ELFYAML::ELF_SHF>(Shdr->sh_flags); |
786 | if (Shdr->sh_addr) |
787 | S.Address = static_cast<uint64_t>(Shdr->sh_addr); |
788 | S.AddressAlign = Shdr->sh_addralign; |
789 | |
790 | S.OriginalSecNdx = Shdr - &Sections[0]; |
791 | |
792 | Expected<StringRef> NameOrErr = getUniquedSectionName(Sec: *Shdr); |
793 | if (!NameOrErr) |
794 | return NameOrErr.takeError(); |
795 | S.Name = NameOrErr.get(); |
796 | |
797 | if (Shdr->sh_entsize != ELFYAML::getDefaultShEntSize<ELFT>( |
798 | Obj.getHeader().e_machine, S.Type, S.Name)) |
799 | S.EntSize = static_cast<llvm::yaml::Hex64>(Shdr->sh_entsize); |
800 | |
801 | if (Shdr->sh_link != ELF::SHN_UNDEF) { |
802 | Expected<const Elf_Shdr *> LinkSection = Obj.getSection(Shdr->sh_link); |
803 | if (!LinkSection) |
804 | return make_error<StringError>( |
805 | "unable to resolve sh_link reference in section '" + S.Name + |
806 | "': " + toString(LinkSection.takeError()), |
807 | inconvertibleErrorCode()); |
808 | |
809 | NameOrErr = getUniquedSectionName(Sec: **LinkSection); |
810 | if (!NameOrErr) |
811 | return NameOrErr.takeError(); |
812 | S.Link = NameOrErr.get(); |
813 | } |
814 | |
815 | return Error::success(); |
816 | } |
817 | |
818 | template <class ELFT> |
819 | Error ELFDumper<ELFT>::dumpCommonRelocationSection( |
820 | const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S) { |
821 | if (Error E = dumpCommonSection(Shdr, S)) |
822 | return E; |
823 | |
824 | // Having a zero sh_info field is normal: .rela.dyn is a dynamic |
825 | // relocation section that normally has no value in this field. |
826 | if (!Shdr->sh_info) |
827 | return Error::success(); |
828 | |
829 | auto InfoSection = Obj.getSection(Shdr->sh_info); |
830 | if (!InfoSection) |
831 | return InfoSection.takeError(); |
832 | |
833 | Expected<StringRef> NameOrErr = getUniquedSectionName(Sec: **InfoSection); |
834 | if (!NameOrErr) |
835 | return NameOrErr.takeError(); |
836 | S.RelocatableSec = NameOrErr.get(); |
837 | |
838 | return Error::success(); |
839 | } |
840 | |
841 | template <class ELFT> |
842 | Expected<ELFYAML::StackSizesSection *> |
843 | ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) { |
844 | auto S = std::make_unique<ELFYAML::StackSizesSection>(); |
845 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
846 | return std::move(E); |
847 | |
848 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
849 | if (!ContentOrErr) |
850 | return ContentOrErr.takeError(); |
851 | |
852 | ArrayRef<uint8_t> Content = *ContentOrErr; |
853 | DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4); |
854 | |
855 | std::vector<ELFYAML::StackSizeEntry> Entries; |
856 | DataExtractor::Cursor Cur(0); |
857 | while (Cur && Cur.tell() < Content.size()) { |
858 | uint64_t Address = Data.getAddress(C&: Cur); |
859 | uint64_t Size = Data.getULEB128(C&: Cur); |
860 | Entries.push_back(x: {.Address: Address, .Size: Size}); |
861 | } |
862 | |
863 | if (Content.empty() || !Cur) { |
864 | // If .stack_sizes cannot be decoded, we dump it as an array of bytes. |
865 | consumeError(Err: Cur.takeError()); |
866 | S->Content = yaml::BinaryRef(Content); |
867 | } else { |
868 | S->Entries = std::move(Entries); |
869 | } |
870 | |
871 | return S.release(); |
872 | } |
873 | |
874 | template <class ELFT> |
875 | Expected<ELFYAML::BBAddrMapSection *> |
876 | ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) { |
877 | auto S = std::make_unique<ELFYAML::BBAddrMapSection>(); |
878 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
879 | return std::move(E); |
880 | |
881 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
882 | if (!ContentOrErr) |
883 | return ContentOrErr.takeError(); |
884 | |
885 | ArrayRef<uint8_t> Content = *ContentOrErr; |
886 | if (Content.empty()) |
887 | return S.release(); |
888 | |
889 | DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4); |
890 | |
891 | std::vector<ELFYAML::BBAddrMapEntry> Entries; |
892 | bool HasAnyPGOAnalysisMapEntry = false; |
893 | std::vector<ELFYAML::PGOAnalysisMapEntry> PGOAnalyses; |
894 | DataExtractor::Cursor Cur(0); |
895 | uint8_t Version = 0; |
896 | uint8_t Feature = 0; |
897 | uint64_t Address = 0; |
898 | while (Cur && Cur.tell() < Content.size()) { |
899 | if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) { |
900 | Version = Data.getU8(C&: Cur); |
901 | if (Cur && Version > 2) |
902 | return createStringError( |
903 | EC: errc::invalid_argument, |
904 | S: "invalid SHT_LLVM_BB_ADDR_MAP section version: " + |
905 | Twine(static_cast<int>(Version))); |
906 | Feature = Data.getU8(C&: Cur); |
907 | } |
908 | uint64_t NumBBRanges = 1; |
909 | uint64_t NumBlocks = 0; |
910 | uint32_t TotalNumBlocks = 0; |
911 | auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Val: Feature); |
912 | if (!FeatureOrErr) |
913 | return FeatureOrErr.takeError(); |
914 | if (FeatureOrErr->MultiBBRange) { |
915 | NumBBRanges = Data.getULEB128(C&: Cur); |
916 | } else { |
917 | Address = Data.getAddress(C&: Cur); |
918 | NumBlocks = Data.getULEB128(C&: Cur); |
919 | } |
920 | std::vector<ELFYAML::BBAddrMapEntry::BBRangeEntry> BBRanges; |
921 | uint64_t BaseAddress = 0; |
922 | for (uint64_t BBRangeN = 0; Cur && BBRangeN != NumBBRanges; ++BBRangeN) { |
923 | if (FeatureOrErr->MultiBBRange) { |
924 | BaseAddress = Data.getAddress(C&: Cur); |
925 | NumBlocks = Data.getULEB128(C&: Cur); |
926 | } else { |
927 | BaseAddress = Address; |
928 | } |
929 | |
930 | std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries; |
931 | // Read the specified number of BB entries, or until decoding fails. |
932 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks; |
933 | ++BlockIndex) { |
934 | uint32_t ID = Version >= 2 ? Data.getULEB128(C&: Cur) : BlockIndex; |
935 | uint64_t Offset = Data.getULEB128(C&: Cur); |
936 | uint64_t Size = Data.getULEB128(C&: Cur); |
937 | uint64_t Metadata = Data.getULEB128(C&: Cur); |
938 | BBEntries.push_back(x: {.ID: ID, .AddressOffset: Offset, .Size: Size, .Metadata: Metadata}); |
939 | } |
940 | TotalNumBlocks += BBEntries.size(); |
941 | BBRanges.push_back(x: {.BaseAddress: BaseAddress, /*NumBlocks=*/{}, .BBEntries: BBEntries}); |
942 | } |
943 | Entries.push_back( |
944 | x: {.Version: Version, .Feature: Feature, /*NumBBRanges=*/{}, .BBRanges: std::move(BBRanges)}); |
945 | |
946 | ELFYAML::PGOAnalysisMapEntry &PGOAnalysis = PGOAnalyses.emplace_back(); |
947 | if (FeatureOrErr->hasPGOAnalysis()) { |
948 | HasAnyPGOAnalysisMapEntry = true; |
949 | |
950 | if (FeatureOrErr->FuncEntryCount) |
951 | PGOAnalysis.FuncEntryCount = Data.getULEB128(C&: Cur); |
952 | |
953 | if (FeatureOrErr->hasPGOAnalysisBBData()) { |
954 | auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace(); |
955 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks; |
956 | ++BlockIndex) { |
957 | auto &PGOBBEntry = PGOBBEntries.emplace_back(); |
958 | if (FeatureOrErr->BBFreq) { |
959 | PGOBBEntry.BBFreq = Data.getULEB128(C&: Cur); |
960 | if (!Cur) |
961 | break; |
962 | } |
963 | |
964 | if (FeatureOrErr->BrProb) { |
965 | auto &SuccEntries = PGOBBEntry.Successors.emplace(); |
966 | uint64_t SuccCount = Data.getULEB128(C&: Cur); |
967 | for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) { |
968 | uint32_t ID = Data.getULEB128(C&: Cur); |
969 | uint32_t BrProb = Data.getULEB128(C&: Cur); |
970 | SuccEntries.push_back(x: {.ID: ID, .BrProb: BrProb}); |
971 | } |
972 | } |
973 | } |
974 | } |
975 | } |
976 | } |
977 | |
978 | if (!Cur) { |
979 | // If the section cannot be decoded, we dump it as an array of bytes. |
980 | consumeError(Err: Cur.takeError()); |
981 | S->Content = yaml::BinaryRef(Content); |
982 | } else { |
983 | S->Entries = std::move(Entries); |
984 | if (HasAnyPGOAnalysisMapEntry) |
985 | S->PGOAnalyses = std::move(PGOAnalyses); |
986 | } |
987 | |
988 | return S.release(); |
989 | } |
990 | |
991 | template <class ELFT> |
992 | Expected<ELFYAML::AddrsigSection *> |
993 | ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) { |
994 | auto S = std::make_unique<ELFYAML::AddrsigSection>(); |
995 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
996 | return std::move(E); |
997 | |
998 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
999 | if (!ContentOrErr) |
1000 | return ContentOrErr.takeError(); |
1001 | |
1002 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1003 | DataExtractor::Cursor Cur(0); |
1004 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1005 | std::vector<ELFYAML::YAMLFlowString> Symbols; |
1006 | while (Cur && Cur.tell() < Content.size()) { |
1007 | uint64_t SymNdx = Data.getULEB128(C&: Cur); |
1008 | if (!Cur) |
1009 | break; |
1010 | |
1011 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: SymNdx); |
1012 | if (!SymbolName || SymbolName->empty()) { |
1013 | consumeError(Err: SymbolName.takeError()); |
1014 | Symbols.emplace_back( |
1015 | args: StringRef(std::to_string(val: SymNdx)).copy(A&: StringAllocator)); |
1016 | continue; |
1017 | } |
1018 | |
1019 | Symbols.emplace_back(args&: *SymbolName); |
1020 | } |
1021 | |
1022 | if (Cur) { |
1023 | S->Symbols = std::move(Symbols); |
1024 | return S.release(); |
1025 | } |
1026 | |
1027 | consumeError(Err: Cur.takeError()); |
1028 | S->Content = yaml::BinaryRef(Content); |
1029 | return S.release(); |
1030 | } |
1031 | |
1032 | template <class ELFT> |
1033 | Expected<ELFYAML::LinkerOptionsSection *> |
1034 | ELFDumper<ELFT>::dumpLinkerOptionsSection(const Elf_Shdr *Shdr) { |
1035 | auto S = std::make_unique<ELFYAML::LinkerOptionsSection>(); |
1036 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1037 | return std::move(E); |
1038 | |
1039 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1040 | if (!ContentOrErr) |
1041 | return ContentOrErr.takeError(); |
1042 | |
1043 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1044 | if (Content.empty() || Content.back() != 0) { |
1045 | S->Content = Content; |
1046 | return S.release(); |
1047 | } |
1048 | |
1049 | SmallVector<StringRef, 16> Strings; |
1050 | toStringRef(Input: Content.drop_back()).split(A&: Strings, Separator: '\0'); |
1051 | if (Strings.size() % 2 != 0) { |
1052 | S->Content = Content; |
1053 | return S.release(); |
1054 | } |
1055 | |
1056 | S->Options.emplace(); |
1057 | for (size_t I = 0, E = Strings.size(); I != E; I += 2) |
1058 | S->Options->push_back(x: {.Key: Strings[I], .Value: Strings[I + 1]}); |
1059 | |
1060 | return S.release(); |
1061 | } |
1062 | |
1063 | template <class ELFT> |
1064 | Expected<ELFYAML::DependentLibrariesSection *> |
1065 | ELFDumper<ELFT>::dumpDependentLibrariesSection(const Elf_Shdr *Shdr) { |
1066 | auto DL = std::make_unique<ELFYAML::DependentLibrariesSection>(); |
1067 | if (Error E = dumpCommonSection(Shdr, S&: *DL)) |
1068 | return std::move(E); |
1069 | |
1070 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1071 | if (!ContentOrErr) |
1072 | return ContentOrErr.takeError(); |
1073 | |
1074 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1075 | if (!Content.empty() && Content.back() != 0) { |
1076 | DL->Content = Content; |
1077 | return DL.release(); |
1078 | } |
1079 | |
1080 | DL->Libs.emplace(); |
1081 | for (const uint8_t *I = Content.begin(), *E = Content.end(); I < E;) { |
1082 | StringRef Lib((const char *)I); |
1083 | DL->Libs->emplace_back(args&: Lib); |
1084 | I += Lib.size() + 1; |
1085 | } |
1086 | |
1087 | return DL.release(); |
1088 | } |
1089 | |
1090 | template <class ELFT> |
1091 | Expected<ELFYAML::CallGraphProfileSection *> |
1092 | ELFDumper<ELFT>::dumpCallGraphProfileSection(const Elf_Shdr *Shdr) { |
1093 | auto S = std::make_unique<ELFYAML::CallGraphProfileSection>(); |
1094 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1095 | return std::move(E); |
1096 | |
1097 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1098 | if (!ContentOrErr) |
1099 | return ContentOrErr.takeError(); |
1100 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1101 | const uint32_t SizeOfEntry = ELFYAML::getDefaultShEntSize<ELFT>( |
1102 | Obj.getHeader().e_machine, S->Type, S->Name); |
1103 | // Dump the section by using the Content key when it is truncated. |
1104 | // There is no need to create either "Content" or "Entries" fields when the |
1105 | // section is empty. |
1106 | if (Content.empty() || Content.size() % SizeOfEntry != 0) { |
1107 | if (!Content.empty()) |
1108 | S->Content = yaml::BinaryRef(Content); |
1109 | return S.release(); |
1110 | } |
1111 | |
1112 | std::vector<ELFYAML::CallGraphEntryWeight> Entries(Content.size() / |
1113 | SizeOfEntry); |
1114 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1115 | DataExtractor::Cursor Cur(0); |
1116 | auto ReadEntry = [&](ELFYAML::CallGraphEntryWeight &E) { |
1117 | E.Weight = Data.getU64(C&: Cur); |
1118 | if (!Cur) { |
1119 | consumeError(Err: Cur.takeError()); |
1120 | return false; |
1121 | } |
1122 | return true; |
1123 | }; |
1124 | |
1125 | for (ELFYAML::CallGraphEntryWeight &E : Entries) { |
1126 | if (ReadEntry(E)) |
1127 | continue; |
1128 | S->Content = yaml::BinaryRef(Content); |
1129 | return S.release(); |
1130 | } |
1131 | |
1132 | S->Entries = std::move(Entries); |
1133 | return S.release(); |
1134 | } |
1135 | |
1136 | template <class ELFT> |
1137 | Expected<ELFYAML::DynamicSection *> |
1138 | ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) { |
1139 | auto S = std::make_unique<ELFYAML::DynamicSection>(); |
1140 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1141 | return std::move(E); |
1142 | |
1143 | auto DynTagsOrErr = Obj.template getSectionContentsAsArray<Elf_Dyn>(*Shdr); |
1144 | if (!DynTagsOrErr) |
1145 | return DynTagsOrErr.takeError(); |
1146 | |
1147 | S->Entries.emplace(); |
1148 | for (const Elf_Dyn &Dyn : *DynTagsOrErr) |
1149 | S->Entries->push_back({(ELFYAML::ELF_DYNTAG)Dyn.getTag(), Dyn.getVal()}); |
1150 | |
1151 | return S.release(); |
1152 | } |
1153 | |
1154 | template <class ELFT> |
1155 | Expected<ELFYAML::RelocationSection *> |
1156 | ELFDumper<ELFT>::dumpRelocSection(const Elf_Shdr *Shdr) { |
1157 | auto S = std::make_unique<ELFYAML::RelocationSection>(); |
1158 | if (auto E = dumpCommonRelocationSection(Shdr, S&: *S)) |
1159 | return std::move(E); |
1160 | |
1161 | auto SymTabOrErr = Obj.getSection(Shdr->sh_link); |
1162 | if (!SymTabOrErr) |
1163 | return SymTabOrErr.takeError(); |
1164 | |
1165 | if (Shdr->sh_size != 0) |
1166 | S->Relocations.emplace(); |
1167 | |
1168 | if (Shdr->sh_type == ELF::SHT_REL) { |
1169 | auto Rels = Obj.rels(*Shdr); |
1170 | if (!Rels) |
1171 | return Rels.takeError(); |
1172 | for (const Elf_Rel &Rel : *Rels) { |
1173 | ELFYAML::Relocation R; |
1174 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
1175 | return std::move(E); |
1176 | S->Relocations->push_back(x: R); |
1177 | } |
1178 | } else { |
1179 | auto Rels = Obj.relas(*Shdr); |
1180 | if (!Rels) |
1181 | return Rels.takeError(); |
1182 | for (const Elf_Rela &Rel : *Rels) { |
1183 | ELFYAML::Relocation R; |
1184 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
1185 | return std::move(E); |
1186 | R.Addend = Rel.r_addend; |
1187 | S->Relocations->push_back(x: R); |
1188 | } |
1189 | } |
1190 | |
1191 | return S.release(); |
1192 | } |
1193 | |
1194 | template <class ELFT> |
1195 | Expected<ELFYAML::RelrSection *> |
1196 | ELFDumper<ELFT>::dumpRelrSection(const Elf_Shdr *Shdr) { |
1197 | auto S = std::make_unique<ELFYAML::RelrSection>(); |
1198 | if (auto E = dumpCommonSection(Shdr, S&: *S)) |
1199 | return std::move(E); |
1200 | |
1201 | if (Expected<ArrayRef<Elf_Relr>> Relrs = Obj.relrs(*Shdr)) { |
1202 | S->Entries.emplace(); |
1203 | for (Elf_Relr Rel : *Relrs) |
1204 | S->Entries->emplace_back(Rel); |
1205 | return S.release(); |
1206 | } else { |
1207 | // Ignore. We are going to dump the data as raw content below. |
1208 | consumeError(Relrs.takeError()); |
1209 | } |
1210 | |
1211 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1212 | if (!ContentOrErr) |
1213 | return ContentOrErr.takeError(); |
1214 | S->Content = *ContentOrErr; |
1215 | return S.release(); |
1216 | } |
1217 | |
1218 | template <class ELFT> |
1219 | Expected<ELFYAML::RawContentSection *> |
1220 | ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { |
1221 | auto S = std::make_unique<ELFYAML::RawContentSection>(); |
1222 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1223 | return std::move(E); |
1224 | |
1225 | unsigned SecIndex = Shdr - &Sections[0]; |
1226 | if (SecIndex != 0 || Shdr->sh_type != ELF::SHT_NULL) { |
1227 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1228 | if (!ContentOrErr) |
1229 | return ContentOrErr.takeError(); |
1230 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1231 | if (!Content.empty()) |
1232 | S->Content = yaml::BinaryRef(Content); |
1233 | } else { |
1234 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
1235 | } |
1236 | |
1237 | if (Shdr->sh_info) |
1238 | S->Info = static_cast<llvm::yaml::Hex64>(Shdr->sh_info); |
1239 | return S.release(); |
1240 | } |
1241 | |
1242 | template <class ELFT> |
1243 | Expected<ELFYAML::SymtabShndxSection *> |
1244 | ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) { |
1245 | auto S = std::make_unique<ELFYAML::SymtabShndxSection>(); |
1246 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1247 | return std::move(E); |
1248 | |
1249 | auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
1250 | if (!EntriesOrErr) |
1251 | return EntriesOrErr.takeError(); |
1252 | |
1253 | S->Entries.emplace(); |
1254 | for (const Elf_Word &E : *EntriesOrErr) |
1255 | S->Entries->push_back(E); |
1256 | return S.release(); |
1257 | } |
1258 | |
1259 | template <class ELFT> |
1260 | Expected<ELFYAML::NoBitsSection *> |
1261 | ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { |
1262 | auto S = std::make_unique<ELFYAML::NoBitsSection>(); |
1263 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1264 | return std::move(E); |
1265 | if (Shdr->sh_size) |
1266 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
1267 | return S.release(); |
1268 | } |
1269 | |
1270 | template <class ELFT> |
1271 | Expected<ELFYAML::NoteSection *> |
1272 | ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) { |
1273 | auto S = std::make_unique<ELFYAML::NoteSection>(); |
1274 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1275 | return std::move(E); |
1276 | |
1277 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1278 | if (!ContentOrErr) |
1279 | return ContentOrErr.takeError(); |
1280 | |
1281 | std::vector<ELFYAML::NoteEntry> Entries; |
1282 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1283 | size_t Align = std::max<size_t>(Shdr->sh_addralign, 4); |
1284 | while (!Content.empty()) { |
1285 | if (Content.size() < sizeof(Elf_Nhdr)) { |
1286 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1287 | return S.release(); |
1288 | } |
1289 | |
1290 | const Elf_Nhdr * = reinterpret_cast<const Elf_Nhdr *>(Content.data()); |
1291 | if (Content.size() < Header->getSize(Align)) { |
1292 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1293 | return S.release(); |
1294 | } |
1295 | |
1296 | Elf_Note Note(*Header); |
1297 | Entries.push_back( |
1298 | {Note.getName(), Note.getDesc(Align), (ELFYAML::ELF_NT)Note.getType()}); |
1299 | |
1300 | Content = Content.drop_front(N: Header->getSize(Align)); |
1301 | } |
1302 | |
1303 | S->Notes = std::move(Entries); |
1304 | return S.release(); |
1305 | } |
1306 | |
1307 | template <class ELFT> |
1308 | Expected<ELFYAML::HashSection *> |
1309 | ELFDumper<ELFT>::dumpHashSection(const Elf_Shdr *Shdr) { |
1310 | auto S = std::make_unique<ELFYAML::HashSection>(); |
1311 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1312 | return std::move(E); |
1313 | |
1314 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1315 | if (!ContentOrErr) |
1316 | return ContentOrErr.takeError(); |
1317 | |
1318 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1319 | if (Content.size() % 4 != 0 || Content.size() < 8) { |
1320 | S->Content = yaml::BinaryRef(Content); |
1321 | return S.release(); |
1322 | } |
1323 | |
1324 | DataExtractor::Cursor Cur(0); |
1325 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
1326 | uint64_t NBucket = Data.getU32(C&: Cur); |
1327 | uint64_t NChain = Data.getU32(C&: Cur); |
1328 | if (Content.size() != (2 + NBucket + NChain) * 4) { |
1329 | S->Content = yaml::BinaryRef(Content); |
1330 | if (Cur) |
1331 | return S.release(); |
1332 | llvm_unreachable("entries were not read correctly" ); |
1333 | } |
1334 | |
1335 | S->Bucket.emplace(args&: NBucket); |
1336 | for (uint32_t &V : *S->Bucket) |
1337 | V = Data.getU32(C&: Cur); |
1338 | |
1339 | S->Chain.emplace(args&: NChain); |
1340 | for (uint32_t &V : *S->Chain) |
1341 | V = Data.getU32(C&: Cur); |
1342 | |
1343 | if (Cur) |
1344 | return S.release(); |
1345 | llvm_unreachable("entries were not read correctly" ); |
1346 | } |
1347 | |
1348 | template <class ELFT> |
1349 | Expected<ELFYAML::GnuHashSection *> |
1350 | ELFDumper<ELFT>::dumpGnuHashSection(const Elf_Shdr *Shdr) { |
1351 | auto S = std::make_unique<ELFYAML::GnuHashSection>(); |
1352 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1353 | return std::move(E); |
1354 | |
1355 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1356 | if (!ContentOrErr) |
1357 | return ContentOrErr.takeError(); |
1358 | |
1359 | unsigned AddrSize = ELFT::Is64Bits ? 8 : 4; |
1360 | ArrayRef<uint8_t> Content = *ContentOrErr; |
1361 | DataExtractor Data(Content, Obj.isLE(), AddrSize); |
1362 | |
1363 | ELFYAML::GnuHashHeader ; |
1364 | DataExtractor::Cursor Cur(0); |
1365 | uint64_t NBuckets = Data.getU32(C&: Cur); |
1366 | Header.SymNdx = Data.getU32(C&: Cur); |
1367 | uint64_t MaskWords = Data.getU32(C&: Cur); |
1368 | Header.Shift2 = Data.getU32(C&: Cur); |
1369 | |
1370 | // Set just the raw binary content if we were unable to read the header |
1371 | // or when the section data is truncated or malformed. |
1372 | uint64_t Size = Data.getData().size() - Cur.tell(); |
1373 | if (!Cur || (Size < MaskWords * AddrSize + NBuckets * 4) || |
1374 | (Size % 4 != 0)) { |
1375 | consumeError(Err: Cur.takeError()); |
1376 | S->Content = yaml::BinaryRef(Content); |
1377 | return S.release(); |
1378 | } |
1379 | |
1380 | S->Header = Header; |
1381 | |
1382 | S->BloomFilter.emplace(args&: MaskWords); |
1383 | for (llvm::yaml::Hex64 &Val : *S->BloomFilter) |
1384 | Val = Data.getAddress(C&: Cur); |
1385 | |
1386 | S->HashBuckets.emplace(args&: NBuckets); |
1387 | for (llvm::yaml::Hex32 &Val : *S->HashBuckets) |
1388 | Val = Data.getU32(C&: Cur); |
1389 | |
1390 | S->HashValues.emplace(args: (Data.getData().size() - Cur.tell()) / 4); |
1391 | for (llvm::yaml::Hex32 &Val : *S->HashValues) |
1392 | Val = Data.getU32(C&: Cur); |
1393 | |
1394 | if (Cur) |
1395 | return S.release(); |
1396 | llvm_unreachable("GnuHashSection was not read correctly" ); |
1397 | } |
1398 | |
1399 | template <class ELFT> |
1400 | Expected<ELFYAML::VerdefSection *> |
1401 | ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) { |
1402 | auto S = std::make_unique<ELFYAML::VerdefSection>(); |
1403 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1404 | return std::move(E); |
1405 | |
1406 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
1407 | if (!StringTableShdrOrErr) |
1408 | return StringTableShdrOrErr.takeError(); |
1409 | |
1410 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
1411 | if (!StringTableOrErr) |
1412 | return StringTableOrErr.takeError(); |
1413 | |
1414 | auto Contents = Obj.getSectionContents(*Shdr); |
1415 | if (!Contents) |
1416 | return Contents.takeError(); |
1417 | |
1418 | S->Entries.emplace(); |
1419 | |
1420 | llvm::ArrayRef<uint8_t> Data = *Contents; |
1421 | const uint8_t *Buf = Data.data(); |
1422 | while (Buf) { |
1423 | const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); |
1424 | ELFYAML::VerdefEntry Entry; |
1425 | if (Verdef->vd_version != 1) |
1426 | return createStringError(EC: errc::invalid_argument, |
1427 | S: "invalid SHT_GNU_verdef section version: " + |
1428 | Twine(Verdef->vd_version)); |
1429 | |
1430 | if (Verdef->vd_flags != 0) |
1431 | Entry.Flags = Verdef->vd_flags; |
1432 | |
1433 | if (Verdef->vd_ndx != 0) |
1434 | Entry.VersionNdx = Verdef->vd_ndx; |
1435 | |
1436 | if (Verdef->vd_hash != 0) |
1437 | Entry.Hash = Verdef->vd_hash; |
1438 | |
1439 | const uint8_t *BufAux = Buf + Verdef->vd_aux; |
1440 | while (BufAux) { |
1441 | const Elf_Verdaux *Verdaux = |
1442 | reinterpret_cast<const Elf_Verdaux *>(BufAux); |
1443 | Entry.VerNames.push_back( |
1444 | StringTableOrErr->drop_front(Verdaux->vda_name).data()); |
1445 | BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; |
1446 | } |
1447 | |
1448 | S->Entries->push_back(x: Entry); |
1449 | Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; |
1450 | } |
1451 | |
1452 | if (Shdr->sh_info != S->Entries->size()) |
1453 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
1454 | |
1455 | return S.release(); |
1456 | } |
1457 | |
1458 | template <class ELFT> |
1459 | Expected<ELFYAML::SymverSection *> |
1460 | ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { |
1461 | auto S = std::make_unique<ELFYAML::SymverSection>(); |
1462 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1463 | return std::move(E); |
1464 | |
1465 | auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(*Shdr); |
1466 | if (!VersionsOrErr) |
1467 | return VersionsOrErr.takeError(); |
1468 | |
1469 | S->Entries.emplace(); |
1470 | for (const Elf_Half &E : *VersionsOrErr) |
1471 | S->Entries->push_back(E); |
1472 | |
1473 | return S.release(); |
1474 | } |
1475 | |
1476 | template <class ELFT> |
1477 | Expected<ELFYAML::VerneedSection *> |
1478 | ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { |
1479 | auto S = std::make_unique<ELFYAML::VerneedSection>(); |
1480 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1481 | return std::move(E); |
1482 | |
1483 | auto Contents = Obj.getSectionContents(*Shdr); |
1484 | if (!Contents) |
1485 | return Contents.takeError(); |
1486 | |
1487 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
1488 | if (!StringTableShdrOrErr) |
1489 | return StringTableShdrOrErr.takeError(); |
1490 | |
1491 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
1492 | if (!StringTableOrErr) |
1493 | return StringTableOrErr.takeError(); |
1494 | |
1495 | S->VerneedV.emplace(); |
1496 | |
1497 | llvm::ArrayRef<uint8_t> Data = *Contents; |
1498 | const uint8_t *Buf = Data.data(); |
1499 | while (Buf) { |
1500 | const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); |
1501 | |
1502 | ELFYAML::VerneedEntry Entry; |
1503 | Entry.Version = Verneed->vn_version; |
1504 | Entry.File = |
1505 | StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data()); |
1506 | |
1507 | const uint8_t *BufAux = Buf + Verneed->vn_aux; |
1508 | while (BufAux) { |
1509 | const Elf_Vernaux *Vernaux = |
1510 | reinterpret_cast<const Elf_Vernaux *>(BufAux); |
1511 | |
1512 | ELFYAML::VernauxEntry Aux; |
1513 | Aux.Hash = Vernaux->vna_hash; |
1514 | Aux.Flags = Vernaux->vna_flags; |
1515 | Aux.Other = Vernaux->vna_other; |
1516 | Aux.Name = |
1517 | StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data()); |
1518 | |
1519 | Entry.AuxV.push_back(x: Aux); |
1520 | BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; |
1521 | } |
1522 | |
1523 | S->VerneedV->push_back(x: Entry); |
1524 | Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; |
1525 | } |
1526 | |
1527 | if (Shdr->sh_info != S->VerneedV->size()) |
1528 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
1529 | |
1530 | return S.release(); |
1531 | } |
1532 | |
1533 | template <class ELFT> |
1534 | Expected<StringRef> ELFDumper<ELFT>::getSymbolName(uint32_t SymtabNdx, |
1535 | uint32_t SymbolNdx) { |
1536 | auto SymtabOrErr = Obj.getSection(SymtabNdx); |
1537 | if (!SymtabOrErr) |
1538 | return SymtabOrErr.takeError(); |
1539 | |
1540 | const Elf_Shdr *Symtab = *SymtabOrErr; |
1541 | auto SymOrErr = Obj.getSymbol(Symtab, SymbolNdx); |
1542 | if (!SymOrErr) |
1543 | return SymOrErr.takeError(); |
1544 | |
1545 | auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab); |
1546 | if (!StrTabOrErr) |
1547 | return StrTabOrErr.takeError(); |
1548 | return getUniquedSymbolName(Sym: *SymOrErr, StrTable: *StrTabOrErr, SymTab: Symtab); |
1549 | } |
1550 | |
1551 | template <class ELFT> |
1552 | Expected<ELFYAML::GroupSection *> |
1553 | ELFDumper<ELFT>::dumpGroupSection(const Elf_Shdr *Shdr) { |
1554 | auto S = std::make_unique<ELFYAML::GroupSection>(); |
1555 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1556 | return std::move(E); |
1557 | |
1558 | // Get symbol with index sh_info. This symbol's name is the signature of the group. |
1559 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: Shdr->sh_info); |
1560 | if (!SymbolName) |
1561 | return SymbolName.takeError(); |
1562 | S->Signature = *SymbolName; |
1563 | |
1564 | auto MembersOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
1565 | if (!MembersOrErr) |
1566 | return MembersOrErr.takeError(); |
1567 | |
1568 | S->Members.emplace(); |
1569 | for (Elf_Word Member : *MembersOrErr) { |
1570 | if (Member == llvm::ELF::GRP_COMDAT) { |
1571 | S->Members->push_back(x: {.sectionNameOrType: "GRP_COMDAT" }); |
1572 | continue; |
1573 | } |
1574 | |
1575 | Expected<const Elf_Shdr *> SHdrOrErr = Obj.getSection(Member); |
1576 | if (!SHdrOrErr) |
1577 | return SHdrOrErr.takeError(); |
1578 | Expected<StringRef> NameOrErr = getUniquedSectionName(Sec: **SHdrOrErr); |
1579 | if (!NameOrErr) |
1580 | return NameOrErr.takeError(); |
1581 | S->Members->push_back(x: {.sectionNameOrType: *NameOrErr}); |
1582 | } |
1583 | return S.release(); |
1584 | } |
1585 | |
1586 | template <class ELFT> |
1587 | Expected<ELFYAML::ARMIndexTableSection *> |
1588 | ELFDumper<ELFT>::dumpARMIndexTableSection(const Elf_Shdr *Shdr) { |
1589 | auto S = std::make_unique<ELFYAML::ARMIndexTableSection>(); |
1590 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1591 | return std::move(E); |
1592 | |
1593 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
1594 | if (!ContentOrErr) |
1595 | return ContentOrErr.takeError(); |
1596 | |
1597 | if (ContentOrErr->size() % (sizeof(Elf_Word) * 2) != 0) { |
1598 | S->Content = yaml::BinaryRef(*ContentOrErr); |
1599 | return S.release(); |
1600 | } |
1601 | |
1602 | ArrayRef<Elf_Word> Words( |
1603 | reinterpret_cast<const Elf_Word *>(ContentOrErr->data()), |
1604 | ContentOrErr->size() / sizeof(Elf_Word)); |
1605 | |
1606 | S->Entries.emplace(); |
1607 | for (size_t I = 0, E = Words.size(); I != E; I += 2) |
1608 | S->Entries->push_back(x: {.Offset: (yaml::Hex32)Words[I], .Value: (yaml::Hex32)Words[I + 1]}); |
1609 | |
1610 | return S.release(); |
1611 | } |
1612 | |
1613 | template <class ELFT> |
1614 | Expected<ELFYAML::MipsABIFlags *> |
1615 | ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) { |
1616 | assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && |
1617 | "Section type is not SHT_MIPS_ABIFLAGS" ); |
1618 | auto S = std::make_unique<ELFYAML::MipsABIFlags>(); |
1619 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
1620 | return std::move(E); |
1621 | |
1622 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
1623 | if (!ContentOrErr) |
1624 | return ContentOrErr.takeError(); |
1625 | |
1626 | auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>( |
1627 | ContentOrErr.get().data()); |
1628 | S->Version = Flags->version; |
1629 | S->ISALevel = Flags->isa_level; |
1630 | S->ISARevision = Flags->isa_rev; |
1631 | S->GPRSize = Flags->gpr_size; |
1632 | S->CPR1Size = Flags->cpr1_size; |
1633 | S->CPR2Size = Flags->cpr2_size; |
1634 | S->FpABI = Flags->fp_abi; |
1635 | S->ISAExtension = Flags->isa_ext; |
1636 | S->ASEs = Flags->ases; |
1637 | S->Flags1 = Flags->flags1; |
1638 | S->Flags2 = Flags->flags2; |
1639 | return S.release(); |
1640 | } |
1641 | |
1642 | template <class ELFT> |
1643 | static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj, |
1644 | std::unique_ptr<DWARFContext> DWARFCtx) { |
1645 | ELFDumper<ELFT> Dumper(Obj, std::move(DWARFCtx)); |
1646 | Expected<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); |
1647 | if (!YAMLOrErr) |
1648 | return YAMLOrErr.takeError(); |
1649 | |
1650 | std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); |
1651 | yaml::Output Yout(Out); |
1652 | Yout << *YAML; |
1653 | |
1654 | return Error::success(); |
1655 | } |
1656 | |
1657 | Error elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { |
1658 | std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); |
1659 | if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(Val: &Obj)) |
1660 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1661 | |
1662 | if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(Val: &Obj)) |
1663 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1664 | |
1665 | if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(Val: &Obj)) |
1666 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1667 | |
1668 | if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(Val: &Obj)) |
1669 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
1670 | |
1671 | llvm_unreachable("unknown ELF file format" ); |
1672 | } |
1673 | |