[llvm] cd2c409 - [llvm-readobj] - Implement --dependent-libraries flag.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 6 03:28:55 PST 2019


Author: Georgii Rymar
Date: 2019-12-06T14:28:29+03:00
New Revision: cd2c409cebb4f838549fba0b71093b0e15d52bca

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

LOG: [llvm-readobj] - Implement --dependent-libraries flag.

There is no way to dump SHT_LLVM_DEPENDENT_LIBRARIES sections
currently. This patch implements this.

The section is described here:
https://llvm.org/docs/Extensions.html#sht-llvm-dependent-libraries-section-dependent-libraries

Differential revision: https://reviews.llvm.org/D70665

Added: 
    llvm/test/tools/llvm-readobj/elf-dependent-libraries.test

Modified: 
    llvm/docs/CommandGuide/llvm-readobj.rst
    llvm/tools/llvm-readobj/ELFDumper.cpp
    llvm/tools/llvm-readobj/ObjDumper.h
    llvm/tools/llvm-readobj/llvm-readobj.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index ea1b22d6d9f5..46a4b87d3fbd 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -152,6 +152,10 @@ The following options are implemented only for the ELF file format.
 
  Display demangled symbol names in the output.
 
+.. option:: --dependent-libraries
+
+ Display the dependent libraries section.
+
 .. option:: --dyn-relocations
 
  Display the dynamic relocation entries.

diff  --git a/llvm/test/tools/llvm-readobj/elf-dependent-libraries.test b/llvm/test/tools/llvm-readobj/elf-dependent-libraries.test
new file mode 100644
index 000000000000..feb56a52daed
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/elf-dependent-libraries.test
@@ -0,0 +1,74 @@
+## Check that we can use the --dependent-libraries option
+## to dump SHT_LLVM_DEPENDENT_LIBRARIES sections.
+
+## Check how we dump a file that has a single valid SHT_LLVM_DEPENDENT_LIBRARIES
+## section with multiple entries.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj --dependent-libraries %t1 2>&1 | FileCheck %s -DFILE=%t
+
+# CHECK:      DependentLibs [
+# CHECK-NEXT:   foo
+# CHECK-NEXT:   bar
+# CHECK-NEXT:   foo
+# CHECK-NEXT: ]
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:      .deplibs
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Libraries: [ foo, bar, foo ]
+
+## 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
+
+# MIX:       DependentLibs [
+# MIX-EMPTY:
+# MIX-NEXT:   warning: '[[FILE]]': SHT_LLVM_DEPENDENT_LIBRARIES section at index 1 is broken: the content is not null-terminated
+# MIX-NEXT:   abc
+# MIX-EMPTY:
+# 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:  ]
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+## Case 1: test we report a warning for a non-null-terminated section.
+  - Name:      .deplibs.nonul
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Content:   "666f6f" ## 'f', 'o', 'o'
+## Case 2: test we can dump an entry from a valid section that has a single entry.
+  - Name:      .deplibs.single
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Libraries: [ abc ]
+## Case 3: test we do not display warnings for an empty section.
+  - Name:      .deplibs.empty
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Content:   ""
+## Case 4: test we report a warning when the section offset is invalid.
+  - Name:      .deplibs.broken.shoffset
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Libraries: [ yyy ]
+    ShOffset:  0xffff0000
+## Case 5: test we can dump all entries from a valid section that has more than one entry.
+  - Name:      .deplibs.multiple
+    Type:      SHT_LLVM_DEPENDENT_LIBRARIES
+    Libraries: [ bar, xxx ]
+
+## llvm-readelf doesn't support --dependent-libraries yet.
+# RUN: llvm-readelf --dependent-libraries %t1 2>&1 | FileCheck %s --check-prefix=READELF
+
+# READELF: printDependentLibs not implemented!

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index b95fbcb90469..69b954063865 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -193,6 +193,7 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
   void printFileHeaders() override;
   void printSectionHeaders() override;
   void printRelocations() override;
+  void printDependentLibs() override;
   void printDynamicRelocations() override;
   void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
   void printHashSymbols() override;
@@ -617,6 +618,7 @@ template <typename ELFT> class DumpStyle {
   virtual void printSymbols(const ELFFile<ELFT> *Obj, bool PrintSymbols,
                             bool PrintDynamicSymbols) = 0;
   virtual void printHashSymbols(const ELFFile<ELFT> *Obj) {}
+  virtual void printDependentLibs(const ELFFile<ELFT> *Obj) = 0;
   virtual void printDynamic(const ELFFile<ELFT> *Obj) {}
   virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
   virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
@@ -687,6 +689,7 @@ template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> {
   void printSymbols(const ELFO *Obj, bool PrintSymbols,
                     bool PrintDynamicSymbols) override;
   void printHashSymbols(const ELFO *Obj) override;
+  void printDependentLibs(const ELFFile<ELFT> *Obj) override;
   void printDynamic(const ELFFile<ELFT> *Obj) override;
   void printDynamicRelocations(const ELFO *Obj) override;
   void printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Offset,
@@ -807,6 +810,7 @@ template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> {
   void printSectionHeaders(const ELFO *Obj) override;
   void printSymbols(const ELFO *Obj, bool PrintSymbols,
                     bool PrintDynamicSymbols) override;
+  void printDependentLibs(const ELFFile<ELFT> *Obj) override;
   void printDynamic(const ELFFile<ELFT> *Obj) override;
   void printDynamicRelocations(const ELFO *Obj) override;
   void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders,
@@ -2054,6 +2058,10 @@ template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {
                                                 SymbolVersionNeedSection);
 }
 
+template <class ELFT> void ELFDumper<ELFT>::printDependentLibs() {
+  ELFDumperStyle->printDependentLibs(ObjF->getELFFile());
+}
+
 template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocations() {
   ELFDumperStyle->printDynamicRelocations(ObjF->getELFFile());
 }
@@ -4873,6 +4881,11 @@ void GNUStyle<ELFT>::printELFLinkerOptions(const ELFFile<ELFT> *Obj) {
   OS << "printELFLinkerOptions not implemented!\n";
 }
 
+template <class ELFT>
+void GNUStyle<ELFT>::printDependentLibs(const ELFFile<ELFT> *Obj) {
+  OS << "printDependentLibs not implemented!\n";
+}
+
 // Used for printing section names in places where possible errors can be
 // ignored.
 static StringRef getSectionName(const SectionRef &Sec) {
@@ -6143,6 +6156,42 @@ 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;
+    }
+  }
+}
+
 template <class ELFT>
 void LLVMStyle<ELFT>::printStackSizes(const ELFObjectFile<ELFT> *Obj) {
   ListScope L(W, "StackSizes");

diff  --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 2ba441342499..3fc8d3e79ac1 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -53,6 +53,7 @@ class ObjDumper {
   virtual void printUnwindInfo() = 0;
 
   // Only implemented for ELF at this time.
+  virtual void printDependentLibs() {}
   virtual void printDynamicRelocations() { }
   virtual void printDynamicTable() { }
   virtual void printNeededLibraries() { }

diff  --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 4db13897879d..89b80cb6e9d8 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -58,6 +58,11 @@ namespace opts {
                    "--section-groups and --elf-hash-histogram."));
   cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All));
 
+  // --dependent-libraries
+  cl::opt<bool>
+      DependentLibraries("dependent-libraries",
+                         cl::desc("Display the dependent libraries section"));
+
   // --headers -e
   cl::opt<bool>
       Headers("headers",
@@ -489,6 +494,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer,
   if (opts::VersionInfo)
     Dumper->printVersionInfo();
   if (Obj->isELF()) {
+    if (opts::DependentLibraries)
+      Dumper->printDependentLibs();
     if (opts::ELFLinkerOptions)
       Dumper->printELFLinkerOptions();
     if (opts::ArchSpecificInfo)


        


More information about the llvm-commits mailing list