diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -132,9 +132,9 @@ public: enum FrameKind { FK_CIE, FK_FDE }; - FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, - int64_t DataAlign, Triple::ArchType Arch) - : Kind(K), Offset(Offset), Length(Length), + FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length, + uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch) + : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign, Arch) {} virtual ~FrameEntry() {} @@ -152,6 +152,8 @@ protected: const FrameKind Kind; + const bool IsDWARF64; + /// Offset of this entry in the section. const uint64_t Offset; @@ -166,14 +168,14 @@ public: // CIEs (and FDEs) are simply container classes, so the only sensible way to // create them is by providing the full parsed contents in the constructor. - CIE(uint64_t Offset, uint64_t Length, uint8_t Version, + CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version, SmallString<8> Augmentation, uint8_t AddressSize, uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, uint32_t LSDAPointerEncoding, Optional Personality, Optional PersonalityEnc, Triple::ArchType Arch) - : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, + : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor, DataAlignmentFactor, Arch), Version(Version), Augmentation(std::move(Augmentation)), AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), @@ -223,10 +225,10 @@ /// DWARF Frame Description Entry (FDE) class FDE : public FrameEntry { public: - FDE(uint64_t Offset, uint64_t Length, uint64_t CIEPointer, + FDE(bool IsDWARF64, 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, + : FrameEntry(FK_FDE, IsDWARF64, Offset, Length, Cie ? Cie->getCodeAlignmentFactor() : 0, Cie ? Cie->getDataAlignmentFactor() : 0, Arch), 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 @@ -298,9 +298,11 @@ } void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { - OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length, - IsEH ? 0 : DW_CIE_ID) - << "\n"; + OS << format("%08" PRIx64, Offset) + << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) + << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, + getCIEId(IsDWARF64, IsEH)) + << " CIE\n"; OS << format(" Version: %d\n", Version); OS << " Augmentation: \"" << Augmentation << "\"\n"; if (Version >= 4) { @@ -325,15 +327,16 @@ } void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { - OS << format("%08x %08x %08x", (uint32_t)Offset, (uint32_t)Length, - (uint32_t)CIEPointer) + OS << format("%08" PRIx64, Offset) + << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) + << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) << " FDE cie="; if (LinkedCIE) - OS << format("%08x", (uint32_t)(LinkedCIE->getOffset())); + OS << format("%08" PRIx64, LinkedCIE->getOffset()); else OS << ""; - OS << format(" pc=%08x...%08x\n", (uint32_t)InitialLocation, - (uint32_t)InitialLocation + (uint32_t)AddressRange); + OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation, + InitialLocation + AddressRange); if (LSDAAddress) OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); CFIs.dump(OS, MRI, IsEH); @@ -469,10 +472,11 @@ } auto Cie = std::make_unique( - StartOffset, Length, Version, AugmentationString, AddressSize, - SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, - ReturnAddressRegister, AugmentationData, FDEPointerEncoding, - LSDAPointerEncoding, Personality, PersonalityEncoding, Arch); + IsDWARF64, StartOffset, Length, Version, AugmentationString, + AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, + DataAlignmentFactor, ReturnAddressRegister, AugmentationData, + FDEPointerEncoding, LSDAPointerEncoding, Personality, + PersonalityEncoding, Arch); CIEs[StartOffset] = Cie.get(); Entries.emplace_back(std::move(Cie)); } else { @@ -522,9 +526,9 @@ AddressRange = Data.getRelocatedAddress(&Offset); } - Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, - InitialLocation, AddressRange, - Cie, LSDAAddress, Arch)); + Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer, + InitialLocation, AddressRange, Cie, + LSDAAddress, Arch)); } if (Error E = diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test --- 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 @@ 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=00000000 pc=fffffd00...fffffd24 +EH-NEXT: 00000018 00000024 0000001c FDE cie=00000000 pc=fffffffffffffd00...fffffffffffffd24 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 --- 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=00000000 pc=ffffffe4...00000004 +# CHECK: 00000014 00000020 00000018 FDE cie=00000000 pc=ffffffffffffffe4...00000004 # CHECK: DW_CFA_advance_loc: 8 # CHECK: DW_CFA_def_cfa_offset: +16 # CHECK: DW_CFA_offset: reg30 -8 diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -14,6 +14,7 @@ DWARFAcceleratorTableTest.cpp DWARFDataExtractorTest.cpp DWARFDebugArangeSetTest.cpp + DWARFDebugFrameTest.cpp DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp DWARFDieTest.cpp diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp @@ -0,0 +1,122 @@ +//===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) { + return dwarf::CIE(IsDWARF64, Offset, Length, + /*Version=*/3, + /*Augmentation=*/StringRef(), + /*AddressSize=*/8, + /*SegmentDescriptorSize=*/0, + /*CodeAlignmentFactor=*/1, + /*DataAlignmentFactor=*/-8, + /*ReturnAddressRegister=*/16, + /*AugmentationData=*/StringRef(), + /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr, + /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit, + /*Personality=*/None, + /*PersonalityEnc=*/None, + /*Arch=*/Triple::x86_64); +} + +void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH, + StringRef ExpectedFirstLine) { + std::string Output; + raw_string_ostream OS(Output); + TestCIE.dump(OS, /*MRI=*/nullptr, IsEH); + OS.flush(); + StringRef FirstLine = StringRef(Output).split('\n').first; + EXPECT_EQ(FirstLine, ExpectedFirstLine); +} + +void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH, + StringRef ExpectedFirstLine) { + std::string Output; + raw_string_ostream OS(Output); + TestFDE.dump(OS, /*MRI=*/nullptr, IsEH); + OS.flush(); + StringRef FirstLine = StringRef(Output).split('\n').first; + EXPECT_EQ(FirstLine, ExpectedFirstLine); +} + +TEST(DWARFDebugFrame, DumpDWARF32CIE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, + /*Offset=*/0x1111abcd, + /*Length=*/0x2222abcd); + expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE"); +} + +TEST(DWARFDebugFrame, DumpDWARF64CIE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, + /*Offset=*/0x1111abcdabcd, + /*Length=*/0x2222abcdabcd); + expectDumpResult(TestCIE, /*IsEH=*/false, + "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE"); +} + +TEST(DWARFDebugFrame, DumpEHCIE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, + /*Offset=*/0x1000, + /*Length=*/0x20); + expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE"); +} + +TEST(DWARFDebugFrame, DumpEH64CIE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, + /*Offset=*/0x1000, + /*Length=*/0x20); + expectDumpResult(TestCIE, /*IsEH=*/true, + "00001000 0000000000000020 00000000 CIE"); +} + +TEST(DWARFDebugFrame, DumpDWARF64FDE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, + /*Offset=*/0x1111abcdabcd, + /*Length=*/0x2222abcdabcd); + dwarf::FDE TestFDE(/*IsDWARF64=*/true, + /*Offset=*/0x3333abcdabcd, + /*Length=*/0x4444abcdabcd, + /*CIEPointer=*/0x1111abcdabcd, + /*InitialLocation=*/0x5555abcdabcd, + /*AddressRange=*/0x111111111111, + /*Cie=*/&TestCIE, + /*LSDAAddress=*/None, + /*Arch=*/Triple::x86_64); + expectDumpResult(TestFDE, /*IsEH=*/false, + "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE " + "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde"); +} + +TEST(DWARFDebugFrame, DumpEH64FDE) { + dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, + /*Offset=*/0x1111ab9a000c, + /*Length=*/0x20); + dwarf::FDE TestFDE(/*IsDWARF64=*/true, + /*Offset=*/0x1111abcdabcd, + /*Length=*/0x2222abcdabcd, + /*CIEPointer=*/0x33abcd, + /*InitialLocation=*/0x4444abcdabcd, + /*AddressRange=*/0x111111111111, + /*Cie=*/&TestCIE, + /*LSDAAddress=*/None, + /*Arch=*/Triple::x86_64); + expectDumpResult(TestFDE, /*IsEH=*/true, + "1111abcdabcd 00002222abcdabcd 0033abcd FDE " + "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde"); +} + +} // end anonymous namespace