diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -375,7 +375,19 @@ 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( + 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 @@ 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 --- /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",@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 --- 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 --- 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 --- a/llvm/test/tools/llvm-readobj/ELF/unwind.test +++ b/llvm/test/tools/llvm-readobj/ELF/unwind.test @@ -243,3 +243,22 @@ ## .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"