Index: test/tools/llvm-readobj/elf-groups.test =================================================================== --- test/tools/llvm-readobj/elf-groups.test +++ test/tools/llvm-readobj/elf-groups.test @@ -15,6 +15,8 @@ RUN: llvm-readobj -g %p/Inputs/elf-groups.x86_64 \ RUN: | FileCheck %s +RUN: llvm-readobj -g -elf-output-style=GNU %p/Inputs/elf-groups.x86_64 \ +RUN: | FileCheck --check-prefix="GNU" %s CHECK: Groups { CHECK-NEXT: Group { CHECK-NEXT: Name: .group (92) @@ -37,3 +39,15 @@ CHECK-NEXT: ] CHECK-NEXT: } +GNU:COMDAT group section [ 1] `.group' [_Z3fooIcEvT_] contains 2 sections: +GNU-NEXT: [Index] Name +GNU-NEXT: [ 10] .text._Z3fooIcEvT_ +GNU-NEXT: [ 11] .rela.text._Z3fooIcEvT_ +GNU:COMDAT group section [ 2] `.group' [_Z3fooIiEvT_] contains 2 sections: +GNU-NEXT: [Index] Name +GNU-NEXT: [ 12] .text._Z3fooIiEvT_ +GNU-NEXT: [ 13] .rela.text._Z3fooIiEvT_ +GNU:COMDAT group section [ 3] `.group' [_ZNKSt9type_info4nameEv] contains 1 sections: +GNU-NEXT: [Index] Name +GNU-NEXT: [ 14] .text._ZNKSt9type_info4nameEv + Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -222,6 +222,7 @@ public: virtual void printFileHeaders(const ELFFile *Obj) = 0; virtual ~DumpStyle() { } + virtual void printGroupSections(const ELFFile *Obj) = 0; }; template class GNUStyle : public DumpStyle { @@ -231,6 +232,7 @@ typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; GNUStyle(StreamWriter &W) : OS(W.getOStream()) {} void printFileHeaders(const ELFFile *Obj) override; + void printGroupSections(const ELFFile *Obj) override; private: template @@ -246,8 +248,8 @@ public: typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; LLVMStyle(StreamWriter &W) : W(W) {} - void printFileHeaders(const ELFFile *Obj) override; + void printGroupSections(const ELFFile *Obj) override; private: StreamWriter &W; @@ -2250,37 +2252,7 @@ } template void ELFDumper::printGroupSections() { - DictScope Lists(W, "Groups"); - uint32_t SectionIndex = 0; - bool HasGroups = false; - for (const Elf_Shdr &Sec : Obj->sections()) { - if (Sec.sh_type == ELF::SHT_GROUP) { - HasGroups = true; - const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); - StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); - const Elf_Sym *Sym = Obj->template getEntry(Symtab, Sec.sh_info); - auto Data = unwrapOrError( - Obj->template getSectionContentsAsArray(&Sec)); - DictScope D(W, "Group"); - StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); - W.printNumber("Name", Name, Sec.sh_name); - W.printNumber("Index", SectionIndex); - W.printHex("Type", getGroupType(Data[0]), Data[0]); - W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n"; - { - ListScope L(W, "Section(s) in group"); - size_t Member = 1; - while (Member < Data.size()) { - auto Sec = unwrapOrError(Obj->getSection(Data[Member])); - const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); - W.startLine() << Name << " (" << Data[Member++] << ")\n"; - } - } - } - ++SectionIndex; - } - if (!HasGroups) - W.startLine() << "There are no group sections in the file.\n"; + ELFDumperStyle->printGroupSections(Obj); } static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, @@ -2345,6 +2317,37 @@ printFields(OS, "Section header string table index:", Str); } +template void GNUStyle::printGroupSections(const ELFO *Obj) { + uint32_t SectionIndex = 0; + bool HasGroups = false; + for (const Elf_Shdr &Sec : Obj->sections()) { + if (Sec.sh_type == ELF::SHT_GROUP) { + HasGroups = true; + const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); + const Elf_Sym *Signature = + Obj->template getEntry(Symtab, Sec.sh_info); + ArrayRef Data = unwrapOrError( + Obj->template getSectionContentsAsArray(&Sec)); + StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); + OS << "\n" << getGroupType(Data[0]) << " group section [" + << format_decimal(SectionIndex, 5) << "] `" << Name << "' [" + << StrTable.data() + Signature->st_name << "] contains " + << (Data.size() - 1) << " sections:\n" + << " [Index] Name\n"; + for (auto &Ndx : Data.slice(1)) { + auto Sec = unwrapOrError(Obj->getSection(Ndx)); + const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); + OS << " [" << format_decimal(Ndx, 5) << "] " << Name + << "\n"; + } + } + ++SectionIndex; + } + if (!HasGroups) + OS << "There are no section groups in this file.\n"; +} + template void LLVMStyle::printFileHeaders(const ELFFile *Obj) { const Elf_Ehdr *e = Obj->getHeader(); @@ -2389,3 +2392,38 @@ W.printNumber("StringTableSectionIndex", e->e_shstrndx); } } + +template +void LLVMStyle::printGroupSections(const ELFO *Obj) { + DictScope Lists(W, "Groups"); + uint32_t SectionIndex = 0; + bool HasGroups = false; + for (const Elf_Shdr &Sec : Obj->sections()) { + if (Sec.sh_type == ELF::SHT_GROUP) { + HasGroups = true; + const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); + const Elf_Sym *Sym = Obj->template getEntry(Symtab, Sec.sh_info); + auto Data = unwrapOrError( + Obj->template getSectionContentsAsArray(&Sec)); + DictScope D(W, "Group"); + StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); + W.printNumber("Name", Name, Sec.sh_name); + W.printNumber("Index", SectionIndex); + W.printHex("Type", getGroupType(Data[0]), Data[0]); + W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n"; + { + ListScope L(W, "Section(s) in group"); + size_t Member = 1; + while (Member < Data.size()) { + auto Sec = unwrapOrError(Obj->getSection(Data[Member])); + const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); + W.startLine() << Name << " (" << Data[Member++] << ")\n"; + } + } + } + ++SectionIndex; + } + if (!HasGroups) + W.startLine() << "There are no group sections in the file.\n"; +}