[llvm] 343dceb - [llvm-readelf/obj] - Improve error reporting when dumping group sections.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 20 01:41:53 PST 2020
Author: Georgii Rymar
Date: 2020-11-20T12:40:23+03:00
New Revision: 343dceb8315b5c8d7844ec64e6e0931e6ba3655a
URL: https://github.com/llvm/llvm-project/commit/343dceb8315b5c8d7844ec64e6e0931e6ba3655a
DIFF: https://github.com/llvm/llvm-project/commit/343dceb8315b5c8d7844ec64e6e0931e6ba3655a.diff
LOG: [llvm-readelf/obj] - Improve error reporting when dumping group sections.
Our code that dumps groups has 3 noticeable issues:
1) It uses `unwrapOrError` in many places.
2) It doesn't allow reporting unique warnings, because the `getGroups` helper is not
a member of `DumpStyle<ELFT>`.
3) It might just crash. See the comment for `StrTableOrErr->data() + Sym.st_name` line.
In this patch I am starting addressing these points.
For start I've converted one of `unwrapOrError` calls to a unique warning.
Differential revision: https://reviews.llvm.org/D91798
Added:
Modified:
llvm/test/tools/llvm-readobj/ELF/groups.test
llvm/tools/llvm-readobj/ELFDumper.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-readobj/ELF/groups.test b/llvm/test/tools/llvm-readobj/ELF/groups.test
index f4d2b8190a47..a5f4338729d0 100644
--- a/llvm/test/tools/llvm-readobj/ELF/groups.test
+++ b/llvm/test/tools/llvm-readobj/ELF/groups.test
@@ -74,6 +74,9 @@ Sections:
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 @@ Symbols:
# 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
index 6ec494f1d967..0d53ab668f8f 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -170,6 +170,22 @@ struct DynRegionInfo {
}
};
+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;
@@ -773,6 +789,8 @@ template <typename ELFT> class DumpStyle {
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);
@@ -3551,29 +3569,21 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders() {
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;
@@ -3584,15 +3594,14 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> &Obj,
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,
@@ -3612,7 +3621,7 @@ std::vector<GroupSection> getGroups(const ELFFile<ELFT> &Obj,
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)
@@ -3621,10 +3630,8 @@ mapSectionsToGroups(ArrayRef<GroupSection> 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"
@@ -6256,7 +6263,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders() {
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");
More information about the llvm-commits
mailing list