| 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 > 3) |
| 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 | std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets; |
| 938 | if (FeatureOrErr->CallsiteOffsets) { |
| 939 | uint32_t NumCallsites = Data.getULEB128(C&: Cur); |
| 940 | CallsiteOffsets = std::vector<llvm::yaml::Hex64>(NumCallsites, 0); |
| 941 | for (uint32_t CallsiteIndex = 0; Cur && CallsiteIndex < NumCallsites; |
| 942 | ++CallsiteIndex) { |
| 943 | (*CallsiteOffsets)[CallsiteIndex] = Data.getULEB128(C&: Cur); |
| 944 | } |
| 945 | } |
| 946 | uint64_t Size = Data.getULEB128(C&: Cur); |
| 947 | uint64_t Metadata = Data.getULEB128(C&: Cur); |
| 948 | BBEntries.push_back( |
| 949 | x: {.ID: ID, .AddressOffset: Offset, .Size: Size, .Metadata: Metadata, .CallsiteOffsets: std::move(CallsiteOffsets)}); |
| 950 | } |
| 951 | TotalNumBlocks += BBEntries.size(); |
| 952 | BBRanges.push_back(x: {.BaseAddress: BaseAddress, /*NumBlocks=*/{}, .BBEntries: BBEntries}); |
| 953 | } |
| 954 | Entries.push_back( |
| 955 | x: {.Version: Version, .Feature: Feature, /*NumBBRanges=*/{}, .BBRanges: std::move(BBRanges)}); |
| 956 | |
| 957 | ELFYAML::PGOAnalysisMapEntry &PGOAnalysis = PGOAnalyses.emplace_back(); |
| 958 | if (FeatureOrErr->hasPGOAnalysis()) { |
| 959 | HasAnyPGOAnalysisMapEntry = true; |
| 960 | |
| 961 | if (FeatureOrErr->FuncEntryCount) |
| 962 | PGOAnalysis.FuncEntryCount = Data.getULEB128(C&: Cur); |
| 963 | |
| 964 | if (FeatureOrErr->hasPGOAnalysisBBData()) { |
| 965 | auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace(); |
| 966 | for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks; |
| 967 | ++BlockIndex) { |
| 968 | auto &PGOBBEntry = PGOBBEntries.emplace_back(); |
| 969 | if (FeatureOrErr->BBFreq) { |
| 970 | PGOBBEntry.BBFreq = Data.getULEB128(C&: Cur); |
| 971 | if (!Cur) |
| 972 | break; |
| 973 | } |
| 974 | |
| 975 | if (FeatureOrErr->BrProb) { |
| 976 | auto &SuccEntries = PGOBBEntry.Successors.emplace(); |
| 977 | uint64_t SuccCount = Data.getULEB128(C&: Cur); |
| 978 | for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) { |
| 979 | uint32_t ID = Data.getULEB128(C&: Cur); |
| 980 | uint32_t BrProb = Data.getULEB128(C&: Cur); |
| 981 | SuccEntries.push_back(x: {.ID: ID, .BrProb: BrProb}); |
| 982 | } |
| 983 | } |
| 984 | } |
| 985 | } |
| 986 | } |
| 987 | } |
| 988 | |
| 989 | if (!Cur) { |
| 990 | // If the section cannot be decoded, we dump it as an array of bytes. |
| 991 | consumeError(Err: Cur.takeError()); |
| 992 | S->Content = yaml::BinaryRef(Content); |
| 993 | } else { |
| 994 | S->Entries = std::move(Entries); |
| 995 | if (HasAnyPGOAnalysisMapEntry) |
| 996 | S->PGOAnalyses = std::move(PGOAnalyses); |
| 997 | } |
| 998 | |
| 999 | return S.release(); |
| 1000 | } |
| 1001 | |
| 1002 | template <class ELFT> |
| 1003 | Expected<ELFYAML::AddrsigSection *> |
| 1004 | ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) { |
| 1005 | auto S = std::make_unique<ELFYAML::AddrsigSection>(); |
| 1006 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1007 | return std::move(E); |
| 1008 | |
| 1009 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1010 | if (!ContentOrErr) |
| 1011 | return ContentOrErr.takeError(); |
| 1012 | |
| 1013 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1014 | DataExtractor::Cursor Cur(0); |
| 1015 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
| 1016 | std::vector<ELFYAML::YAMLFlowString> Symbols; |
| 1017 | while (Cur && Cur.tell() < Content.size()) { |
| 1018 | uint64_t SymNdx = Data.getULEB128(C&: Cur); |
| 1019 | if (!Cur) |
| 1020 | break; |
| 1021 | |
| 1022 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: SymNdx); |
| 1023 | if (!SymbolName || SymbolName->empty()) { |
| 1024 | consumeError(Err: SymbolName.takeError()); |
| 1025 | Symbols.emplace_back( |
| 1026 | args: StringRef(std::to_string(val: SymNdx)).copy(A&: StringAllocator)); |
| 1027 | continue; |
| 1028 | } |
| 1029 | |
| 1030 | Symbols.emplace_back(args&: *SymbolName); |
| 1031 | } |
| 1032 | |
| 1033 | if (Cur) { |
| 1034 | S->Symbols = std::move(Symbols); |
| 1035 | return S.release(); |
| 1036 | } |
| 1037 | |
| 1038 | consumeError(Err: Cur.takeError()); |
| 1039 | S->Content = yaml::BinaryRef(Content); |
| 1040 | return S.release(); |
| 1041 | } |
| 1042 | |
| 1043 | template <class ELFT> |
| 1044 | Expected<ELFYAML::LinkerOptionsSection *> |
| 1045 | ELFDumper<ELFT>::dumpLinkerOptionsSection(const Elf_Shdr *Shdr) { |
| 1046 | auto S = std::make_unique<ELFYAML::LinkerOptionsSection>(); |
| 1047 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1048 | return std::move(E); |
| 1049 | |
| 1050 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1051 | if (!ContentOrErr) |
| 1052 | return ContentOrErr.takeError(); |
| 1053 | |
| 1054 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1055 | if (Content.empty() || Content.back() != 0) { |
| 1056 | S->Content = Content; |
| 1057 | return S.release(); |
| 1058 | } |
| 1059 | |
| 1060 | SmallVector<StringRef, 16> Strings; |
| 1061 | toStringRef(Input: Content.drop_back()).split(A&: Strings, Separator: '\0'); |
| 1062 | if (Strings.size() % 2 != 0) { |
| 1063 | S->Content = Content; |
| 1064 | return S.release(); |
| 1065 | } |
| 1066 | |
| 1067 | S->Options.emplace(); |
| 1068 | for (size_t I = 0, E = Strings.size(); I != E; I += 2) |
| 1069 | S->Options->push_back(x: {.Key: Strings[I], .Value: Strings[I + 1]}); |
| 1070 | |
| 1071 | return S.release(); |
| 1072 | } |
| 1073 | |
| 1074 | template <class ELFT> |
| 1075 | Expected<ELFYAML::DependentLibrariesSection *> |
| 1076 | ELFDumper<ELFT>::dumpDependentLibrariesSection(const Elf_Shdr *Shdr) { |
| 1077 | auto DL = std::make_unique<ELFYAML::DependentLibrariesSection>(); |
| 1078 | if (Error E = dumpCommonSection(Shdr, S&: *DL)) |
| 1079 | return std::move(E); |
| 1080 | |
| 1081 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1082 | if (!ContentOrErr) |
| 1083 | return ContentOrErr.takeError(); |
| 1084 | |
| 1085 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1086 | if (!Content.empty() && Content.back() != 0) { |
| 1087 | DL->Content = Content; |
| 1088 | return DL.release(); |
| 1089 | } |
| 1090 | |
| 1091 | DL->Libs.emplace(); |
| 1092 | for (const uint8_t *I = Content.begin(), *E = Content.end(); I < E;) { |
| 1093 | StringRef Lib((const char *)I); |
| 1094 | DL->Libs->emplace_back(args&: Lib); |
| 1095 | I += Lib.size() + 1; |
| 1096 | } |
| 1097 | |
| 1098 | return DL.release(); |
| 1099 | } |
| 1100 | |
| 1101 | template <class ELFT> |
| 1102 | Expected<ELFYAML::CallGraphProfileSection *> |
| 1103 | ELFDumper<ELFT>::dumpCallGraphProfileSection(const Elf_Shdr *Shdr) { |
| 1104 | auto S = std::make_unique<ELFYAML::CallGraphProfileSection>(); |
| 1105 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1106 | return std::move(E); |
| 1107 | |
| 1108 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1109 | if (!ContentOrErr) |
| 1110 | return ContentOrErr.takeError(); |
| 1111 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1112 | const uint32_t SizeOfEntry = ELFYAML::getDefaultShEntSize<ELFT>( |
| 1113 | Obj.getHeader().e_machine, S->Type, S->Name); |
| 1114 | // Dump the section by using the Content key when it is truncated. |
| 1115 | // There is no need to create either "Content" or "Entries" fields when the |
| 1116 | // section is empty. |
| 1117 | if (Content.empty() || Content.size() % SizeOfEntry != 0) { |
| 1118 | if (!Content.empty()) |
| 1119 | S->Content = yaml::BinaryRef(Content); |
| 1120 | return S.release(); |
| 1121 | } |
| 1122 | |
| 1123 | std::vector<ELFYAML::CallGraphEntryWeight> Entries(Content.size() / |
| 1124 | SizeOfEntry); |
| 1125 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
| 1126 | DataExtractor::Cursor Cur(0); |
| 1127 | auto ReadEntry = [&](ELFYAML::CallGraphEntryWeight &E) { |
| 1128 | E.Weight = Data.getU64(C&: Cur); |
| 1129 | if (!Cur) { |
| 1130 | consumeError(Err: Cur.takeError()); |
| 1131 | return false; |
| 1132 | } |
| 1133 | return true; |
| 1134 | }; |
| 1135 | |
| 1136 | for (ELFYAML::CallGraphEntryWeight &E : Entries) { |
| 1137 | if (ReadEntry(E)) |
| 1138 | continue; |
| 1139 | S->Content = yaml::BinaryRef(Content); |
| 1140 | return S.release(); |
| 1141 | } |
| 1142 | |
| 1143 | S->Entries = std::move(Entries); |
| 1144 | return S.release(); |
| 1145 | } |
| 1146 | |
| 1147 | template <class ELFT> |
| 1148 | Expected<ELFYAML::DynamicSection *> |
| 1149 | ELFDumper<ELFT>::dumpDynamicSection(const Elf_Shdr *Shdr) { |
| 1150 | auto S = std::make_unique<ELFYAML::DynamicSection>(); |
| 1151 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1152 | return std::move(E); |
| 1153 | |
| 1154 | auto DynTagsOrErr = Obj.template getSectionContentsAsArray<Elf_Dyn>(*Shdr); |
| 1155 | if (!DynTagsOrErr) |
| 1156 | return DynTagsOrErr.takeError(); |
| 1157 | |
| 1158 | S->Entries.emplace(); |
| 1159 | for (const Elf_Dyn &Dyn : *DynTagsOrErr) |
| 1160 | S->Entries->push_back({(ELFYAML::ELF_DYNTAG)Dyn.getTag(), Dyn.getVal()}); |
| 1161 | |
| 1162 | return S.release(); |
| 1163 | } |
| 1164 | |
| 1165 | template <class ELFT> |
| 1166 | Expected<ELFYAML::RelocationSection *> |
| 1167 | ELFDumper<ELFT>::dumpRelocSection(const Elf_Shdr *Shdr) { |
| 1168 | auto S = std::make_unique<ELFYAML::RelocationSection>(); |
| 1169 | if (auto E = dumpCommonRelocationSection(Shdr, S&: *S)) |
| 1170 | return std::move(E); |
| 1171 | |
| 1172 | auto SymTabOrErr = Obj.getSection(Shdr->sh_link); |
| 1173 | if (!SymTabOrErr) |
| 1174 | return SymTabOrErr.takeError(); |
| 1175 | |
| 1176 | if (Shdr->sh_size != 0) |
| 1177 | S->Relocations.emplace(); |
| 1178 | |
| 1179 | std::vector<Elf_Rel> Rels; |
| 1180 | std::vector<Elf_Rela> Relas; |
| 1181 | if (Shdr->sh_type == ELF::SHT_CREL) { |
| 1182 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1183 | if (!ContentOrErr) |
| 1184 | return ContentOrErr.takeError(); |
| 1185 | auto Crel = Obj.decodeCrel(*ContentOrErr); |
| 1186 | if (!Crel) |
| 1187 | return Crel.takeError(); |
| 1188 | Rels = std::move(Crel->first); |
| 1189 | Relas = std::move(Crel->second); |
| 1190 | } else if (Shdr->sh_type == ELF::SHT_REL) { |
| 1191 | auto R = Obj.rels(*Shdr); |
| 1192 | if (!R) |
| 1193 | return R.takeError(); |
| 1194 | Rels = std::move(*R); |
| 1195 | } else { |
| 1196 | auto R = Obj.relas(*Shdr); |
| 1197 | if (!R) |
| 1198 | return R.takeError(); |
| 1199 | Relas = std::move(*R); |
| 1200 | } |
| 1201 | |
| 1202 | for (const Elf_Rel &Rel : Rels) { |
| 1203 | ELFYAML::Relocation R; |
| 1204 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
| 1205 | return std::move(E); |
| 1206 | S->Relocations->push_back(x: R); |
| 1207 | } |
| 1208 | for (const Elf_Rela &Rel : Relas) { |
| 1209 | ELFYAML::Relocation R; |
| 1210 | if (Error E = dumpRelocation(&Rel, *SymTabOrErr, R)) |
| 1211 | return std::move(E); |
| 1212 | R.Addend = Rel.r_addend; |
| 1213 | S->Relocations->push_back(x: R); |
| 1214 | } |
| 1215 | |
| 1216 | return S.release(); |
| 1217 | } |
| 1218 | |
| 1219 | template <class ELFT> |
| 1220 | Expected<ELFYAML::RelrSection *> |
| 1221 | ELFDumper<ELFT>::dumpRelrSection(const Elf_Shdr *Shdr) { |
| 1222 | auto S = std::make_unique<ELFYAML::RelrSection>(); |
| 1223 | if (auto E = dumpCommonSection(Shdr, S&: *S)) |
| 1224 | return std::move(E); |
| 1225 | |
| 1226 | if (Expected<ArrayRef<Elf_Relr>> Relrs = Obj.relrs(*Shdr)) { |
| 1227 | S->Entries.emplace(); |
| 1228 | for (Elf_Relr Rel : *Relrs) |
| 1229 | S->Entries->emplace_back(Rel); |
| 1230 | return S.release(); |
| 1231 | } else { |
| 1232 | // Ignore. We are going to dump the data as raw content below. |
| 1233 | consumeError(Relrs.takeError()); |
| 1234 | } |
| 1235 | |
| 1236 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1237 | if (!ContentOrErr) |
| 1238 | return ContentOrErr.takeError(); |
| 1239 | S->Content = *ContentOrErr; |
| 1240 | return S.release(); |
| 1241 | } |
| 1242 | |
| 1243 | template <class ELFT> |
| 1244 | Expected<ELFYAML::RawContentSection *> |
| 1245 | ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) { |
| 1246 | auto S = std::make_unique<ELFYAML::RawContentSection>(); |
| 1247 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1248 | return std::move(E); |
| 1249 | |
| 1250 | unsigned SecIndex = Shdr - &Sections[0]; |
| 1251 | if (SecIndex != 0 || Shdr->sh_type != ELF::SHT_NULL) { |
| 1252 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1253 | if (!ContentOrErr) |
| 1254 | return ContentOrErr.takeError(); |
| 1255 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1256 | if (!Content.empty()) |
| 1257 | S->Content = yaml::BinaryRef(Content); |
| 1258 | } else { |
| 1259 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
| 1260 | } |
| 1261 | |
| 1262 | if (Shdr->sh_info) |
| 1263 | S->Info = static_cast<llvm::yaml::Hex64>(Shdr->sh_info); |
| 1264 | return S.release(); |
| 1265 | } |
| 1266 | |
| 1267 | template <class ELFT> |
| 1268 | Expected<ELFYAML::SymtabShndxSection *> |
| 1269 | ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) { |
| 1270 | auto S = std::make_unique<ELFYAML::SymtabShndxSection>(); |
| 1271 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1272 | return std::move(E); |
| 1273 | |
| 1274 | auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
| 1275 | if (!EntriesOrErr) |
| 1276 | return EntriesOrErr.takeError(); |
| 1277 | |
| 1278 | S->Entries.emplace(); |
| 1279 | llvm::append_range(*S->Entries, *EntriesOrErr); |
| 1280 | return S.release(); |
| 1281 | } |
| 1282 | |
| 1283 | template <class ELFT> |
| 1284 | Expected<ELFYAML::NoBitsSection *> |
| 1285 | ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) { |
| 1286 | auto S = std::make_unique<ELFYAML::NoBitsSection>(); |
| 1287 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1288 | return std::move(E); |
| 1289 | if (Shdr->sh_size) |
| 1290 | S->Size = static_cast<llvm::yaml::Hex64>(Shdr->sh_size); |
| 1291 | return S.release(); |
| 1292 | } |
| 1293 | |
| 1294 | template <class ELFT> |
| 1295 | Expected<ELFYAML::NoteSection *> |
| 1296 | ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) { |
| 1297 | auto S = std::make_unique<ELFYAML::NoteSection>(); |
| 1298 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1299 | return std::move(E); |
| 1300 | |
| 1301 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1302 | if (!ContentOrErr) |
| 1303 | return ContentOrErr.takeError(); |
| 1304 | |
| 1305 | std::vector<ELFYAML::NoteEntry> Entries; |
| 1306 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1307 | size_t Align = std::max<size_t>(Shdr->sh_addralign, 4); |
| 1308 | while (!Content.empty()) { |
| 1309 | if (Content.size() < sizeof(Elf_Nhdr)) { |
| 1310 | S->Content = yaml::BinaryRef(*ContentOrErr); |
| 1311 | return S.release(); |
| 1312 | } |
| 1313 | |
| 1314 | const Elf_Nhdr * = reinterpret_cast<const Elf_Nhdr *>(Content.data()); |
| 1315 | if (Content.size() < Header->getSize(Align)) { |
| 1316 | S->Content = yaml::BinaryRef(*ContentOrErr); |
| 1317 | return S.release(); |
| 1318 | } |
| 1319 | |
| 1320 | Elf_Note Note(*Header); |
| 1321 | Entries.push_back( |
| 1322 | {Note.getName(), Note.getDesc(Align), (ELFYAML::ELF_NT)Note.getType()}); |
| 1323 | |
| 1324 | Content = Content.drop_front(N: Header->getSize(Align)); |
| 1325 | } |
| 1326 | |
| 1327 | S->Notes = std::move(Entries); |
| 1328 | return S.release(); |
| 1329 | } |
| 1330 | |
| 1331 | template <class ELFT> |
| 1332 | Expected<ELFYAML::HashSection *> |
| 1333 | ELFDumper<ELFT>::dumpHashSection(const Elf_Shdr *Shdr) { |
| 1334 | auto S = std::make_unique<ELFYAML::HashSection>(); |
| 1335 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1336 | return std::move(E); |
| 1337 | |
| 1338 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1339 | if (!ContentOrErr) |
| 1340 | return ContentOrErr.takeError(); |
| 1341 | |
| 1342 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1343 | if (Content.size() % 4 != 0 || Content.size() < 8) { |
| 1344 | S->Content = yaml::BinaryRef(Content); |
| 1345 | return S.release(); |
| 1346 | } |
| 1347 | |
| 1348 | DataExtractor::Cursor Cur(0); |
| 1349 | DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0); |
| 1350 | uint64_t NBucket = Data.getU32(C&: Cur); |
| 1351 | uint64_t NChain = Data.getU32(C&: Cur); |
| 1352 | if (Content.size() != (2 + NBucket + NChain) * 4) { |
| 1353 | S->Content = yaml::BinaryRef(Content); |
| 1354 | if (Cur) |
| 1355 | return S.release(); |
| 1356 | llvm_unreachable("entries were not read correctly" ); |
| 1357 | } |
| 1358 | |
| 1359 | S->Bucket.emplace(args&: NBucket); |
| 1360 | for (uint32_t &V : *S->Bucket) |
| 1361 | V = Data.getU32(C&: Cur); |
| 1362 | |
| 1363 | S->Chain.emplace(args&: NChain); |
| 1364 | for (uint32_t &V : *S->Chain) |
| 1365 | V = Data.getU32(C&: Cur); |
| 1366 | |
| 1367 | if (Cur) |
| 1368 | return S.release(); |
| 1369 | llvm_unreachable("entries were not read correctly" ); |
| 1370 | } |
| 1371 | |
| 1372 | template <class ELFT> |
| 1373 | Expected<ELFYAML::GnuHashSection *> |
| 1374 | ELFDumper<ELFT>::dumpGnuHashSection(const Elf_Shdr *Shdr) { |
| 1375 | auto S = std::make_unique<ELFYAML::GnuHashSection>(); |
| 1376 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1377 | return std::move(E); |
| 1378 | |
| 1379 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1380 | if (!ContentOrErr) |
| 1381 | return ContentOrErr.takeError(); |
| 1382 | |
| 1383 | unsigned AddrSize = ELFT::Is64Bits ? 8 : 4; |
| 1384 | ArrayRef<uint8_t> Content = *ContentOrErr; |
| 1385 | DataExtractor Data(Content, Obj.isLE(), AddrSize); |
| 1386 | |
| 1387 | ELFYAML::GnuHashHeader ; |
| 1388 | DataExtractor::Cursor Cur(0); |
| 1389 | uint64_t NBuckets = Data.getU32(C&: Cur); |
| 1390 | Header.SymNdx = Data.getU32(C&: Cur); |
| 1391 | uint64_t MaskWords = Data.getU32(C&: Cur); |
| 1392 | Header.Shift2 = Data.getU32(C&: Cur); |
| 1393 | |
| 1394 | // Set just the raw binary content if we were unable to read the header |
| 1395 | // or when the section data is truncated or malformed. |
| 1396 | uint64_t Size = Data.getData().size() - Cur.tell(); |
| 1397 | if (!Cur || (Size < MaskWords * AddrSize + NBuckets * 4) || |
| 1398 | (Size % 4 != 0)) { |
| 1399 | consumeError(Err: Cur.takeError()); |
| 1400 | S->Content = yaml::BinaryRef(Content); |
| 1401 | return S.release(); |
| 1402 | } |
| 1403 | |
| 1404 | S->Header = Header; |
| 1405 | |
| 1406 | S->BloomFilter.emplace(args&: MaskWords); |
| 1407 | for (llvm::yaml::Hex64 &Val : *S->BloomFilter) |
| 1408 | Val = Data.getAddress(C&: Cur); |
| 1409 | |
| 1410 | S->HashBuckets.emplace(args&: NBuckets); |
| 1411 | for (llvm::yaml::Hex32 &Val : *S->HashBuckets) |
| 1412 | Val = Data.getU32(C&: Cur); |
| 1413 | |
| 1414 | S->HashValues.emplace(args: (Data.getData().size() - Cur.tell()) / 4); |
| 1415 | for (llvm::yaml::Hex32 &Val : *S->HashValues) |
| 1416 | Val = Data.getU32(C&: Cur); |
| 1417 | |
| 1418 | if (Cur) |
| 1419 | return S.release(); |
| 1420 | llvm_unreachable("GnuHashSection was not read correctly" ); |
| 1421 | } |
| 1422 | |
| 1423 | template <class ELFT> |
| 1424 | Expected<ELFYAML::VerdefSection *> |
| 1425 | ELFDumper<ELFT>::dumpVerdefSection(const Elf_Shdr *Shdr) { |
| 1426 | auto S = std::make_unique<ELFYAML::VerdefSection>(); |
| 1427 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1428 | return std::move(E); |
| 1429 | |
| 1430 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
| 1431 | if (!StringTableShdrOrErr) |
| 1432 | return StringTableShdrOrErr.takeError(); |
| 1433 | |
| 1434 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
| 1435 | if (!StringTableOrErr) |
| 1436 | return StringTableOrErr.takeError(); |
| 1437 | |
| 1438 | auto Contents = Obj.getSectionContents(*Shdr); |
| 1439 | if (!Contents) |
| 1440 | return Contents.takeError(); |
| 1441 | |
| 1442 | S->Entries.emplace(); |
| 1443 | |
| 1444 | llvm::ArrayRef<uint8_t> Data = *Contents; |
| 1445 | const uint8_t *Buf = Data.data(); |
| 1446 | while (Buf) { |
| 1447 | const Elf_Verdef *Verdef = reinterpret_cast<const Elf_Verdef *>(Buf); |
| 1448 | ELFYAML::VerdefEntry Entry; |
| 1449 | if (Verdef->vd_version != 1) |
| 1450 | return createStringError(EC: errc::invalid_argument, |
| 1451 | S: "invalid SHT_GNU_verdef section version: " + |
| 1452 | Twine(Verdef->vd_version)); |
| 1453 | |
| 1454 | if (Verdef->vd_flags != 0) |
| 1455 | Entry.Flags = Verdef->vd_flags; |
| 1456 | |
| 1457 | if (Verdef->vd_ndx != 0) |
| 1458 | Entry.VersionNdx = Verdef->vd_ndx; |
| 1459 | |
| 1460 | if (Verdef->vd_hash != 0) |
| 1461 | Entry.Hash = Verdef->vd_hash; |
| 1462 | |
| 1463 | if (Verdef->vd_aux != sizeof(Elf_Verdef)) |
| 1464 | Entry.VDAux = Verdef->vd_aux; |
| 1465 | |
| 1466 | const uint8_t *BufAux = Buf + Verdef->vd_aux; |
| 1467 | if (BufAux > Data.end()) |
| 1468 | return createStringError( |
| 1469 | EC: errc::invalid_argument, |
| 1470 | S: "corrupted section: vd_aux value " + Twine(Verdef->vd_aux) + |
| 1471 | " in section verdef points past end of the section" ); |
| 1472 | while (BufAux) { |
| 1473 | const Elf_Verdaux *Verdaux = |
| 1474 | reinterpret_cast<const Elf_Verdaux *>(BufAux); |
| 1475 | Entry.VerNames.push_back( |
| 1476 | StringTableOrErr->drop_front(Verdaux->vda_name).data()); |
| 1477 | BufAux = Verdaux->vda_next ? BufAux + Verdaux->vda_next : nullptr; |
| 1478 | } |
| 1479 | |
| 1480 | S->Entries->push_back(x: Entry); |
| 1481 | Buf = Verdef->vd_next ? Buf + Verdef->vd_next : nullptr; |
| 1482 | } |
| 1483 | |
| 1484 | if (Shdr->sh_info != S->Entries->size()) |
| 1485 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
| 1486 | |
| 1487 | return S.release(); |
| 1488 | } |
| 1489 | |
| 1490 | template <class ELFT> |
| 1491 | Expected<ELFYAML::SymverSection *> |
| 1492 | ELFDumper<ELFT>::dumpSymverSection(const Elf_Shdr *Shdr) { |
| 1493 | auto S = std::make_unique<ELFYAML::SymverSection>(); |
| 1494 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1495 | return std::move(E); |
| 1496 | |
| 1497 | auto VersionsOrErr = Obj.template getSectionContentsAsArray<Elf_Half>(*Shdr); |
| 1498 | if (!VersionsOrErr) |
| 1499 | return VersionsOrErr.takeError(); |
| 1500 | |
| 1501 | S->Entries.emplace(); |
| 1502 | llvm::append_range(*S->Entries, *VersionsOrErr); |
| 1503 | |
| 1504 | return S.release(); |
| 1505 | } |
| 1506 | |
| 1507 | template <class ELFT> |
| 1508 | Expected<ELFYAML::VerneedSection *> |
| 1509 | ELFDumper<ELFT>::dumpVerneedSection(const Elf_Shdr *Shdr) { |
| 1510 | auto S = std::make_unique<ELFYAML::VerneedSection>(); |
| 1511 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1512 | return std::move(E); |
| 1513 | |
| 1514 | auto Contents = Obj.getSectionContents(*Shdr); |
| 1515 | if (!Contents) |
| 1516 | return Contents.takeError(); |
| 1517 | |
| 1518 | auto StringTableShdrOrErr = Obj.getSection(Shdr->sh_link); |
| 1519 | if (!StringTableShdrOrErr) |
| 1520 | return StringTableShdrOrErr.takeError(); |
| 1521 | |
| 1522 | auto StringTableOrErr = Obj.getStringTable(**StringTableShdrOrErr); |
| 1523 | if (!StringTableOrErr) |
| 1524 | return StringTableOrErr.takeError(); |
| 1525 | |
| 1526 | S->VerneedV.emplace(); |
| 1527 | |
| 1528 | llvm::ArrayRef<uint8_t> Data = *Contents; |
| 1529 | const uint8_t *Buf = Data.data(); |
| 1530 | while (Buf) { |
| 1531 | const Elf_Verneed *Verneed = reinterpret_cast<const Elf_Verneed *>(Buf); |
| 1532 | |
| 1533 | ELFYAML::VerneedEntry Entry; |
| 1534 | Entry.Version = Verneed->vn_version; |
| 1535 | Entry.File = |
| 1536 | StringRef(StringTableOrErr->drop_front(Verneed->vn_file).data()); |
| 1537 | |
| 1538 | const uint8_t *BufAux = Buf + Verneed->vn_aux; |
| 1539 | while (BufAux) { |
| 1540 | const Elf_Vernaux *Vernaux = |
| 1541 | reinterpret_cast<const Elf_Vernaux *>(BufAux); |
| 1542 | |
| 1543 | ELFYAML::VernauxEntry Aux; |
| 1544 | Aux.Hash = Vernaux->vna_hash; |
| 1545 | Aux.Flags = Vernaux->vna_flags; |
| 1546 | Aux.Other = Vernaux->vna_other; |
| 1547 | Aux.Name = |
| 1548 | StringRef(StringTableOrErr->drop_front(Vernaux->vna_name).data()); |
| 1549 | |
| 1550 | Entry.AuxV.push_back(x: Aux); |
| 1551 | BufAux = Vernaux->vna_next ? BufAux + Vernaux->vna_next : nullptr; |
| 1552 | } |
| 1553 | |
| 1554 | S->VerneedV->push_back(x: Entry); |
| 1555 | Buf = Verneed->vn_next ? Buf + Verneed->vn_next : nullptr; |
| 1556 | } |
| 1557 | |
| 1558 | if (Shdr->sh_info != S->VerneedV->size()) |
| 1559 | S->Info = (llvm::yaml::Hex64)Shdr->sh_info; |
| 1560 | |
| 1561 | return S.release(); |
| 1562 | } |
| 1563 | |
| 1564 | template <class ELFT> |
| 1565 | Expected<StringRef> ELFDumper<ELFT>::getSymbolName(uint32_t SymtabNdx, |
| 1566 | uint32_t SymbolNdx) { |
| 1567 | auto SymtabOrErr = Obj.getSection(SymtabNdx); |
| 1568 | if (!SymtabOrErr) |
| 1569 | return SymtabOrErr.takeError(); |
| 1570 | |
| 1571 | const Elf_Shdr *Symtab = *SymtabOrErr; |
| 1572 | auto SymOrErr = Obj.getSymbol(Symtab, SymbolNdx); |
| 1573 | if (!SymOrErr) |
| 1574 | return SymOrErr.takeError(); |
| 1575 | |
| 1576 | auto StrTabOrErr = Obj.getStringTableForSymtab(*Symtab); |
| 1577 | if (!StrTabOrErr) |
| 1578 | return StrTabOrErr.takeError(); |
| 1579 | return getUniquedSymbolName(Sym: *SymOrErr, StrTable: *StrTabOrErr, SymTab: Symtab); |
| 1580 | } |
| 1581 | |
| 1582 | template <class ELFT> |
| 1583 | Expected<ELFYAML::GroupSection *> |
| 1584 | ELFDumper<ELFT>::dumpGroupSection(const Elf_Shdr *Shdr) { |
| 1585 | auto S = std::make_unique<ELFYAML::GroupSection>(); |
| 1586 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1587 | return std::move(E); |
| 1588 | |
| 1589 | // Get symbol with index sh_info. This symbol's name is the signature of the group. |
| 1590 | Expected<StringRef> SymbolName = getSymbolName(SymtabNdx: Shdr->sh_link, SymbolNdx: Shdr->sh_info); |
| 1591 | if (!SymbolName) |
| 1592 | return SymbolName.takeError(); |
| 1593 | S->Signature = *SymbolName; |
| 1594 | |
| 1595 | auto MembersOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(*Shdr); |
| 1596 | if (!MembersOrErr) |
| 1597 | return MembersOrErr.takeError(); |
| 1598 | |
| 1599 | S->Members.emplace(); |
| 1600 | for (Elf_Word Member : *MembersOrErr) { |
| 1601 | if (Member == llvm::ELF::GRP_COMDAT) { |
| 1602 | S->Members->push_back(x: {.sectionNameOrType: "GRP_COMDAT" }); |
| 1603 | continue; |
| 1604 | } |
| 1605 | |
| 1606 | Expected<const Elf_Shdr *> SHdrOrErr = Obj.getSection(Member); |
| 1607 | if (!SHdrOrErr) |
| 1608 | return SHdrOrErr.takeError(); |
| 1609 | Expected<StringRef> NameOrErr = getUniquedSectionName(Sec: **SHdrOrErr); |
| 1610 | if (!NameOrErr) |
| 1611 | return NameOrErr.takeError(); |
| 1612 | S->Members->push_back(x: {.sectionNameOrType: *NameOrErr}); |
| 1613 | } |
| 1614 | return S.release(); |
| 1615 | } |
| 1616 | |
| 1617 | template <class ELFT> |
| 1618 | Expected<ELFYAML::ARMIndexTableSection *> |
| 1619 | ELFDumper<ELFT>::dumpARMIndexTableSection(const Elf_Shdr *Shdr) { |
| 1620 | auto S = std::make_unique<ELFYAML::ARMIndexTableSection>(); |
| 1621 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1622 | return std::move(E); |
| 1623 | |
| 1624 | Expected<ArrayRef<uint8_t>> ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1625 | if (!ContentOrErr) |
| 1626 | return ContentOrErr.takeError(); |
| 1627 | |
| 1628 | if (ContentOrErr->size() % (sizeof(Elf_Word) * 2) != 0) { |
| 1629 | S->Content = yaml::BinaryRef(*ContentOrErr); |
| 1630 | return S.release(); |
| 1631 | } |
| 1632 | |
| 1633 | ArrayRef<Elf_Word> Words( |
| 1634 | reinterpret_cast<const Elf_Word *>(ContentOrErr->data()), |
| 1635 | ContentOrErr->size() / sizeof(Elf_Word)); |
| 1636 | |
| 1637 | S->Entries.emplace(); |
| 1638 | for (size_t I = 0, E = Words.size(); I != E; I += 2) |
| 1639 | S->Entries->push_back(x: {.Offset: (yaml::Hex32)Words[I], .Value: (yaml::Hex32)Words[I + 1]}); |
| 1640 | |
| 1641 | return S.release(); |
| 1642 | } |
| 1643 | |
| 1644 | template <class ELFT> |
| 1645 | Expected<ELFYAML::MipsABIFlags *> |
| 1646 | ELFDumper<ELFT>::dumpMipsABIFlags(const Elf_Shdr *Shdr) { |
| 1647 | assert(Shdr->sh_type == ELF::SHT_MIPS_ABIFLAGS && |
| 1648 | "Section type is not SHT_MIPS_ABIFLAGS" ); |
| 1649 | auto S = std::make_unique<ELFYAML::MipsABIFlags>(); |
| 1650 | if (Error E = dumpCommonSection(Shdr, S&: *S)) |
| 1651 | return std::move(E); |
| 1652 | |
| 1653 | auto ContentOrErr = Obj.getSectionContents(*Shdr); |
| 1654 | if (!ContentOrErr) |
| 1655 | return ContentOrErr.takeError(); |
| 1656 | |
| 1657 | auto *Flags = reinterpret_cast<const object::Elf_Mips_ABIFlags<ELFT> *>( |
| 1658 | ContentOrErr.get().data()); |
| 1659 | S->Version = Flags->version; |
| 1660 | S->ISALevel = Flags->isa_level; |
| 1661 | S->ISARevision = Flags->isa_rev; |
| 1662 | S->GPRSize = Flags->gpr_size; |
| 1663 | S->CPR1Size = Flags->cpr1_size; |
| 1664 | S->CPR2Size = Flags->cpr2_size; |
| 1665 | S->FpABI = Flags->fp_abi; |
| 1666 | S->ISAExtension = Flags->isa_ext; |
| 1667 | S->ASEs = Flags->ases; |
| 1668 | S->Flags1 = Flags->flags1; |
| 1669 | S->Flags2 = Flags->flags2; |
| 1670 | return S.release(); |
| 1671 | } |
| 1672 | |
| 1673 | template <class ELFT> |
| 1674 | static Error elf2yaml(raw_ostream &Out, const object::ELFFile<ELFT> &Obj, |
| 1675 | std::unique_ptr<DWARFContext> DWARFCtx) { |
| 1676 | ELFDumper<ELFT> Dumper(Obj, std::move(DWARFCtx)); |
| 1677 | Expected<ELFYAML::Object *> YAMLOrErr = Dumper.dump(); |
| 1678 | if (!YAMLOrErr) |
| 1679 | return YAMLOrErr.takeError(); |
| 1680 | |
| 1681 | std::unique_ptr<ELFYAML::Object> YAML(YAMLOrErr.get()); |
| 1682 | yaml::Output Yout(Out); |
| 1683 | Yout << *YAML; |
| 1684 | |
| 1685 | return Error::success(); |
| 1686 | } |
| 1687 | |
| 1688 | Error elf2yaml(raw_ostream &Out, const object::ObjectFile &Obj) { |
| 1689 | std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); |
| 1690 | if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(Val: &Obj)) |
| 1691 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
| 1692 | |
| 1693 | if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(Val: &Obj)) |
| 1694 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
| 1695 | |
| 1696 | if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(Val: &Obj)) |
| 1697 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
| 1698 | |
| 1699 | if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(Val: &Obj)) |
| 1700 | return elf2yaml(Out, Obj: ELFObj->getELFFile(), DWARFCtx: std::move(DWARFCtx)); |
| 1701 | |
| 1702 | llvm_unreachable("unknown ELF file format" ); |
| 1703 | } |
| 1704 | |