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,73 @@ +# RUN: yaml2obj %s -o %t.o + +# RUN: llvm-readobj --elf-section-groups -elf-output-style=GNU %t.o \ +# RUN: | 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] `.group1' [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 %t.o \ +# RUN: | 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: .group1 +# 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: } + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .group + Type: SHT_GROUP + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: bar + Members: + - SectionOrType: GRP_COMDAT + - SectionOrType: .foo + - Name: .foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .group1 + Type: SHT_GROUP + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: zed + Members: + - SectionOrType: GRP_COMDAT + - SectionOrType: .foo +Symbols: + Local: + - Name: bar + Section: .group + - Name: zed + Section: .group1 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" @@ -2489,18 +2490,38 @@ } return Ret; } + +DenseMap +mapSectionsToGroups(ArrayRef Groups) { + DenseMap Ret; + for (const GroupSection &G : Groups) + for (const GroupMember &GM : G.Members) + Ret.insert({GM.Index, &G}); + return Ret; +} + } // namespace template void GNUStyle::printGroupSections(const ELFO *Obj) { std::vector V = getGroups(Obj); + DenseMap Map = mapSectionsToGroups(V); for (const GroupSection &G : V) { OS << "\n" << getGroupType(G.Type) << " group section [" << format_decimal(G.Index, 5) << "] `" << G.Name << "' [" << G.Signature << "] contains " << G.Members.size() << " sections:\n" << " [Index] Name\n"; - for (const GroupMember &GM : G.Members) + for (const GroupMember &GM : G.Members) { + const GroupSection *MainGroup = Map[GM.Index]; + if (MainGroup != &G) { + OS << "Error: section [" << format_decimal(GM.Index, 5) + << "] in group section [" << format_decimal(G.Index, 5) + << "] already in group section [" + << format_decimal(MainGroup->Index, 5) << "]"; + continue; + } OS << " [" << format_decimal(GM.Index, 5) << "] " << GM.Name << "\n"; + } } if (V.empty()) @@ -3525,6 +3546,7 @@ void LLVMStyle::printGroupSections(const ELFO *Obj) { DictScope Lists(W, "Groups"); std::vector V = getGroups(Obj); + DenseMap Map = mapSectionsToGroups(V); for (const GroupSection &G : V) { DictScope D(W, "Group"); W.printNumber("Name", G.Name, G.ShName); @@ -3533,8 +3555,16 @@ W.startLine() << "Signature: " << G.Signature << "\n"; ListScope L(W, "Section(s) in group"); - for (const GroupMember &GM : G.Members) + for (const GroupMember &GM : G.Members) { + const GroupSection *MainGroup = Map[GM.Index]; + if (MainGroup != &G) { + W.startLine() << "Error: " << GM.Name << " (" << GM.Index + << ") already in a group " + MainGroup->Name + " (" + << MainGroup->Index << ")\n"; + continue; + } W.startLine() << GM.Name << " (" << GM.Index << ")\n"; + } } if (V.empty())