[llvm] 2569787 - [DebugInfo] - Fix multiple issues in DWARFDebugFrame::parse().
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Tue May 26 02:13:27 PDT 2020
Author: Georgii Rymar
Date: 2020-05-26T12:13:13+03:00
New Revision: 2569787e44595d31942da2bb5558931351929e57
URL: https://github.com/llvm/llvm-project/commit/2569787e44595d31942da2bb5558931351929e57
DIFF: https://github.com/llvm/llvm-project/commit/2569787e44595d31942da2bb5558931351929e57.diff
LOG: [DebugInfo] - Fix multiple issues in DWARFDebugFrame::parse().
I've noticed an issue with "Data.getRelocatedValue(...)" call.
it might silently ignore an error when a content is truncated.
That leads to an infinite loop in the code (e.g. llvm-readobj hangs).
After fixing the issue I've found that actually we always tried
to read past the end of a section, even when a content was valid.
It happened because the terminator CIE (a CIE with the length == 0)
was never handled. At first I've tried just to stop adding the terminator
entry (and return), but it does not seem to be correct, because tools like
llvm-objdump might want to print something for such entries
(see comments in the code and test cases).
This patch fixes issues mentioned, provides new test cases for
both llvm-readobj and lib/DebugInfo and adds FIXMEs to existent
test cases related.
Differential revision: https://reviews.llvm.org/D80299
Added:
llvm/test/DebugInfo/X86/eh-frame-truncated.s
Modified:
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
llvm/test/tools/llvm-objdump/eh_frame-mipsel.test
llvm/test/tools/llvm-objdump/eh_frame_zero_cie.test
llvm/test/tools/llvm-readobj/ELF/unwind.test
Removed:
################################################################################
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index 269a45e57a8d..0e8d521f9433 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -375,7 +375,19 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
uint64_t Length;
DwarfFormat Format;
std::tie(Length, Format) = Data.getInitialLength(&Offset);
- uint64_t Id;
+ bool IsDWARF64 = Format == DWARF64;
+
+ // If the Length is 0, then this CIE is a terminator. We add it because some
+ // dumper tools might need it to print something special for such entries
+ // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
+ if (Length == 0) {
+ auto Cie = std::make_unique<CIE>(
+ IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
+ SmallString<8>(), 0, 0, None, None, Arch);
+ CIEs[StartOffset] = Cie.get();
+ Entries.push_back(std::move(Cie));
+ break;
+ }
// At this point, Offset points to the next field after Length.
// Length is the structure size excluding itself. Compute an offset one
@@ -385,8 +397,12 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
uint64_t EndStructureOffset = Offset + Length;
// The Id field's size depends on the DWARF format
- bool IsDWARF64 = Format == DWARF64;
- Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset);
+ Error Err = Error::success();
+ uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
+ /*SectionIndex=*/nullptr, &Err);
+ if (Err)
+ return Err;
+
if (Id == getCIEId(IsDWARF64, IsEH)) {
uint8_t Version = Data.getU8(&Offset);
const char *Augmentation = Data.getCStr(&Offset);
diff --git a/llvm/test/DebugInfo/X86/eh-frame-truncated.s b/llvm/test/DebugInfo/X86/eh-frame-truncated.s
new file mode 100644
index 000000000000..28107e13530a
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/eh-frame-truncated.s
@@ -0,0 +1,10 @@
+## Check we report a proper error when the content
+## of the .eh_frame section is truncated.
+
+# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o %t
+# RUN: not llvm-dwarfdump -debug-frame %t 2>&1 | FileCheck %s
+
+# CHECK: error: unexpected end of data at offset 0x4
+
+.section .eh_frame,"a", at unwind
+.long 0xFF ## Length
diff --git a/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test b/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test
index 67d240826914..e89d9aeb53cb 100644
--- a/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test
+++ b/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test
@@ -19,6 +19,7 @@
# CHECK: DW_CFA_offset: reg31 -4
# CHECK: DW_CFA_nop:
+## FIXME: GNU objdump prints "00000038 ZERO terminator" instead.
# CHECK: 00000038 00000000 00000000 CIE
# CHECK: Version: 0
# CHECK: Augmentation: ""
diff --git a/llvm/test/tools/llvm-objdump/eh_frame_zero_cie.test b/llvm/test/tools/llvm-objdump/eh_frame_zero_cie.test
index 4702162a749b..510c944028cd 100644
--- a/llvm/test/tools/llvm-objdump/eh_frame_zero_cie.test
+++ b/llvm/test/tools/llvm-objdump/eh_frame_zero_cie.test
@@ -2,6 +2,7 @@
# CHECK: .eh_frame contents:
+## FIXME: GNU objdump prints "00000000 ZERO terminator" instead.
# CHECK: 00000000 00000000 00000000 CIE
# CHECK: Version: 0
# CHECK: Augmentation: ""
diff --git a/llvm/test/tools/llvm-readobj/ELF/unwind.test b/llvm/test/tools/llvm-readobj/ELF/unwind.test
index dbdc9617aae3..466c6a6a7517 100644
--- a/llvm/test/tools/llvm-readobj/ELF/unwind.test
+++ b/llvm/test/tools/llvm-readobj/ELF/unwind.test
@@ -243,3 +243,22 @@ Sections:
## .quad 0x00010000 # Address range
## .Lend:
Content: 14000000FFFFFFFFCDAB1111000000000000010000000000
+
+## Check we report a error when the .eh_frame section contains truncated data.
+# RUN: yaml2obj --docnum=3 %s -o %t3.exe
+# RUN: not llvm-readobj --unwind %t3.exe 2>&1 | FileCheck %s -DFILE=%t3.exe --check-prefix=TRUNCATED-ERR
+
+# TRUNCATED-ERR: .eh_frame section at offset 0x34 address 0x0:
+# TRUNCATED-ERR-NEXT: error: '[[FILE]]': unexpected end of data at offset 0x4
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_386
+Sections:
+ - Name: .eh_frame
+ Type: SHT_PROGBITS
+## Length is set to 0xFF, though the actual section length is 4.
+ Content: "FF000000"
More information about the llvm-commits
mailing list