diff --git a/llvm/test/tools/llvm-readobj/ELF/groups.test b/llvm/test/tools/llvm-readobj/ELF/groups.test --- a/llvm/test/tools/llvm-readobj/ELF/groups.test +++ b/llvm/test/tools/llvm-readobj/ELF/groups.test @@ -74,6 +74,9 @@ Type: SHT_RELA Link: .symtab Info: .text.bar + - Name: .symtab + Type: SHT_SYMTAB + Link: [[SYMTABLINK=.strtab]] Symbols: - Name: foo Section: .text.foo @@ -123,3 +126,49 @@ # DUP-GNU-NEXT: warning: '[[FILE]]': section with index 3, included in the group section with index 1, was also found in the group section with index 2 # DUP-GNU-NEXT: [ 3] .text.foo # DUP-GNU-NEXT: [ 6] .rela.text.bar + +# RUN: yaml2obj %s -DSYMTABLINK=0xFF -o %t.symtab.o +# RUN: llvm-readobj --elf-section-groups %t.symtab.o 2>&1 | \ +# RUN: FileCheck -DFILE=%t.symtab.o %s --check-prefix=SYMTAB-LLVM --implicit-check-not=warning: +# RUN: llvm-readelf --elf-section-groups %t.symtab.o 2>&1 | \ +# RUN: FileCheck -DFILE=%t.symtab.o %s --check-prefix=SYMTAB-GNU --implicit-check-not=warning: + +# SYMTAB-LLVM: Groups { +# SYMTAB-LLVM-NEXT: warning: '[[FILE]]': unable to get the string table for SHT_SYMTAB section with index 7: invalid section index: 255 +# SYMTAB-LLVM-NEXT: Group { +# SYMTAB-LLVM-NEXT: Name: .group (16) +# SYMTAB-LLVM-NEXT: Index: 1 +# SYMTAB-LLVM-NEXT: Link: 7 +# SYMTAB-LLVM-NEXT: Info: 1 +# SYMTAB-LLVM-NEXT: Type: COMDAT (0x1) +# SYMTAB-LLVM-NEXT: Signature: +# SYMTAB-LLVM-NEXT: Section(s) in group [ +# SYMTAB-LLVM-NEXT: .text.foo (3) +# SYMTAB-LLVM-NEXT: .rela.text.foo (4) +# SYMTAB-LLVM-NEXT: ] +# SYMTAB-LLVM-NEXT: } +# SYMTAB-LLVM-NEXT: Group { +# SYMTAB-LLVM-NEXT: Name: .group1 (64) +# SYMTAB-LLVM-NEXT: Index: 2 +# SYMTAB-LLVM-NEXT: Link: 7 +# SYMTAB-LLVM-NEXT: Info: 2 +# SYMTAB-LLVM-NEXT: Type: COMDAT (0x1) +# SYMTAB-LLVM-NEXT: Signature: +# SYMTAB-LLVM-NEXT: Section(s) in group [ +# SYMTAB-LLVM-NEXT: .text.bar (5) +# SYMTAB-LLVM-NEXT: .rela.text.bar (6) +# SYMTAB-LLVM-NEXT: ] +# SYMTAB-LLVM-NEXT: } +# SYMTAB-LLVM-NEXT: } + +# SYMTAB-GNU: warning: '[[FILE]]': unable to get the string table for SHT_SYMTAB section with index 7: invalid section index: 255 +# SYMTAB-GNU-EMPTY: +# SYMTAB-GNU-NEXT: COMDAT group section [ 1] `.group' [] contains 2 sections: +# SYMTAB-GNU-NEXT: [Index] Name +# SYMTAB-GNU-NEXT: [ 3] .text.foo +# SYMTAB-GNU-NEXT: [ 4] .rela.text.foo +# SYMTAB-GNU-EMPTY: +# SYMTAB-GNU-NEXT: COMDAT group section [ 2] `.group1' [] contains 2 sections: +# SYMTAB-GNU-NEXT: [Index] Name +# SYMTAB-GNU-NEXT: [ 5] .text.bar +# SYMTAB-GNU-NEXT: [ 6] .rela.text.bar diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -170,6 +170,22 @@ } }; +struct GroupMember { + StringRef Name; + uint64_t Index; +}; + +struct GroupSection { + StringRef Name; + std::string Signature; + uint64_t ShName; + uint64_t Index; + uint32_t Link; + uint32_t Info; + uint32_t Type; + std::vector Members; +}; + namespace { struct VerdAux { unsigned Offset; @@ -773,6 +789,8 @@ const ELFDumper &dumper() const { return Dumper; } protected: + std::vector getGroups(); + void printDependentLibsHelper( function_ref OnSectionStart, function_ref OnSectionEntry); @@ -3551,29 +3569,21 @@ printFields(OS, "Section header string table index:", Str); } -namespace { -struct GroupMember { - StringRef Name; - uint64_t Index; -}; - -struct GroupSection { - StringRef Name; - std::string Signature; - uint64_t ShName; - uint64_t Index; - uint32_t Link; - uint32_t Info; - uint32_t Type; - std::vector Members; -}; +template std::vector DumpStyle::getGroups() { + auto GetSignature = [&](const Elf_Sym &Sym, + const Elf_Shdr &Symtab) -> StringRef { + Expected StrTableOrErr = Obj.getStringTableForSymtab(Symtab); + if (!StrTableOrErr) { + reportUniqueWarning(createError("unable to get the string table for " + + describe(Obj, Symtab) + ": " + + toString(StrTableOrErr.takeError()))); + return ""; + } -template -std::vector getGroups(const ELFFile &Obj, - StringRef FileName) { - using Elf_Shdr = typename ELFT::Shdr; - using Elf_Sym = typename ELFT::Sym; - using Elf_Word = typename ELFT::Word; + // TODO: this might lead to a crash or produce a wrong result, when the + // st_name goes past the end of the string table. + return StrTableOrErr->data() + Sym.st_name; + }; std::vector Ret; uint64_t I = 0; @@ -3584,15 +3594,14 @@ const Elf_Shdr *Symtab = unwrapOrError(FileName, Obj.getSection(Sec.sh_link)); - StringRef StrTable = - unwrapOrError(FileName, Obj.getStringTableForSymtab(*Symtab)); + const Elf_Sym *Sym = unwrapOrError( FileName, Obj.template getEntry(*Symtab, Sec.sh_info)); auto Data = unwrapOrError( FileName, Obj.template getSectionContentsAsArray(Sec)); StringRef Name = unwrapOrError(FileName, Obj.getSectionName(Sec)); - StringRef Signature = StrTable.data() + Sym->st_name; + StringRef Signature = GetSignature(*Sym, *Symtab); Ret.push_back({Name, maybeDemangle(Signature), Sec.sh_name, @@ -3612,7 +3621,7 @@ return Ret; } -DenseMap +static DenseMap mapSectionsToGroups(ArrayRef Groups) { DenseMap Ret; for (const GroupSection &G : Groups) @@ -3621,10 +3630,8 @@ return Ret; } -} // namespace - template void GNUStyle::printGroupSections() { - std::vector V = getGroups(this->Obj, this->FileName); + std::vector V = this->getGroups(); DenseMap Map = mapSectionsToGroups(V); for (const GroupSection &G : V) { OS << "\n" @@ -6256,7 +6263,7 @@ template void LLVMStyle::printGroupSections() { DictScope Lists(W, "Groups"); - std::vector V = getGroups(this->Obj, this->FileName); + std::vector V = this->getGroups(); DenseMap Map = mapSectionsToGroups(V); for (const GroupSection &G : V) { DictScope D(W, "Group");