[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