Index: test/tools/llvm-readobj/broken-group.test =================================================================== --- test/tools/llvm-readobj/broken-group.test +++ test/tools/llvm-readobj/broken-group.test @@ -0,0 +1,41 @@ +broken-group.obj.elf-x86_64 contans 2 COMDAT groups and each one contains +the same section foo. This is a result of bug in linker. +Testcase shows that llvm-readobj reports error in that case. +Linker used: LLD 6.0.0 (trunk 310596) (compatible with GNU linkers) +Code: +.section .foo,"axG",@progbits,bar,comdat +.section .foo,"axG",@progbits,zed,comdat +Invocation: +ld.lld -r test.o -o out.lld + +RUN: llvm-readobj --elf-section-groups -elf-output-style=GNU \ +RUN: %p/Inputs/broken-group.obj.elf-x86_64 | FileCheck %s -check-prefix=GNU +GNU: COMDAT group section [ 2] `.group' [bar] contains 1 sections: +GNU-NEXT: [Index] Name +GNU-NEXT: [ 3] .foo +GNU: COMDAT group section [ 4] `.group' [zed] contains 1 sections: +GNU-NEXT: [Index] Name +GNU-NEXT: Error: section [ 3] in group section [ 4] already in group section [ 2] + +RUN: llvm-readobj --elf-section-groups \ +RUN: %p/Inputs/broken-group.obj.elf-x86_64 | FileCheck %s -check-prefix=LLVM +LLVM: Groups { +LLVM-NEXT: Group { +LLVM-NEXT: Name: .group +LLVM-NEXT: Index: 2 +LLVM-NEXT: Type: COMDAT +LLVM-NEXT: Signature: bar +LLVM-NEXT: Section(s) in group [ +LLVM-NEXT: .foo (3) +LLVM-NEXT: ] +LLVM-NEXT: } +LLVM-NEXT: Group { +LLVM-NEXT: Name: .group +LLVM-NEXT: Index: 4 +LLVM-NEXT: Type: COMDAT +LLVM-NEXT: Signature: zed +LLVM-NEXT: Section(s) in group [ +LLVM-NEXT: Error: .foo (3) already in a group .group (2) +LLVM-NEXT: ] +LLVM-NEXT: } +LLVM-NEXT: } Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -18,6 +18,7 @@ #include "StackMapPrinter.h" #include "llvm-readobj.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallString.h" @@ -2444,6 +2445,7 @@ template void GNUStyle::printGroupSections(const ELFO *Obj) { uint32_t SectionIndex = 0; bool HasGroups = false; + DenseMap SectionToGroup; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type == ELF::SHT_GROUP) { HasGroups = true; @@ -2459,7 +2461,15 @@ << StrTable.data() + Signature->st_name << "] contains " << (Data.size() - 1) << " sections:\n" << " [Index] Name\n"; - for (auto &Ndx : Data.slice(1)) { + for (Elf_Word Ndx : Data.slice(1)) { + auto It = SectionToGroup.insert({Ndx, SectionIndex}); + if (!It.second) { + OS << "Error: section [" << format_decimal(Ndx, 5) + << "] in group section [" << format_decimal(SectionIndex, 5) + << "] already in group section [" + << format_decimal(It.first->second, 5) << "]"; + continue; + } auto Sec = unwrapOrError(Obj->getSection(Ndx)); const StringRef Name = unwrapOrError(Obj->getSectionName(Sec)); OS << " [" << format_decimal(Ndx, 5) << "] " << Name @@ -3491,6 +3501,7 @@ DictScope Lists(W, "Groups"); uint32_t SectionIndex = 0; bool HasGroups = false; + DenseMap> SectionToGroup; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type == ELF::SHT_GROUP) { HasGroups = true; @@ -3501,8 +3512,8 @@ auto Data = unwrapOrError( Obj->template getSectionContentsAsArray(&Sec)); DictScope D(W, "Group"); - StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); - W.printNumber("Name", Name, Sec.sh_name); + StringRef GroupName = unwrapOrError(Obj->getSectionName(&Sec)); + W.printNumber("Name", GroupName, Sec.sh_name); W.printNumber("Index", SectionIndex); W.printHex("Type", getGroupType(Data[0]), Data[0]); W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n"; @@ -3511,8 +3522,18 @@ 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"; + Elf_Word Ndx = Data[Member++]; + const StringRef SecName = unwrapOrError(Obj->getSectionName(Sec)); + auto It = SectionToGroup.insert({Ndx, {GroupName, SectionIndex}}); + if (!It.second) { + StringRef GroupName = It.first->second.first; + uint32_t GroupIndex = It.first->second.second; + W.startLine() << "Error: " << SecName << " (" << Ndx + << ") already in a group " + GroupName + " (" + << GroupIndex << ")\n"; + continue; + } + W.startLine() << SecName << " (" << Ndx << ")\n"; } } }