diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -89,8 +89,6 @@ Expected dumpStackSizesSection(const Elf_Shdr *Shdr); - Expected dumpSpecialSection(const Elf_Shdr *Shdr); - public: ELFDumper(const object::ELFFile &O); Expected dump(); @@ -242,19 +240,71 @@ Expected>> ELFDumper::dumpSections() { std::vector> Ret; + auto Add = [&](Expected SecOrErr) -> Error { + if (!SecOrErr) + return SecOrErr.takeError(); + Ret.emplace_back(*SecOrErr); + return Error::success(); + }; + + auto GetDumper = [this](unsigned Type) + -> std::function(const Elf_Shdr *)> { + switch (Type) { + case ELF::SHT_DYNAMIC: + return [this](const Elf_Shdr *S) { return dumpDynamicSection(S); }; + case ELF::SHT_SYMTAB_SHNDX: + return [this](const Elf_Shdr *S) { return dumpSymtabShndxSection(S); }; + case ELF::SHT_REL: + case ELF::SHT_RELA: + return [this](const Elf_Shdr *S) { return dumpRelocSection(S); }; + case ELF::SHT_RELR: + return [this](const Elf_Shdr *S) { return dumpRelrSection(S); }; + case ELF::SHT_GROUP: + return [this](const Elf_Shdr *S) { return dumpGroup(S); }; + case ELF::SHT_MIPS_ABIFLAGS: + return [this](const Elf_Shdr *S) { return dumpMipsABIFlags(S); }; + case ELF::SHT_NOBITS: + return [this](const Elf_Shdr *S) { return dumpNoBitsSection(S); }; + case ELF::SHT_NOTE: + return [this](const Elf_Shdr *S) { return dumpNoteSection(S); }; + case ELF::SHT_HASH: + return [this](const Elf_Shdr *S) { return dumpHashSection(S); }; + case ELF::SHT_GNU_HASH: + return [this](const Elf_Shdr *S) { return dumpGnuHashSection(S); }; + case ELF::SHT_GNU_verdef: + return [this](const Elf_Shdr *S) { return dumpVerdefSection(S); }; + case ELF::SHT_GNU_versym: + return [this](const Elf_Shdr *S) { return dumpSymverSection(S); }; + case ELF::SHT_GNU_verneed: + return [this](const Elf_Shdr *S) { return dumpVerneedSection(S); }; + case ELF::SHT_LLVM_ADDRSIG: + return [this](const Elf_Shdr *S) { return dumpAddrsigSection(S); }; + case ELF::SHT_LLVM_LINKER_OPTIONS: + return [this](const Elf_Shdr *S) { return dumpLinkerOptionsSection(S); }; + case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: + return [this](const Elf_Shdr *S) { + return dumpDependentLibrariesSection(S); + }; + case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + return + [this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(S); }; + default: + return nullptr; + } + }; for (const Elf_Shdr &Sec : Sections) { - switch (Sec.sh_type) { - case ELF::SHT_DYNAMIC: { - Expected SecOrErr = dumpDynamicSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; + // We have dedicated dumping functions for most of the section types. + // Try to use one of them first. + if (std::function(const Elf_Shdr *)> DumpFn = + GetDumper(Sec.sh_type)) { + if (Error E = Add(DumpFn(&Sec))) + return std::move(E); + continue; } - case ELF::SHT_STRTAB: - case ELF::SHT_SYMTAB: - case ELF::SHT_DYNSYM: { + + if (Sec.sh_type == ELF::SHT_STRTAB || Sec.sh_type == ELF::SHT_SYMTAB || + Sec.sh_type == ELF::SHT_DYNSYM) { // The contents of these sections are described by other parts of the YAML // file. We still dump them so that their positions in the section header // table are correctly recorded. We only dump allocatable section because @@ -266,128 +316,13 @@ auto S = std::make_unique(); if (Error E = dumpCommonSection(&Sec, *S.get())) return std::move(E); - Ret.emplace_back(std::move(S)); + if (Error E = Add(S.release())) + return std::move(E); } - break; - } - case ELF::SHT_SYMTAB_SHNDX: { - Expected SecOrErr = - dumpSymtabShndxSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_REL: - case ELF::SHT_RELA: { - Expected SecOrErr = dumpRelocSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_RELR: { - Expected SecOrErr = dumpRelrSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_GROUP: { - Expected GroupOrErr = dumpGroup(&Sec); - if (!GroupOrErr) - return GroupOrErr.takeError(); - Ret.emplace_back(*GroupOrErr); - break; - } - case ELF::SHT_MIPS_ABIFLAGS: { - Expected SecOrErr = dumpMipsABIFlags(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_NOBITS: { - Expected SecOrErr = dumpNoBitsSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_NOTE: { - Expected SecOrErr = dumpNoteSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_HASH: { - Expected SecOrErr = dumpHashSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_GNU_HASH: { - Expected SecOrErr = dumpGnuHashSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_GNU_verdef: { - Expected SecOrErr = dumpVerdefSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_GNU_versym: { - Expected SecOrErr = dumpSymverSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_GNU_verneed: { - Expected SecOrErr = dumpVerneedSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_LLVM_ADDRSIG: { - Expected SecOrErr = dumpAddrsigSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_LLVM_LINKER_OPTIONS: { - Expected SecOrErr = - dumpLinkerOptionsSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: { - Expected SecOrErr = - dumpDependentLibrariesSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; - } - case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: { - Expected SecOrErr = - dumpCallGraphProfileSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - break; + continue; } - case ELF::SHT_NULL: { + + if (Sec.sh_type == ELF::SHT_NULL) { // We only dump the SHT_NULL section at index 0 when it // has at least one non-null field, because yaml2obj // normally creates the zero section at index 0 implicitly. @@ -395,30 +330,27 @@ const uint8_t *Begin = reinterpret_cast(&Sec); const uint8_t *End = Begin + sizeof(Elf_Shdr); if (std::find_if(Begin, End, [](uint8_t V) { return V != 0; }) == End) - break; + continue; } - LLVM_FALLTHROUGH; } - default: { - // Recognize some special SHT_PROGBITS sections by name. - if (Sec.sh_type == ELF::SHT_PROGBITS) { - Expected SpecialSecOrErr = dumpSpecialSection(&Sec); - if (!SpecialSecOrErr) - return SpecialSecOrErr.takeError(); - if (*SpecialSecOrErr) { - Ret.emplace_back(*SpecialSecOrErr); - break; - } - } - Expected SecOrErr = - dumpContentSection(&Sec); - if (!SecOrErr) - return SecOrErr.takeError(); - Ret.emplace_back(*SecOrErr); - } + // Recognize some special SHT_PROGBITS sections by name. + if (Sec.sh_type == ELF::SHT_PROGBITS) { + auto NameOrErr = getUniquedSectionName(&Sec); + if (!NameOrErr) + return NameOrErr.takeError(); + + if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr)) { + if (Error E = Add(dumpStackSizesSection(&Sec))) + return std::move(E); + continue; + } } + + if (Error E = Add(dumpContentSection(&Sec))) + return std::move(E); } + return std::move(Ret); } @@ -575,18 +507,6 @@ } template -Expected -ELFDumper::dumpSpecialSection(const Elf_Shdr *Shdr) { - auto NameOrErr = getUniquedSectionName(Shdr); - if (!NameOrErr) - return NameOrErr.takeError(); - - if (ELFYAML::StackSizesSection::nameMatches(*NameOrErr)) - return dumpStackSizesSection(Shdr); - return nullptr; -} - -template Error ELFDumper::dumpCommonRelocationSection( const Elf_Shdr *Shdr, ELFYAML::RelocationSection &S) { if (Error E = dumpCommonSection(Shdr, S))