Type: SHT_RELA
Link: .symtab
Info: .text.bar
+ - Name: .symtab
+ Type: SHT_SYMTAB
+ Link: [[SYMTABLINK=.strtab]]
Symbols:
- Name: foo
Section: .text.foo
# 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
}
};
+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<GroupMember> Members;
+};
+
namespace {
struct VerdAux {
unsigned Offset;
const ELFDumper<ELFT> &dumper() const { return Dumper; }
protected:
+ std::vector<GroupSection> getGroups();
+
void printDependentLibsHelper(
function_ref<void(const Elf_Shdr &)> OnSectionStart,
function_ref<void(StringRef, uint64_t)> OnSectionEntry);
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<GroupMember> Members;
-};
+template <class ELFT> std::vector<GroupSection> DumpStyle<ELFT>::getGroups() {
+ auto GetSignature = [&](const Elf_Sym &Sym,
+ const Elf_Shdr &Symtab) -> StringRef {
+ Expected<StringRef> StrTableOrErr = Obj.getStringTableForSymtab(Symtab);
+ if (!StrTableOrErr) {
+ reportUniqueWarning(createError("unable to get the string table for " +
+ describe(Obj, Symtab) + ": " +
+ toString(StrTableOrErr.takeError())));
+ return "<?>";
+ }
-template <class ELFT>
-std::vector<GroupSection> getGroups(const ELFFile<ELFT> &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<GroupSection> Ret;
uint64_t I = 0;
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<Elf_Sym>(*Symtab, Sec.sh_info));
auto Data = unwrapOrError(
FileName, Obj.template getSectionContentsAsArray<Elf_Word>(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,
return Ret;
}
-DenseMap<uint64_t, const GroupSection *>
+static DenseMap<uint64_t, const GroupSection *>
mapSectionsToGroups(ArrayRef<GroupSection> Groups) {
DenseMap<uint64_t, const GroupSection *> Ret;
for (const GroupSection &G : Groups)
return Ret;
}
-} // namespace
-
template <class ELFT> void GNUStyle<ELFT>::printGroupSections() {
- std::vector<GroupSection> V = getGroups<ELFT>(this->Obj, this->FileName);
+ std::vector<GroupSection> V = this->getGroups();
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
for (const GroupSection &G : V) {
OS << "\n"
template <class ELFT> void LLVMStyle<ELFT>::printGroupSections() {
DictScope Lists(W, "Groups");
- std::vector<GroupSection> V = getGroups<ELFT>(this->Obj, this->FileName);
+ std::vector<GroupSection> V = this->getGroups();
DenseMap<uint64_t, const GroupSection *> Map = mapSectionsToGroups(V);
for (const GroupSection &G : V) {
DictScope D(W, "Group");