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