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; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
