From bd2df13ee0f972ac386fd2d8edf5a9205ace04bb Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Thu, 13 Feb 2020 18:20:14 +0700 Subject: [PATCH] [DebugInfo] Fix printing CIE offsets in EH FDEs. While the value of the CIE pointer field in a DWARF FDE record is an offset to the corresponding CIE record from the beginning of the section, for EH FDE records it is relative to the current offset. Previously, we did not make that distinction when dumped both kinds of FDE records and just printed the same value for the CIE pointer field and the CIE offset; that was acceptable for DWARF FDEs but was wrong for EH FDEs. This patch fixes the issue by explicitly printing the offset of the linked CIE object. Differential Revision: https://reviews.llvm.org/D74613 --- lld/test/ELF/eh-frame-hdr-augmentation.s | 2 +- .../include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 11 +++++++---- llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 12 ++++++++---- llvm/test/DebugInfo/RISCV/eh-frame.s | 2 +- .../DebugInfo/X86/debug_frame-invalid-cie-offset.s | 14 ++++++++++++++ llvm/test/MC/Mips/eh-frame.s | 6 +++--- .../llvm-dwarfdump/X86/debug_frame_GNU_args_size.s | 2 +- .../llvm-dwarfdump/X86/debug_frame_offset.test | 2 +- llvm/test/tools/llvm-objdump/eh_frame-arm64.test | 2 +- llvm/test/tools/llvm-objdump/eh_frame-coff.test | 2 +- llvm/test/tools/llvm-objdump/eh_frame-mipsel.test | 2 +- 11 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 llvm/test/DebugInfo/X86/debug_frame-invalid-cie-offset.s diff --git a/lld/test/ELF/eh-frame-hdr-augmentation.s b/lld/test/ELF/eh-frame-hdr-augmentation.s index 9af5336e40e00..6a9a9e64c8d80 100644 --- a/lld/test/ELF/eh-frame-hdr-augmentation.s +++ b/lld/test/ELF/eh-frame-hdr-augmentation.s @@ -19,7 +19,7 @@ // CHECK-NEXT: DW_CFA_nop: // CHECK-NEXT: DW_CFA_nop: -// CHECK: 00000020 00000014 00000024 FDE cie=00000024 pc=00001014...00001014 +// CHECK: 00000020 00000014 00000024 FDE cie=00000000 pc=00001014...00001014 // CHECK-NEXT: LSDA Address: 000000000000100b // CHECK-NEXT: DW_CFA_nop: // CHECK-NEXT: DW_CFA_nop: diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index adf105285e510..eb20db05e6a92 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -223,14 +223,14 @@ class CIE : public FrameEntry { /// DWARF Frame Description Entry (FDE) class FDE : public FrameEntry { public: - FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, + FDE(uint64_t Offset, uint64_t Length, uint64_t CIEPointer, uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, Optional LSDAAddress, Triple::ArchType Arch) : FrameEntry(FK_FDE, Offset, Length, Cie ? Cie->getCodeAlignmentFactor() : 0, Cie ? Cie->getDataAlignmentFactor() : 0, Arch), - LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), + CIEPointer(CIEPointer), InitialLocation(InitialLocation), AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} ~FDE() override = default; @@ -246,8 +246,11 @@ class FDE : public FrameEntry { static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } private: - /// The following fields are defined in section 6.4.1 of the DWARF standard v3 - const uint64_t LinkedCIEOffset; + /// The following fields are defined in section 6.4.1 of the DWARFv3 standard. + /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative + /// offsets to the linked CIEs. See the following link for more info: + /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html + const uint64_t CIEPointer; const uint64_t InitialLocation; const uint64_t AddressRange; const CIE *LinkedCIE; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index ff3ce456adc32..851646770539a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -313,10 +313,14 @@ void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { } void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { - OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length, - (int32_t)LinkedCIEOffset); - OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset, - (uint32_t)InitialLocation, + OS << format("%08x %08x %08x", (uint32_t)Offset, (uint32_t)Length, + (uint32_t)CIEPointer) + << " FDE cie="; + if (LinkedCIE) + OS << format("%08x", (uint32_t)(LinkedCIE->getOffset())); + else + OS << ""; + OS << format(" pc=%08x...%08x\n", (uint32_t)InitialLocation, (uint32_t)InitialLocation + (uint32_t)AddressRange); if (LSDAAddress) OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); diff --git a/llvm/test/DebugInfo/RISCV/eh-frame.s b/llvm/test/DebugInfo/RISCV/eh-frame.s index f4ea3d55925e4..f518d94c2baf8 100644 --- a/llvm/test/DebugInfo/RISCV/eh-frame.s +++ b/llvm/test/DebugInfo/RISCV/eh-frame.s @@ -28,7 +28,7 @@ func: # CHECK: Augmentation data: 1B # CHECK: DW_CFA_def_cfa: reg2 +0 # -# CHECK: 00000014 00000010 00000018 FDE cie=00000018 pc=00000000...00000004 +# CHECK: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000004 # CHECK: DW_CFA_nop: # CHECK: DW_CFA_nop: # CHECK: DW_CFA_nop: diff --git a/llvm/test/DebugInfo/X86/debug_frame-invalid-cie-offset.s b/llvm/test/DebugInfo/X86/debug_frame-invalid-cie-offset.s new file mode 100644 index 0000000000000..40ce76080b608 --- /dev/null +++ b/llvm/test/DebugInfo/X86/debug_frame-invalid-cie-offset.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc -triple i386-unknown-linux %s -filetype=obj -o - | \ +# RUN: llvm-dwarfdump -debug-frame - | \ +# RUN: FileCheck %s + +# CHECK: .debug_frame contents: +# CHECK: 00000000 0000000c 12345678 FDE cie= pc=00010000...00010010 + + .section .debug_frame,"",@progbits + .long .LFDE0end-.LFDE0id # Length +.LFDE0id: + .long 0x12345678 # CIE pointer (invalid) + .long 0x00010000 # Initial location + .long 0x00000010 # Address range +.LFDE0end: diff --git a/llvm/test/MC/Mips/eh-frame.s b/llvm/test/MC/Mips/eh-frame.s index 470f43956ccd5..1de56b66ddb7e 100644 --- a/llvm/test/MC/Mips/eh-frame.s +++ b/llvm/test/MC/Mips/eh-frame.s @@ -67,7 +67,7 @@ func: // DWARF32-EMPTY: // DWARF32-NEXT: DW_CFA_def_cfa_register: reg29 // -// DWARF32: 00000014 00000010 00000018 FDE cie=00000018 pc=00000000...00000000 +// DWARF32: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000000 // DWARF32-NEXT: DW_CFA_nop: // DWARF32-NEXT: DW_CFA_nop: // DWARF32-NEXT: DW_CFA_nop: @@ -89,8 +89,8 @@ func: // DWARF64-NEXT: DW_CFA_def_cfa_register: reg29 // DWARF64_PIC-NEXT: DW_CFA_nop: // -// DWARF64_ABS: 00000014 00000018 00000018 FDE cie=00000018 pc=00000000...00000000 -// DWARF64_PIC: 00000014 00000010 00000018 FDE cie=00000018 pc=00000000...00000000 +// DWARF64_ABS: 00000014 00000018 00000018 FDE cie=00000000 pc=00000000...00000000 +// DWARF64_PIC: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000000 // DWARF64-NEXT: DW_CFA_nop: // DWARF64-NEXT: DW_CFA_nop: // DWARF64-NEXT: DW_CFA_nop: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_GNU_args_size.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_GNU_args_size.s index b5d7cdee0e09d..0adf5e5d37d10 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_GNU_args_size.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_GNU_args_size.s @@ -2,7 +2,7 @@ # RUN: llvm-dwarfdump -v %t | FileCheck %s # CHECK: .eh_frame contents: -# CHECK: 00000018 00000010 0000001c FDE cie=0000001c pc=00000000...00000000 +# CHECK: 00000018 00000010 0000001c FDE cie=00000000 pc=00000000...00000000 # CHECK-NEXT: DW_CFA_GNU_args_size: +16 # CHECK-NEXT: DW_CFA_nop: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test index a441364e8fca9..5db88164945fb 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test @@ -8,7 +8,7 @@ CHECK-NOT: pc RUN: llvm-dwarfdump %p/../../dsymutil/Inputs/basic1.macho.x86_64.o \ RUN: -eh-frame=0x00000018 | FileCheck %s --check-prefix=EH EH: .eh_frame contents: -EH-NEXT: 00000018 00000024 0000001c FDE cie=0000001c pc=fffffd00...fffffd24 +EH-NEXT: 00000018 00000024 0000001c FDE cie=00000000 pc=fffffd00...fffffd24 EH-NEXT: DW_CFA_advance_loc: 1 EH-NOT: pc EH-NOT: CIE diff --git a/llvm/test/tools/llvm-objdump/eh_frame-arm64.test b/llvm/test/tools/llvm-objdump/eh_frame-arm64.test index 88269c6fd328e..169b908986d63 100644 --- a/llvm/test/tools/llvm-objdump/eh_frame-arm64.test +++ b/llvm/test/tools/llvm-objdump/eh_frame-arm64.test @@ -12,7 +12,7 @@ # CHECK: DW_CFA_def_cfa: reg31 +0 -# CHECK: 00000014 00000020 00000018 FDE cie=00000018 pc=ffffffe4...00000004 +# CHECK: 00000014 00000020 00000018 FDE cie=00000000 pc=ffffffe4...00000004 # CHECK: DW_CFA_advance_loc: 8 # CHECK: DW_CFA_def_cfa_offset: +16 # CHECK: DW_CFA_offset: reg30 -8 diff --git a/llvm/test/tools/llvm-objdump/eh_frame-coff.test b/llvm/test/tools/llvm-objdump/eh_frame-coff.test index 7d4c20eef9adb..ad37ebc119920 100644 --- a/llvm/test/tools/llvm-objdump/eh_frame-coff.test +++ b/llvm/test/tools/llvm-objdump/eh_frame-coff.test @@ -16,7 +16,7 @@ # CHECK: DW_CFA_nop: # CHECK: DW_CFA_nop: -# CHECK: 00000020 0000001c 00000024 FDE cie=00000024 pc=00401410...00401488 +# CHECK: 00000020 0000001c 00000024 FDE cie=00000000 pc=00401410...00401488 # CHECK: LSDA Address: 0000000000406000 # CHECK: DW_CFA_advance_loc: 1 # CHECK: DW_CFA_def_cfa_offset: +8 diff --git a/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test b/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test index 4f1b129c16dd2..76143248ef855 100644 --- a/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test +++ b/llvm/test/tools/llvm-objdump/eh_frame-mipsel.test @@ -12,7 +12,7 @@ # CHECK: DW_CFA_def_cfa: reg29 +0 -# CHECK: 0000001c 00000018 00000020 FDE cie=00000020 pc=00400890...004008dc +# CHECK: 0000001c 00000018 00000020 FDE cie=00000000 pc=00400890...004008dc # CHECK: DW_CFA_advance_loc: 4 # CHECK: DW_CFA_def_cfa_offset: +24 # CHECK: DW_CFA_advance_loc: 4