[llvm-branch-commits] [llvm] 1007cb7 - [llvm-objdump] --private-headers: change errors to warnings for dynamic section dumping

Tom Stellard via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Apr 5 22:24:13 PDT 2022


Author: Fangrui Song
Date: 2022-04-05T22:23:09-07:00
New Revision: 1007cb795a3c82eab231b58569ea06a2b613636a

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

LOG: [llvm-objdump] --private-headers: change errors to warnings for dynamic section dumping

Fix #54456: `objcopy --only-keep-debug` produces a linked image with invalid
empty dynamic section. llvm-objdump -p currently reports an error which seems
excessive.

```
% llvm-readelf -l a.out
llvm-readelf: warning: 'a.out': no valid dynamic table was found
...
```

Follow the spirit of llvm-readelf -l (D64472) and report a warning instead.
This allows later files to be dumped despite warnings for an input file, and
improves objdump compatibility in that the exit code is now 0 instead of 1.

```
% llvm-objdump -p a.out  # new behavior
...
Program Header:
llvm-objdump: warning: 'a.out': invalid empty dynamic section
% objdump -p a.out
...
Dynamic Section:

```

Reviewed By: jhenderson, raj.khem

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

(cherry picked from commit 11a8fc685692f56b011f851d974f0cac534f2cb8)

Added: 
    llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test

Modified: 
    llvm/lib/Object/ELF.cpp
    llvm/test/tools/llvm-objdump/ELF/invalid-phdr.test
    llvm/test/tools/llvm-objdump/ELF/program-headers.test
    llvm/tools/llvm-objdump/ELFDump.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 6e56da1a31f3e..56a4262117551 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -561,11 +561,9 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const {
   }
 
   if (Dyn.empty())
-    // TODO: this error is untested.
     return createError("invalid empty dynamic section");
 
   if (Dyn.back().d_tag != ELF::DT_NULL)
-    // TODO: this error is untested.
     return createError("dynamic sections must be DT_NULL terminated");
 
   return Dyn;

diff  --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test
new file mode 100644
index 0000000000000..b10e4f5e44f18
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test
@@ -0,0 +1,38 @@
+## An empty dynamic section is invalid. Test we report a warning instead of an
+## error, so that dumping can continue with other objects.
+# RUN: yaml2obj %s --docnum=1 -o %t.empty
+# RUN: llvm-objdump -p %t.empty 2>&1 | FileCheck %s -DFILE=%t.empty --check-prefix=EMPTY
+
+# EMPTY:       Program Header:
+# EMPTY-NEXT:  warning: '[[FILE]]': invalid empty dynamic section
+# EMPTY-EMPTY:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+
+# RUN: yaml2obj %s --docnum=2 -o %t.nonull
+# RUN: llvm-objdump -p %t.nonull 2>&1 | FileCheck %s -DFILE=%t.nonull --check-prefix=NONULL
+
+# NONULL:       Program Header:
+# NONULL-NEXT:  warning: '[[FILE]]': dynamic sections must be DT_NULL terminated
+# NONULL-EMPTY:
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_SONAME
+        Value: 1

diff  --git a/llvm/test/tools/llvm-objdump/ELF/invalid-phdr.test b/llvm/test/tools/llvm-objdump/ELF/invalid-phdr.test
index 94de7eacc3eca..188c8eeeff491 100644
--- a/llvm/test/tools/llvm-objdump/ELF/invalid-phdr.test
+++ b/llvm/test/tools/llvm-objdump/ELF/invalid-phdr.test
@@ -1,11 +1,12 @@
 ## Test how we handle the case when the e_phoff field is invalid.
 # RUN: yaml2obj %s -o %t
-# RUN: not llvm-objdump --private-headers %t 2>&1 | \
+# RUN: llvm-objdump --private-headers %t 2>&1 | \
 # RUN:   FileCheck -DFILE=%t %s --check-prefix=INVALID-PHOFF
 
 # INVALID-PHOFF:      Program Header:
 # INVALID-PHOFF-NEXT: warning: '[[FILE]]': unable to read program headers: program headers are longer than binary of size 280: e_phoff = 0xffffff, e_phnum = 0, e_phentsize = 0
-# INVALID-PHOFF-NEXT: error: '[[FILE]]': program headers are longer than binary of size 280: e_phoff = 0xffffff, e_phnum = 0, e_phentsize = 0
+# INVALID-PHOFF-NEXT: warning: '[[FILE]]': program headers are longer than binary of size 280: e_phoff = 0xffffff, e_phnum = 0, e_phentsize = 0
+# INVALID-PHOFF-EMPTY:
 
 --- !ELF
 FileHeader:

diff  --git a/llvm/test/tools/llvm-objdump/ELF/program-headers.test b/llvm/test/tools/llvm-objdump/ELF/program-headers.test
index 1e11334d7172f..abd4894c45124 100644
--- a/llvm/test/tools/llvm-objdump/ELF/program-headers.test
+++ b/llvm/test/tools/llvm-objdump/ELF/program-headers.test
@@ -278,12 +278,13 @@ ProgramHeaders:
 ## Check we report an error / warning when we are unable to read program headers.
 ## Case A: the e_phentsize field is invalid.
 # RUN: yaml2obj --docnum=2 -DPHENTSIZE=1 %s -o %t.phdr.err
-# RUN: not llvm-objdump --private-headers %t.phdr.err 2>&1 | \
+# RUN: llvm-objdump --private-headers %t.phdr.err 2>&1 | \
 # RUN:   FileCheck %s -DFILE=%t.phdr.err --check-prefix=PHENTSIZE
 
 # PHENTSIZE:      Program Header:
 # PHENTSIZE-NEXT: warning: '[[FILE]]': unable to read program headers: invalid e_phentsize: 1
-# PHENTSIZE-NEXT: error: '[[FILE]]': invalid e_phentsize: 1
+# PHENTSIZE-NEXT: warning: '[[FILE]]': invalid e_phentsize: 1
+# PHENTSIZE-EMPTY:
 
 --- !ELF
 FileHeader:
@@ -309,16 +310,16 @@ ProgramHeaders:
 
 ## Check we report a warning / error when e_phoff goes 1 byte past the end of the file.
 # RUN: yaml2obj --docnum=2 -DPHOFF=0x161 %s -o %t.phdr.err2
-# RUN: not llvm-objdump --private-headers %t.phdr.err2 2>&1 | \
+# RUN: llvm-objdump --private-headers %t.phdr.err2 2>&1 | \
 # RUN:   FileCheck %s -DFILE=%t.phdr.err2 --check-prefix=PHOFF -DOFF=0x161
 
 # PHOFF:      Program Header:
 # PHOFF-NEXT: warning: '[[FILE]]': unable to read program headers: program headers are longer than binary of size 408: e_phoff = [[OFF]], e_phnum = 1, e_phentsize = 56
-# PHOFF-NEXT: error: '[[FILE]]': program headers are longer than binary of size 408: e_phoff = [[OFF]], e_phnum = 1, e_phentsize = 56
-
+# PHOFF-NEXT: warning: '[[FILE]]': program headers are longer than binary of size 408: e_phoff = [[OFF]], e_phnum = 1, e_phentsize = 56
+# PHOFF-EMPTY:
 
 ## Check we report a warning / error when the value of e_phoff is so large that
 ## e_phoff + e_phnum * e_phentsize > UINT64_MAX.
 # RUN: yaml2obj --docnum=2 -DPHOFF=0xffffffffffffffff %s -o %t.phdr.err3
-# RUN: not llvm-objdump --private-headers %t.phdr.err3 2>&1 | \
+# RUN: llvm-objdump --private-headers %t.phdr.err3 2>&1 | \
 # RUN:   FileCheck %s -DFILE=%t.phdr.err3 --check-prefix=PHOFF -DOFF=0xffffffffffffffff

diff  --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index 98e71497d022a..ca73dafe2b8ed 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -171,8 +171,12 @@ uint64_t objdump::getELFSectionLMA(const object::ELFSectionRef &Sec) {
 
 template <class ELFT>
 static void printDynamicSection(const ELFFile<ELFT> &Elf, StringRef Filename) {
-  ArrayRef<typename ELFT::Dyn> DynamicEntries =
-      unwrapOrError(Elf.dynamicEntries(), Filename);
+  auto DynamicEntriesOrErr = Elf.dynamicEntries();
+  if (!DynamicEntriesOrErr) {
+    reportWarning(toString(DynamicEntriesOrErr.takeError()), Filename);
+    return;
+  }
+  ArrayRef<typename ELFT::Dyn> DynamicEntries = *DynamicEntriesOrErr;
 
   // Find the maximum tag name length to format the value column properly.
   size_t MaxLen = 0;


        


More information about the llvm-branch-commits mailing list