[llvm] r361943 - [llvm-readelf] - Allow dumping of the .dynamic section even if there is no PT_DYNAMIC header.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed May 29 03:31:47 PDT 2019


Author: grimar
Date: Wed May 29 03:31:46 2019
New Revision: 361943

URL: http://llvm.org/viewvc/llvm-project?rev=361943&view=rev
Log:
[llvm-readelf] - Allow dumping of the .dynamic section even if there is no PT_DYNAMIC header.

It is now possible after D61937 was landed and was discussed
in it's review comments. It is not consistent with GNU, which
does not output .dynamic section content in this case for
no visible reason.

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

Modified:
    llvm/trunk/test/Object/corrupt.test
    llvm/trunk/test/Object/invalid.test
    llvm/trunk/test/tools/llvm-readobj/elf-dynamic-malformed.test
    llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test
    llvm/trunk/test/tools/yaml2obj/dynamic-section-raw-content.yaml
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp

Modified: llvm/trunk/test/Object/corrupt.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/corrupt.test?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/test/Object/corrupt.test (original)
+++ llvm/trunk/test/Object/corrupt.test Wed May 29 03:31:46 2019
@@ -38,11 +38,11 @@ RUN:   FileCheck --check-prefix=PHENTSIZ
 
 PHENTSIZE: invalid e_phentsize
 
-RUN: not llvm-readobj --dynamic-table \
+RUN: llvm-readobj --dynamic-table \
 RUN:   %p/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 2>&1 | \
 RUN:   FileCheck --check-prefix=VIRTADDR %s
 
-VIRTADDR: Virtual address is not in any segment
+VIRTADDR: warning: Unable to parse DT_STRTAB: Virtual address is not in any segment
 
 
 RUN: not llvm-readobj --dyn-relocations \

Modified: llvm/trunk/test/Object/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/invalid.test?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/test/Object/invalid.test (original)
+++ llvm/trunk/test/Object/invalid.test Wed May 29 03:31:46 2019
@@ -40,9 +40,6 @@ SECTION-NEXT:    EntrySize: 32
 RUN: not llvm-readobj --symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-SYM-SIZE %s
 INVALID-SYM-SIZE: invalid sh_entsize
 
-RUN: not llvm-readobj --dyn-symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-DYNSYM-SIZE %s
-INVALID-DYNSYM-SIZE: Invalid entity size
-
 RUN: not llvm-readobj --symbols %p/Inputs/invalid-section-index.elf 2>&1 | FileCheck --check-prefix=INVALID-SECTION-INDEX %s
 INVALID-SECTION-INDEX: invalid section index
 

Modified: llvm/trunk/test/tools/llvm-readobj/elf-dynamic-malformed.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/elf-dynamic-malformed.test?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/elf-dynamic-malformed.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/elf-dynamic-malformed.test Wed May 29 03:31:46 2019
@@ -114,7 +114,8 @@ ProgramHeaders:
 # RUN: not llvm-readobj --dynamic-table %t.bad-strtab 2>&1 | FileCheck %s --check-prefix BAD-STRTAB
 # RUN: not llvm-readelf --dynamic-table %t.bad-strtab 2>&1 | FileCheck %s --check-prefix BAD-STRTAB
 
-# BAD-STRTAB: LLVM ERROR: Virtual address is not in any segment
+# BAD-STRTAB: warning: Unable to parse DT_STRTAB: Virtual address is not in any segment
+# BAD-STRTAB: error: Invalid dynamic string table reference
 
 --- !ELF
 FileHeader:
@@ -147,10 +148,19 @@ ProgramHeaders:
 
 # Test handling of other d_ptr tags pointing outside the file's address space.
 # RUN: yaml2obj %s --docnum=5 -o %t.bad-rela
-# RUN: not llvm-readobj --dynamic-table %t.bad-rela 2>&1 | FileCheck %s --check-prefix BAD-RELA
-# RUN: not llvm-readelf --dynamic-table %t.bad-rela 2>&1 | FileCheck %s --check-prefix BAD-RELA
+# RUN: llvm-readobj --dynamic-table %t.bad-rela 2>&1 | FileCheck %s --check-prefixes=CHECK,BAD-RELA
+# RUN: llvm-readelf --dynamic-table %t.bad-rela 2>&1 | FileCheck %s --check-prefixes=CHECK,BAD-RELA-GNU
 
-# BAD-RELA: LLVM ERROR: Virtual address is not in any segment
+# CHECK: warning: Unable to parse DT_RELA: Virtual address is not in any segment
+# BAD-RELA:      DynamicSection [ (2 entries)
+# BAD-RELA-NEXT:   Tag                Type Name/Value
+# BAD-RELA-NEXT:   0x0000000000000007 RELA 0x1000000
+# BAD-RELA-NEXT:   0x0000000000000000 NULL 0x0
+# BAD-RELA-NEXT: ]
+# BAD-RELA-GNU:      Dynamic section at offset 0x1f0 contains 2 entries:
+# BAD-RELA-GNU-NEXT: Tag                Type   Name/Value
+# BAD-RELA-GNU-NEXT: 0x0000000000000007 (RELA) 0x1000000
+# BAD-RELA-GNU-NEXT: 0x0000000000000000 (NULL) 0x0
 
 --- !ELF
 FileHeader:

Modified: llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test Wed May 29 03:31:46 2019
@@ -1,16 +1,22 @@
-# Show that no dumping occurs if there is no PT_DYNAMIC header.
+## Show that dumping occurs even if there is no PT_DYNAMIC header.
+## This is inconsistent with the GNU behavior, but seems to be more reasonable.
 # RUN: yaml2obj %s -o %t.no-phdr
 # RUN: llvm-readobj --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=LLVM
-# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU --allow-empty
+# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU
 
 # LLVM:      File: {{.*}}.no-phdr
 # LLVM-NEXT: Format: ELF64-x86-64
 # LLVM-NEXT: Arch: x86_64
 # LLVM-NEXT: AddressSize: 64bit
 # LLVM-NEXT: LoadName:{{ *}}
-# LLVM-NOT:  {{.}}
+# LLVM-NEXT: DynamicSection [ (1 entries)
+# LLVM-NEXT:   Tag                Type Name/Value
+# LLVM-NEXT:   0x0000000000000000 NULL 0x0
+# LLVM-NEXT: ]
 
-# GNU-NOT: {{.}}
+# GNU:      Dynamic section at offset 0x1b8 contains 1 entries:
+# GNU-NEXT: Tag                Type   Name/Value
+# GNU-NEXT: 0x0000000000000000 (NULL) 0x0
 
 --- !ELF
 FileHeader:

Modified: llvm/trunk/test/tools/yaml2obj/dynamic-section-raw-content.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/dynamic-section-raw-content.yaml?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/test/tools/yaml2obj/dynamic-section-raw-content.yaml (original)
+++ llvm/trunk/test/tools/yaml2obj/dynamic-section-raw-content.yaml Wed May 29 03:31:46 2019
@@ -10,10 +10,10 @@
 # RAW-NEXT: ]
 # RAW-NEXT: Address:
 # RAW-NEXT: Offset:
-# RAW-NEXT: Size: 5
+# RAW-NEXT: Size: 16
 
 # RAW:      Hex dump of section '.dynamic':
-# RAW-NEXT: 0x00000000 01234567 89 {{.*}}
+# RAW-NEXT: 0x00000000 01234567 89012345 67890000 00000000 {{.*}}
 
 # RUN: not yaml2obj --docnum=2 %s -o %t2 2>&1 | FileCheck %s --check-prefix=ERR
 # ERR: Cannot specify both raw content and explicit entries for dynamic section '.dynamic'.
@@ -27,7 +27,7 @@ FileHeader:
 Sections:
   - Name: .dynamic
     Type: SHT_DYNAMIC
-    Content: "0123456789"
+    Content: "01234567890123456789000000000000"
 
 --- !ELF
 FileHeader:

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=361943&r1=361942&r2=361943&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Wed May 29 03:31:46 2019
@@ -1346,6 +1346,7 @@ static const char *getElfMipsOptionsOdkT
 
 template <typename ELFT>
 void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
+  // Try to locate the PT_DYNAMIC header.
   const Elf_Phdr *DynamicPhdr = nullptr;
   for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) {
     if (Phdr.p_type != ELF::PT_DYNAMIC)
@@ -1354,11 +1355,6 @@ void ELFDumper<ELFT>::loadDynamicTable(c
     break;
   }
 
-  // We do not want to dump dynamic section if we have no PT_DYNAMIC header.
-  // This matches GNU's behavior.
-  if (!DynamicPhdr)
-    return;
-
   // Try to locate the .dynamic section in the sections header table.
   const Elf_Shdr *DynamicSec = nullptr;
   for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) {
@@ -1373,9 +1369,16 @@ void ELFDumper<ELFT>::loadDynamicTable(c
   // Ignore sh_entsize and use the expected value for entry size explicitly.
   // This allows us to dump the dynamic sections with a broken sh_entsize
   // field.
-  if (DynamicSec)
+  if (DynamicSec) {
     DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset,
                              DynamicSec->sh_size, sizeof(Elf_Dyn)});
+    parseDynamicTable();
+  }
+
+  // If we have a PT_DYNAMIC header, we will either check the found dynamic
+  // section or take the dynamic table data directly from the header.
+  if (!DynamicPhdr)
+    return;
 
   if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
       ObjF->getMemoryBufferRef().getBufferSize())
@@ -1389,7 +1392,6 @@ void ELFDumper<ELFT>::loadDynamicTable(c
   }
 
   StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec));
-
   if (DynamicSec->sh_addr + DynamicSec->sh_size >
           DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
       DynamicSec->sh_addr < DynamicPhdr->p_vaddr)
@@ -1401,8 +1403,6 @@ void ELFDumper<ELFT>::loadDynamicTable(c
     reportWarning("The SHT_DYNAMIC section '" + Name +
                   "' is not at the start of "
                   "PT_DYNAMIC segment");
-
-  parseDynamicTable();
 }
 
 template <typename ELFT>
@@ -1460,11 +1460,71 @@ ELFDumper<ELFT>::ELFDumper(const object:
     ELFDumperStyle.reset(new LLVMStyle<ELFT>(Writer, this));
 }
 
+static const char *getTypeString(unsigned Arch, uint64_t Type) {
+#define DYNAMIC_TAG(n, v)
+  switch (Arch) {
+  case EM_HEXAGON:
+    switch (Type) {
+#define HEXAGON_DYNAMIC_TAG(name, value)                                       \
+  case DT_##name:                                                              \
+    return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef HEXAGON_DYNAMIC_TAG
+    }
+    break;
+
+  case EM_MIPS:
+    switch (Type) {
+#define MIPS_DYNAMIC_TAG(name, value)                                          \
+  case DT_##name:                                                              \
+    return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef MIPS_DYNAMIC_TAG
+    }
+    break;
+
+  case EM_PPC64:
+    switch (Type) {
+#define PPC64_DYNAMIC_TAG(name, value)                                         \
+  case DT_##name:                                                              \
+    return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef PPC64_DYNAMIC_TAG
+    }
+    break;
+  }
+#undef DYNAMIC_TAG
+  switch (Type) {
+// Now handle all dynamic tags except the architecture specific ones
+#define MIPS_DYNAMIC_TAG(name, value)
+#define HEXAGON_DYNAMIC_TAG(name, value)
+#define PPC64_DYNAMIC_TAG(name, value)
+// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
+#define DYNAMIC_TAG_MARKER(name, value)
+#define DYNAMIC_TAG(name, value)                                               \
+  case DT_##name:                                                              \
+    return #name;
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef DYNAMIC_TAG
+#undef MIPS_DYNAMIC_TAG
+#undef HEXAGON_DYNAMIC_TAG
+#undef PPC64_DYNAMIC_TAG
+#undef DYNAMIC_TAG_MARKER
+  default:
+    return "unknown";
+  }
+}
+
 template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
-  auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
+  auto toMappedAddr = [&](uint64_t Tag, uint64_t VAddr) -> const uint8_t * {
     auto MappedAddrOrError = ObjF->getELFFile()->toMappedAddr(VAddr);
-    if (!MappedAddrOrError)
-      report_fatal_error(MappedAddrOrError.takeError());
+    if (!MappedAddrOrError) {
+      reportWarning("Unable to parse DT_" +
+                    Twine(getTypeString(
+                        ObjF->getELFFile()->getHeader()->e_machine, Tag)) +
+                    ": " + llvm::toString(MappedAddrOrError.takeError()));
+      return nullptr;
+    }
     return MappedAddrOrError.get();
   };
 
@@ -1474,26 +1534,26 @@ template <typename ELFT> void ELFDumper<
   for (const Elf_Dyn &Dyn : dynamic_table()) {
     switch (Dyn.d_tag) {
     case ELF::DT_HASH:
-      HashTable =
-          reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr()));
+      HashTable = reinterpret_cast<const Elf_Hash *>(
+          toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
       break;
     case ELF::DT_GNU_HASH:
-      GnuHashTable =
-          reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr()));
+      GnuHashTable = reinterpret_cast<const Elf_GnuHash *>(
+          toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
       break;
     case ELF::DT_STRTAB:
-      StringTableBegin =
-          reinterpret_cast<const char *>(toMappedAddr(Dyn.getPtr()));
+      StringTableBegin = reinterpret_cast<const char *>(
+          toMappedAddr(Dyn.getTag(), Dyn.getPtr()));
       break;
     case ELF::DT_STRSZ:
       StringTableSize = Dyn.getVal();
       break;
     case ELF::DT_SYMTAB:
-      DynSymRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       DynSymRegion.EntSize = sizeof(Elf_Sym);
       break;
     case ELF::DT_RELA:
-      DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELASZ:
       DynRelaRegion.Size = Dyn.getVal();
@@ -1505,7 +1565,7 @@ template <typename ELFT> void ELFDumper<
       SONameOffset = Dyn.getVal();
       break;
     case ELF::DT_REL:
-      DynRelRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELSZ:
       DynRelRegion.Size = Dyn.getVal();
@@ -1515,7 +1575,7 @@ template <typename ELFT> void ELFDumper<
       break;
     case ELF::DT_RELR:
     case ELF::DT_ANDROID_RELR:
-      DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELRSZ:
     case ELF::DT_ANDROID_RELRSZ:
@@ -1535,7 +1595,7 @@ template <typename ELFT> void ELFDumper<
                     Twine((uint64_t)Dyn.getVal()));
       break;
     case ELF::DT_JMPREL:
-      DynPLTRelRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynPLTRelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_PLTRELSZ:
       DynPLTRelRegion.Size = Dyn.getVal();
@@ -1627,61 +1687,6 @@ template <class ELFT> void ELFDumper<ELF
   ELFDumperStyle->printELFLinkerOptions(ObjF->getELFFile());
 }
 
-static const char *getTypeString(unsigned Arch, uint64_t Type) {
-#define DYNAMIC_TAG(n, v)
-  switch (Arch) {
-  case EM_HEXAGON:
-    switch (Type) {
-#define HEXAGON_DYNAMIC_TAG(name, value)                                       \
-    case DT_##name:                                                            \
-      return #name;
-#include "llvm/BinaryFormat/DynamicTags.def"
-#undef HEXAGON_DYNAMIC_TAG
-    }
-    break;
-
-  case EM_MIPS:
-    switch (Type) {
-#define MIPS_DYNAMIC_TAG(name, value)                                          \
-    case DT_##name:                                                            \
-      return #name;
-#include "llvm/BinaryFormat/DynamicTags.def"
-#undef MIPS_DYNAMIC_TAG
-    }
-    break;
-
-  case EM_PPC64:
-    switch(Type) {
-#define PPC64_DYNAMIC_TAG(name, value)                                         \
-    case DT_##name:                                                            \
-      return #name;
-#include "llvm/BinaryFormat/DynamicTags.def"
-#undef PPC64_DYNAMIC_TAG
-    }
-    break;
-  }
-#undef DYNAMIC_TAG
-  switch (Type) {
-// Now handle all dynamic tags except the architecture specific ones
-#define MIPS_DYNAMIC_TAG(name, value)
-#define HEXAGON_DYNAMIC_TAG(name, value)
-#define PPC64_DYNAMIC_TAG(name, value)
-// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
-#define DYNAMIC_TAG_MARKER(name, value)
-#define DYNAMIC_TAG(name, value)                                               \
-  case DT_##name:                                                              \
-    return #name;
-#include "llvm/BinaryFormat/DynamicTags.def"
-#undef DYNAMIC_TAG
-#undef MIPS_DYNAMIC_TAG
-#undef HEXAGON_DYNAMIC_TAG
-#undef PPC64_DYNAMIC_TAG
-#undef DYNAMIC_TAG_MARKER
-  default:
-    return "unknown";
-  }
-}
-
 #define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum)                                 \
   { #enum, prefix##_##enum }
 




More information about the llvm-commits mailing list