[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