[llvm] f06e656 - [llvm-readobj] Implement --dependent-libraries for GNU output

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Fri May 15 07:20:56 PDT 2020


Author: James Henderson
Date: 2020-05-15T15:11:22+01:00
New Revision: f06e6564a1554338ca00a4b9c3acdcffa212c743

URL: https://github.com/llvm/llvm-project/commit/f06e6564a1554338ca00a4b9c3acdcffa212c743
DIFF: https://github.com/llvm/llvm-project/commit/f06e6564a1554338ca00a4b9c3acdcffa212c743.diff

LOG: [llvm-readobj] Implement --dependent-libraries for GNU output

Previously, the option was only implemented for LLVM output. This fixes
https://bugs.llvm.org/show_bug.cgi?id=45695.

At the current time, GNU readelf does not support this option.
Consequently, this patch simply attempts to roughly follow the output
style for similar options like --syms/--notes etc, combined with
--string-dump output.

Reviewed by: MaskRay, grimar

Differential Revision: https://reviews.llvm.org/D79939

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test b/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
index 724f108e63d7..97f8a7578139 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dependent-libraries.test
@@ -5,13 +5,21 @@
 ## section with multiple entries.
 
 # RUN: yaml2obj --docnum=1 %s -o %t1
-# RUN: llvm-readobj --dependent-libraries %t1 2>&1 | FileCheck %s -DFILE=%t
+# RUN: llvm-readobj --dependent-libraries %t1 | \
+# RUN:   FileCheck %s --check-prefix=LLVM --strict-whitespace --match-full-lines
+# RUN: llvm-readelf --dependent-libraries %t1 | \
+# RUN:   FileCheck %s --check-prefix=GNU --strict-whitespace --match-full-lines --implicit-check-not="Dependent libraries"
 
-# CHECK:      DependentLibs [
-# CHECK-NEXT:   foo
-# CHECK-NEXT:   bar
-# CHECK-NEXT:   foo
-# CHECK-NEXT: ]
+#      LLVM:DependentLibs [
+# LLVM-NEXT:  foo
+# LLVM-NEXT:  bar
+# LLVM-NEXT:  foo
+# LLVM-NEXT:]
+
+#      GNU:Dependent libraries section .deplibs at offset 0x40 contains 3 entries:
+# GNU-NEXT:  [     0]  foo
+# GNU-NEXT:  [     4]  bar
+# GNU-NEXT:  [     8]  foo
 
 --- !ELF
 FileHeader:
@@ -27,15 +35,36 @@ Sections:
 ## Now, check how we dump a mix of valid, empty and invalid SHT_LLVM_DEPENDENT_LIBRARIES sections.
 
 # RUN: yaml2obj --docnum=2 %s -o %t2
-# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX -DFILE=%t2
+# RUN: llvm-readobj --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-LLVM -DFILE=%t2
+# RUN: llvm-readelf --dependent-libraries %t2 2>&1 | FileCheck %s --check-prefix=MIX-GNU -DFILE=%t2
+
+# MIX-LLVM:      DependentLibs [
+# MIX-LLVM-NEXT:   warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
+# MIX-LLVM-NEXT:   abc
+# MIX-LLVM-NEXT:   warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x308)
+# MIX-LLVM-NEXT:   bar
+# MIX-LLVM-NEXT:   xxx
+# MIX-LLVM-NEXT:   baz
+# MIX-LLVM-NEXT: ]
 
-# MIX:      DependentLibs [
-# MIX-NEXT:  warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
-# MIX-NEXT:  abc
-# MIX-NEXT:  warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x2c0)
-# MIX-NEXT:  bar
-# MIX-NEXT:  xxx
-# MIX-NEXT: ]
+# MIX-GNU:      warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.nonul at offset 0x40 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.single at offset 0x43 contains 1 entries:
+# MIX-GNU-NEXT:   [     0]  abc
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.empty at offset 0x47 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 4 is broken: section [index 4] has a sh_offset (0xffff0000) + sh_size (0x4) that is greater than the file size (0x308)
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.broken.shoffset at offset 0xffff0000 contains 0 entries:
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: Dependent libraries section .deplibs.multiple at offset 0x4b contains 2 entries:
+# MIX-GNU-NEXT:   [     0]  bar
+# MIX-GNU-NEXT:   [     4]  xxx
+# MIX-GNU-EMPTY:
+# MIX-GNU-NEXT: warning: '[[FILE]]': cannot get section name of SHT_LLVM_DEPENDENT_LIBRARIES section: a section [index 6] has an invalid sh_name (0x10000) offset which goes past the end of the section name string table
+# MIX-GNU-NEXT: Dependent libraries section <?> at offset 0x53 contains 1 entries:
+# MIX-GNU-NEXT:   [     0]  baz
 
 --- !ELF
 FileHeader:
@@ -65,8 +94,22 @@ Sections:
   - Name:      .deplibs.multiple
     Type:      SHT_LLVM_DEPENDENT_LIBRARIES
     Libraries: [ bar, xxx ]
+## Case 6: test we report a warning in GNU mode if the section name can't be read.
+  - ShName:    0x10000
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Libraries: [ baz ]
 
-## llvm-readelf doesn't support --dependent-libraries yet.
-# RUN: llvm-readelf --dependent-libraries %t1 2>&1 | FileCheck %s --check-prefix=READELF
+## Show the output when there are no dependent library sections.
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-readobj --dependent-libraries %t3 2>&1 | FileCheck %s --check-prefix=NONE
+# RUN: llvm-readelf --dependent-libraries %t3 2>&1 | FileCheck %s --allow-empty --implicit-check-not={{.}}
 
-# READELF: printDependentLibs not implemented!
+# NONE:      DependentLibs [
+# NONE-NEXT: ]
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 21ba0f09bb38..a0ac37ac6c31 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -767,6 +767,11 @@ template <typename ELFT> class DumpStyle {
   const ELFDumper<ELFT> *dumper() const { return Dumper; }
 
 protected:
+  void printDependentLibsHelper(
+      const ELFFile<ELFT> *Obj,
+      function_ref<void(const Elf_Shdr &)> OnSectionStart,
+      function_ref<void(StringRef, uint64_t)> OnSectionEntry);
+
   void reportUniqueWarning(Error Err) const;
   StringRef FileName;
 
@@ -5310,9 +5315,88 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
   OS << "printELFLinkerOptions not implemented!\n";
 }
 
+template <class ELFT>
+void DumpStyle<ELFT>::printDependentLibsHelper(
+    const ELFFile<ELFT> *Obj,
+    function_ref<void(const Elf_Shdr &)> OnSectionStart,
+    function_ref<void(StringRef, uint64_t)> OnLibEntry) {
+  auto Warn = [this](unsigned SecNdx, StringRef Msg) {
+    this->reportUniqueWarning(
+        createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
+                    Twine(SecNdx) + " is broken: " + Msg));
+  };
+
+  unsigned I = -1;
+  for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
+    ++I;
+    if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
+      continue;
+
+    OnSectionStart(Shdr);
+
+    Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
+    if (!ContentsOrErr) {
+      Warn(I, toString(ContentsOrErr.takeError()));
+      continue;
+    }
+
+    ArrayRef<uint8_t> Contents = *ContentsOrErr;
+    if (!Contents.empty() && Contents.back() != 0) {
+      Warn(I, "the content is not null-terminated");
+      continue;
+    }
+
+    for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
+      StringRef Lib((const char *)I);
+      OnLibEntry(Lib, I - Contents.begin());
+      I += Lib.size() + 1;
+    }
+  }
+}
+
 template <class ELFT>
 void GNUStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
-  OS << "printDependentLibs not implemented!\n";
+  bool SectionStarted = false;
+  struct NameOffset {
+    StringRef Name;
+    uint64_t Offset;
+  };
+  std::vector<NameOffset> SecEntries;
+  NameOffset Current;
+  auto PrintSection = [&]() {
+    OS << "Dependent libraries section " << Current.Name << " at offset "
+       << format_hex(Current.Offset, 1) << " contains " << SecEntries.size()
+       << " entries:\n";
+    for (NameOffset Entry : SecEntries)
+      OS << "  [" << format("%6tx", Entry.Offset) << "]  " << Entry.Name
+         << "\n";
+    OS << "\n";
+    SecEntries.clear();
+  };
+
+  auto OnSectionStart = [&](const Elf_Shdr &Shdr) {
+    if (SectionStarted)
+      PrintSection();
+    SectionStarted = true;
+    Current.Offset = Shdr.sh_offset;
+    Expected<StringRef> Name = Obj->getSectionName(&Shdr);
+    if (!Name) {
+      Current.Name = "<?>";
+      this->reportUniqueWarning(
+          createError("cannot get section name of "
+                      "SHT_LLVM_DEPENDENT_LIBRARIES section: " +
+                      toString(Name.takeError())));
+    } else {
+      Current.Name = *Name;
+    }
+  };
+  auto OnLibEntry = [&](StringRef Lib, uint64_t Offset) {
+    SecEntries.push_back(NameOffset{Lib, Offset});
+  };
+
+  printDependentLibsHelper(Obj, OnSectionStart, OnLibEntry);
+  if (SectionStarted)
+    PrintSection();
 }
 
 // Used for printing section names in places where possible errors can be
@@ -6582,37 +6666,9 @@ void LLVMStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
 template <class ELFT>
 void LLVMStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
   ListScope L(W, "DependentLibs");
-
-  auto Warn = [this](unsigned SecNdx, StringRef Msg) {
-    this->reportUniqueWarning(
-        createError("SHT_LLVM_DEPENDENT_LIBRARIES section at index " +
-                    Twine(SecNdx) + " is broken: " + Msg));
-  };
-
-  unsigned I = -1;
-  for (const Elf_Shdr &Shdr : unwrapOrError(this->FileName, Obj->sections())) {
-    ++I;
-    if (Shdr.sh_type != ELF::SHT_LLVM_DEPENDENT_LIBRARIES)
-      continue;
-
-    Expected<ArrayRef<uint8_t>> ContentsOrErr = Obj->getSectionContents(&Shdr);
-    if (!ContentsOrErr) {
-      Warn(I, toString(ContentsOrErr.takeError()));
-      continue;
-    }
-
-    ArrayRef<uint8_t> Contents = *ContentsOrErr;
-    if (!Contents.empty() && Contents.back() != 0) {
-      Warn(I, "the content is not null-terminated");
-      continue;
-    }
-
-    for (const uint8_t *I = Contents.begin(), *E = Contents.end(); I < E;) {
-      StringRef Lib((const char *)I);
-      W.printString(Lib);
-      I += Lib.size() + 1;
-    }
-  }
+  printDependentLibsHelper(
+      Obj, [](const Elf_Shdr &) {},
+      [this](StringRef Lib, uint64_t) { W.printString(Lib); });
 }
 
 template <class ELFT>


        


More information about the llvm-commits mailing list