1cada5b88SIgor Kudrin //===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===// 2cada5b88SIgor Kudrin // 3cada5b88SIgor Kudrin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cada5b88SIgor Kudrin // See https://llvm.org/LICENSE.txt for license information. 5cada5b88SIgor Kudrin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cada5b88SIgor Kudrin // 7cada5b88SIgor Kudrin //===----------------------------------------------------------------------===// 8cada5b88SIgor Kudrin 9290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 10bee8cdcaSGeorgii Rymar #include "llvm/ADT/DenseSet.h" 11cada5b88SIgor Kudrin #include "llvm/ADT/SmallVector.h" 12cada5b88SIgor Kudrin #include "llvm/ADT/StringRef.h" 13cada5b88SIgor Kudrin #include "llvm/BinaryFormat/Dwarf.h" 14290e4823Sserge-sans-paille #include "llvm/DebugInfo/DIContext.h" 15290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 161e820e82SGeorgii Rymar #include "llvm/Testing/Support/Error.h" 17cada5b88SIgor Kudrin #include "gtest/gtest.h" 18cada5b88SIgor Kudrin 19cada5b88SIgor Kudrin using namespace llvm; 20cada5b88SIgor Kudrin 21cada5b88SIgor Kudrin namespace { 22cada5b88SIgor Kudrin 23cada5b88SIgor Kudrin dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) { 24cada5b88SIgor Kudrin return dwarf::CIE(IsDWARF64, Offset, Length, 25cada5b88SIgor Kudrin /*Version=*/3, 26cada5b88SIgor Kudrin /*Augmentation=*/StringRef(), 27cada5b88SIgor Kudrin /*AddressSize=*/8, 28cada5b88SIgor Kudrin /*SegmentDescriptorSize=*/0, 29cada5b88SIgor Kudrin /*CodeAlignmentFactor=*/1, 30cada5b88SIgor Kudrin /*DataAlignmentFactor=*/-8, 31cada5b88SIgor Kudrin /*ReturnAddressRegister=*/16, 32cada5b88SIgor Kudrin /*AugmentationData=*/StringRef(), 33cada5b88SIgor Kudrin /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr, 34cada5b88SIgor Kudrin /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit, 35b6a01caaSKazu Hirata /*Personality=*/std::nullopt, 36b6a01caaSKazu Hirata /*PersonalityEnc=*/std::nullopt, 37cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 38cada5b88SIgor Kudrin } 39cada5b88SIgor Kudrin 40cada5b88SIgor Kudrin void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH, 41cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 42cada5b88SIgor Kudrin std::string Output; 43cada5b88SIgor Kudrin raw_string_ostream OS(Output); 44f491b898SShubham Sandeep Rastogi TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); 45cada5b88SIgor Kudrin OS.flush(); 46cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 47cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 48cada5b88SIgor Kudrin } 49cada5b88SIgor Kudrin 50cada5b88SIgor Kudrin void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH, 51cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 52cada5b88SIgor Kudrin std::string Output; 53cada5b88SIgor Kudrin raw_string_ostream OS(Output); 54f491b898SShubham Sandeep Rastogi TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); 55cada5b88SIgor Kudrin OS.flush(); 56cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 57cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 58cada5b88SIgor Kudrin } 59cada5b88SIgor Kudrin 60cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF32CIE) { 61cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 62cada5b88SIgor Kudrin /*Offset=*/0x1111abcd, 63cada5b88SIgor Kudrin /*Length=*/0x2222abcd); 64cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE"); 65cada5b88SIgor Kudrin } 66cada5b88SIgor Kudrin 67cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64CIE) { 68cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 69cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 70cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 71cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, 72cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE"); 73cada5b88SIgor Kudrin } 74cada5b88SIgor Kudrin 75cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEHCIE) { 76cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 77cada5b88SIgor Kudrin /*Offset=*/0x1000, 78cada5b88SIgor Kudrin /*Length=*/0x20); 79cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE"); 80cada5b88SIgor Kudrin } 81cada5b88SIgor Kudrin 82cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64CIE) { 83cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 84cada5b88SIgor Kudrin /*Offset=*/0x1000, 85cada5b88SIgor Kudrin /*Length=*/0x20); 86cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, 87cada5b88SIgor Kudrin "00001000 0000000000000020 00000000 CIE"); 88cada5b88SIgor Kudrin } 89cada5b88SIgor Kudrin 90cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64FDE) { 91cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 92cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 93cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 94cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 95cada5b88SIgor Kudrin /*Offset=*/0x3333abcdabcd, 96cada5b88SIgor Kudrin /*Length=*/0x4444abcdabcd, 97cada5b88SIgor Kudrin /*CIEPointer=*/0x1111abcdabcd, 98cada5b88SIgor Kudrin /*InitialLocation=*/0x5555abcdabcd, 99cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 100cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 101b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 102cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 103cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/false, 104cada5b88SIgor Kudrin "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE " 105cada5b88SIgor Kudrin "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde"); 106cada5b88SIgor Kudrin } 107cada5b88SIgor Kudrin 108cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64FDE) { 109cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 110cada5b88SIgor Kudrin /*Offset=*/0x1111ab9a000c, 111cada5b88SIgor Kudrin /*Length=*/0x20); 112cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 113cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 114cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd, 115cada5b88SIgor Kudrin /*CIEPointer=*/0x33abcd, 116cada5b88SIgor Kudrin /*InitialLocation=*/0x4444abcdabcd, 117cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 118cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 119b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 120cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 121cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/true, 122cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd 0033abcd FDE " 123cada5b88SIgor Kudrin "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde"); 124cada5b88SIgor Kudrin } 125cada5b88SIgor Kudrin 126bee8cdcaSGeorgii Rymar static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions, 127b6a01caaSKazu Hirata Optional<uint64_t> Size = std::nullopt) { 1281e820e82SGeorgii Rymar DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 1291e820e82SGeorgii Rymar /*AddressSize=*/8); 1301e820e82SGeorgii Rymar uint64_t Offset = 0; 1311e820e82SGeorgii Rymar const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size(); 1321e820e82SGeorgii Rymar return C.cfis().parse(Data, &Offset, EndOffset); 133bee8cdcaSGeorgii Rymar } 134bee8cdcaSGeorgii Rymar 135f8122d35SGreg Clayton static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) { 136f8122d35SGreg Clayton DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 137f8122d35SGreg Clayton /*AddressSize=*/8); 138f8122d35SGreg Clayton uint64_t Offset = 0; 139f8122d35SGreg Clayton return FDE.cfis().parse(Data, &Offset, Instructions.size()); 140f8122d35SGreg Clayton } 141f8122d35SGreg Clayton 142bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) { 143bee8cdcaSGeorgii Rymar llvm::DenseSet<uint8_t> ValidExtendedOpcodes = { 144bee8cdcaSGeorgii Rymar dwarf::DW_CFA_nop, 145bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc, 146bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset, 147bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore, 148bee8cdcaSGeorgii Rymar dwarf::DW_CFA_set_loc, 149bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc1, 150bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc2, 151bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc4, 152bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset_extended, 153bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore_extended, 154bee8cdcaSGeorgii Rymar dwarf::DW_CFA_undefined, 155bee8cdcaSGeorgii Rymar dwarf::DW_CFA_same_value, 156bee8cdcaSGeorgii Rymar dwarf::DW_CFA_register, 157bee8cdcaSGeorgii Rymar dwarf::DW_CFA_remember_state, 158bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore_state, 159bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa, 160bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_register, 161bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, 162bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_expression, 163bee8cdcaSGeorgii Rymar dwarf::DW_CFA_expression, 164bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset_extended_sf, 165bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_sf, 166bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_offset_sf, 167167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa, 168167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, 169bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset, 170bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset_sf, 171bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_expression, 172bee8cdcaSGeorgii Rymar dwarf::DW_CFA_MIPS_advance_loc8, 173bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_window_save, 174bee8cdcaSGeorgii Rymar dwarf::DW_CFA_AARCH64_negate_ra_state, 175bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_args_size}; 1761e820e82SGeorgii Rymar 1771e820e82SGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1781e820e82SGeorgii Rymar /*Offset=*/0x0, 1791e820e82SGeorgii Rymar /*Length=*/0xff); 1801e820e82SGeorgii Rymar 181bee8cdcaSGeorgii Rymar // See DWARF standard v3, section 7.23: low 6 bits are used to encode an 182bee8cdcaSGeorgii Rymar // extended opcode. 183bee8cdcaSGeorgii Rymar for (uint8_t Code = 0; Code <= 63; ++Code) { 184bee8cdcaSGeorgii Rymar if (ValidExtendedOpcodes.count(Code)) 185bee8cdcaSGeorgii Rymar continue; 186bee8cdcaSGeorgii Rymar 187bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, Code), 188bee8cdcaSGeorgii Rymar FailedWithMessage(("invalid extended CFI opcode 0x" + 189bee8cdcaSGeorgii Rymar Twine::utohexstr(Code)) 190bee8cdcaSGeorgii Rymar .str() 191bee8cdcaSGeorgii Rymar .c_str())); 192bee8cdcaSGeorgii Rymar } 193bee8cdcaSGeorgii Rymar } 194bee8cdcaSGeorgii Rymar 195bee8cdcaSGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed. 196bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) { 197bee8cdcaSGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 198bee8cdcaSGeorgii Rymar /*Offset=*/0x0, 199bee8cdcaSGeorgii Rymar /*Length=*/0xff); 200bee8cdcaSGeorgii Rymar 2011e820e82SGeorgii Rymar // Having an empty instructions list is fine. 202bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 2031e820e82SGeorgii Rymar 2041e820e82SGeorgii Rymar // Unable to read an opcode, because the instructions list is empty, but we 2051e820e82SGeorgii Rymar // say to the parser that it is not. 2061e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 207bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {}, /*Size=*/1), 2081e820e82SGeorgii Rymar FailedWithMessage( 2091e820e82SGeorgii Rymar "unexpected end of data at offset 0x0 while reading [0x0, 0x1)")); 2101e820e82SGeorgii Rymar 2111e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_offset instruction. 2121e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 213bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_offset}), 2141e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2151e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2161e820e82SGeorgii Rymar 2171e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_set_loc instruction. 2181e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 219bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}), 2201e820e82SGeorgii Rymar FailedWithMessage( 2211e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x9)")); 2221e820e82SGeorgii Rymar 2231e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc1 instruction. 2241e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 225bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}), 2261e820e82SGeorgii Rymar FailedWithMessage( 2271e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x2)")); 2281e820e82SGeorgii Rymar 2291e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc2 instruction. 2301e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 231bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}), 2321e820e82SGeorgii Rymar FailedWithMessage( 2331e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x3)")); 2341e820e82SGeorgii Rymar 2351e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc4 instruction. 2361e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 237bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}), 2381e820e82SGeorgii Rymar FailedWithMessage( 2391e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x5)")); 2401e820e82SGeorgii Rymar 2411e820e82SGeorgii Rymar // A test for an instruction with a single ULEB128 operand. 2421e820e82SGeorgii Rymar auto CheckOp_ULEB128 = [&](uint8_t Inst) { 2431e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 244bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2451e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2461e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2471e820e82SGeorgii Rymar }; 2481e820e82SGeorgii Rymar 2491e820e82SGeorgii Rymar for (uint8_t Inst : 2501e820e82SGeorgii Rymar {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined, 2511e820e82SGeorgii Rymar dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register, 2521e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size}) 2531e820e82SGeorgii Rymar CheckOp_ULEB128(Inst); 2541e820e82SGeorgii Rymar 2551e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction. 2561e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 257bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}), 2581e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2591e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2601e820e82SGeorgii Rymar 2611e820e82SGeorgii Rymar // A test for an instruction with two ULEB128 operands. 2621e820e82SGeorgii Rymar auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) { 2631e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 264bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2651e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2661e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2671e820e82SGeorgii Rymar 2681e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 269bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2701e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2711e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2721e820e82SGeorgii Rymar }; 2731e820e82SGeorgii Rymar 2741e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register, 275167e7afcSRamNalamothu dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa, 276167e7afcSRamNalamothu dwarf::DW_CFA_val_offset}) 2771e820e82SGeorgii Rymar CheckOp_ULEB128_ULEB128(Inst); 2781e820e82SGeorgii Rymar 2791e820e82SGeorgii Rymar // A test for an instruction with two operands: ULEB128, SLEB128. 2801e820e82SGeorgii Rymar auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) { 2811e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 282bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2831e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2841e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2851e820e82SGeorgii Rymar 2861e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 287bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2881e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2891e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2901e820e82SGeorgii Rymar }; 2911e820e82SGeorgii Rymar 292167e7afcSRamNalamothu for (uint8_t Inst : 293167e7afcSRamNalamothu {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf, 294167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf}) 2951e820e82SGeorgii Rymar CheckOp_ULEB128_SLEB128(Inst); 2961e820e82SGeorgii Rymar 2971e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_expression instruction. 2981e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 299bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}), 3001e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 3011e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3021e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 303bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 3041e820e82SGeorgii Rymar /*expression length=*/0x1}), 3051e820e82SGeorgii Rymar FailedWithMessage( 3061e820e82SGeorgii Rymar "unexpected end of data at offset 0x2 while reading [0x2, 0x3)")); 3071e820e82SGeorgii Rymar // The DW_CFA_def_cfa_expression can contain a zero length expression. 308bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 3091e820e82SGeorgii Rymar /*ExprLen=*/0}), 3101e820e82SGeorgii Rymar Succeeded()); 3111e820e82SGeorgii Rymar 3121e820e82SGeorgii Rymar // A test for an instruction with three operands: ULEB128, expression length 3131e820e82SGeorgii Rymar // (ULEB128) and expression bytes. 3141e820e82SGeorgii Rymar auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) { 3151e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 316bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst}), 3171e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 3181e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3191e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 320bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 3211e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 3221e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3231e820e82SGeorgii Rymar // A zero length expression is fine 324bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst, 3251e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/0}), 3261e820e82SGeorgii Rymar Succeeded()); 3271e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 328bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, 3291e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/1}), 3301e820e82SGeorgii Rymar FailedWithMessage( 3311e820e82SGeorgii Rymar "unexpected end of data at offset 0x3 while reading [0x3, 0x4)")); 3321e820e82SGeorgii Rymar }; 3331e820e82SGeorgii Rymar 3341e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression}) 3351e820e82SGeorgii Rymar CheckOp_ULEB128_Expr(Inst); 3361e820e82SGeorgii Rymar } 3371e820e82SGeorgii Rymar 338f8122d35SGreg Clayton void expectDumpResult(const dwarf::UnwindLocation &Loc, 339f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 340f8122d35SGreg Clayton std::string Output; 341f8122d35SGreg Clayton raw_string_ostream OS(Output); 342f8122d35SGreg Clayton OS << Loc; 343f8122d35SGreg Clayton OS.flush(); 344f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 345f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 346f8122d35SGreg Clayton } 347f8122d35SGreg Clayton 348f8122d35SGreg Clayton TEST(DWARFDebugFrame, DumpUnwindLocations) { 349f8122d35SGreg Clayton // Test constructing unwind locations and dumping each kind. 350f8122d35SGreg Clayton constexpr int32_t PlusOff = 8; 351f8122d35SGreg Clayton constexpr int32_t MinusOff = -8; 352a1a3fdcdSGreg Clayton constexpr uint8_t RegNum = 12; 353f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified"); 354f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined"); 355f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createSame(), "same"); 356f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff), 357f8122d35SGreg Clayton "CFA+8"); 358f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff), 359f8122d35SGreg Clayton "CFA-8"); 360f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff), 361f8122d35SGreg Clayton "[CFA+8]"); 362f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff), 363f8122d35SGreg Clayton "[CFA-8]"); 364f8122d35SGreg Clayton 365f8122d35SGreg Clayton expectDumpResult( 366f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff), 367f8122d35SGreg Clayton "reg12+8"); 368f8122d35SGreg Clayton expectDumpResult( 369f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff), 370f8122d35SGreg Clayton "reg12-8"); 371f8122d35SGreg Clayton expectDumpResult( 372f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff), 373f8122d35SGreg Clayton "[reg12+8]"); 374f8122d35SGreg Clayton expectDumpResult( 375f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff), 376f8122d35SGreg Clayton "[reg12-8]"); 377f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12"); 378f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32"); 379f8122d35SGreg Clayton } 380f8122d35SGreg Clayton 381f8122d35SGreg Clayton void expectDumpResult(const dwarf::RegisterLocations &Locs, 382f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 383f8122d35SGreg Clayton std::string Output; 384f8122d35SGreg Clayton raw_string_ostream OS(Output); 385f8122d35SGreg Clayton OS << Locs; 386f8122d35SGreg Clayton OS.flush(); 387f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 388f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 389f8122d35SGreg Clayton } 390f8122d35SGreg Clayton 391f8122d35SGreg Clayton TEST(DWARFDebugFrame, RegisterLocations) { 392f8122d35SGreg Clayton // Test the functionality of the RegisterLocations class. 393f8122d35SGreg Clayton dwarf::RegisterLocations Locs; 394f8122d35SGreg Clayton expectDumpResult(Locs, ""); 395f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 396f8122d35SGreg Clayton // Set a register location for reg12 to unspecified and verify it dumps 397f8122d35SGreg Clayton // correctly. 398f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified()); 399f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 400f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=unspecified"); 401f8122d35SGreg Clayton 402f8122d35SGreg Clayton // Replace the register location for reg12 to "same" and verify it dumps 403f8122d35SGreg Clayton // correctly after it is modified 404f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame()); 405f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 406f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=same"); 407f8122d35SGreg Clayton 408f8122d35SGreg Clayton // Remove the register location for reg12 verify it dumps correctly after it 409f8122d35SGreg Clayton // is removed. 410f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 411f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 412f8122d35SGreg Clayton expectDumpResult(Locs, ""); 413f8122d35SGreg Clayton 414f8122d35SGreg Clayton // Verify multiple registers added to the list dump correctly. 415f8122d35SGreg Clayton auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4); 416f8122d35SGreg Clayton auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8); 417f8122d35SGreg Clayton auto Reg14Loc = dwarf::UnwindLocation::createSame(); 418f8122d35SGreg Clayton Locs.setRegisterLocation(12, Reg12Loc); 419f8122d35SGreg Clayton Locs.setRegisterLocation(13, Reg13Loc); 420f8122d35SGreg Clayton Locs.setRegisterLocation(14, Reg14Loc); 421f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 422f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same"); 423f8122d35SGreg Clayton 424f8122d35SGreg Clayton // Verify RegisterLocations::getRegisterLocation() works as expected. 425*89fab98eSFangrui Song std::optional<dwarf::UnwindLocation> OptionalLoc; 426f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(0); 4273361a364SKazu Hirata EXPECT_FALSE(OptionalLoc.has_value()); 428f8122d35SGreg Clayton 429f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(12); 4303361a364SKazu Hirata EXPECT_TRUE(OptionalLoc.has_value()); 431f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg12Loc); 432f8122d35SGreg Clayton 433f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(13); 4343361a364SKazu Hirata EXPECT_TRUE(OptionalLoc.has_value()); 435f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg13Loc); 436f8122d35SGreg Clayton 437f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(14); 4383361a364SKazu Hirata EXPECT_TRUE(OptionalLoc.has_value()); 439f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg14Loc); 440f8122d35SGreg Clayton 441f8122d35SGreg Clayton // Verify registers are correctly removed when multiple exist in the list. 442f8122d35SGreg Clayton Locs.removeRegisterLocation(13); 4433361a364SKazu Hirata EXPECT_FALSE(Locs.getRegisterLocation(13).has_value()); 444f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 445f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg14=same"); 446f8122d35SGreg Clayton Locs.removeRegisterLocation(14); 4473361a364SKazu Hirata EXPECT_FALSE(Locs.getRegisterLocation(14).has_value()); 448f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 449f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4]"); 450f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 4513361a364SKazu Hirata EXPECT_FALSE(Locs.getRegisterLocation(12).has_value()); 452f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 453f8122d35SGreg Clayton expectDumpResult(Locs, ""); 454f8122d35SGreg Clayton } 455f8122d35SGreg Clayton 456223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when 457223852d7SRamNalamothu // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty. 458223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows) { 459223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 460223852d7SRamNalamothu /*Offset=*/0x0, 461223852d7SRamNalamothu /*Length=*/0xff); 462223852d7SRamNalamothu 463223852d7SRamNalamothu // Having an empty instructions list is fine. 464223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 465223852d7SRamNalamothu EXPECT_TRUE(TestCIE.cfis().empty()); 466223852d7SRamNalamothu 467223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 468223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 469223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 470223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 471223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 472223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 473223852d7SRamNalamothu 474223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 475223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 476223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 477223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 478223852d7SRamNalamothu /*InitialLocation=*/0x1000, 479223852d7SRamNalamothu /*AddressRange=*/0x1000, 480223852d7SRamNalamothu /*Cie=*/&TestCIE, 481b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 482223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 483223852d7SRamNalamothu 484223852d7SRamNalamothu // Having an empty instructions list is fine. 485223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 486223852d7SRamNalamothu EXPECT_TRUE(TestFDE.cfis().empty()); 487223852d7SRamNalamothu 488223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 489223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 490223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 491223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 492223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 493223852d7SRamNalamothu } 494223852d7SRamNalamothu 495223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs 496223852d7SRamNalamothu // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions. 497223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) { 498223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 499223852d7SRamNalamothu /*Offset=*/0x0, 500223852d7SRamNalamothu /*Length=*/0xff); 501223852d7SRamNalamothu 502223852d7SRamNalamothu // Make a CIE that has only DW_CFA_nop instructions. 503223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded()); 504223852d7SRamNalamothu EXPECT_TRUE(!TestCIE.cfis().empty()); 505223852d7SRamNalamothu 506223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 507223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 508223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 509223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 510223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 511223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 512223852d7SRamNalamothu 513223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 514223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 515223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 516223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 517223852d7SRamNalamothu /*InitialLocation=*/0x1000, 518223852d7SRamNalamothu /*AddressRange=*/0x1000, 519223852d7SRamNalamothu /*Cie=*/&TestCIE, 520b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 521223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 522223852d7SRamNalamothu 523223852d7SRamNalamothu // Make an FDE that has only DW_CFA_nop instructions. 524223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded()); 525223852d7SRamNalamothu EXPECT_TRUE(!TestFDE.cfis().empty()); 526223852d7SRamNalamothu 527223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 528223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 529223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 530223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 531223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 532223852d7SRamNalamothu } 533223852d7SRamNalamothu 534f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 535f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 536f8122d35SGreg Clayton /*Offset=*/0x0, 537f8122d35SGreg Clayton /*Length=*/0xff); 538f8122d35SGreg Clayton 539f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 540f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 541f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 542f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 543f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 544f8122d35SGreg Clayton /*AddressRange=*/0x1000, 545f8122d35SGreg Clayton /*Cie=*/&TestCIE, 546b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 547f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 548f8122d35SGreg Clayton 549f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 550f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 551f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 552f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 553f8122d35SGreg Clayton Succeeded()); 554f8122d35SGreg Clayton 555f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 556f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 557f8122d35SGreg Clayton // Here we encode two DW_CFA_set_loc opcodes: 558f8122d35SGreg Clayton // DW_CFA_set_loc(0x1100) 559f8122d35SGreg Clayton // DW_CFA_set_loc(0x1000) 560f8122d35SGreg Clayton // These opcodes cause a new row to be appended to the rows in a UnwindTable 561f8122d35SGreg Clayton // and the resulting rows are not in ascending address order and should cause 562f8122d35SGreg Clayton // a state machine error. 563f8122d35SGreg Clayton EXPECT_THAT_ERROR( 564f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 565f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 566f8122d35SGreg Clayton Succeeded()); 567f8122d35SGreg Clayton 568f8122d35SGreg Clayton // Verify we catch state machine error. 569f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 570f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 571f8122d35SGreg Clayton FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 572f8122d35SGreg Clayton " must be greater than the current row " 573f8122d35SGreg Clayton "address 0x1100")); 574f8122d35SGreg Clayton } 575f8122d35SGreg Clayton 576f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 577f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 578f8122d35SGreg Clayton /*Offset=*/0x0, 579f8122d35SGreg Clayton /*Length=*/0xff); 580f8122d35SGreg Clayton 581f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 582f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 583f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 584f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 585f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 586f8122d35SGreg Clayton /*AddressRange=*/0x1000, 587f8122d35SGreg Clayton /*Cie=*/&TestCIE, 588b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 589f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 590f8122d35SGreg Clayton 591f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 592f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 593f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 594f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 595f8122d35SGreg Clayton Succeeded()); 596f8122d35SGreg Clayton 597f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 598f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 599f8122d35SGreg Clayton // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 600f8122d35SGreg Clayton // DW_CFA_remember_state, and an error should be returned. 601f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 602f8122d35SGreg Clayton Succeeded()); 603f8122d35SGreg Clayton 604f8122d35SGreg Clayton // Verify we catch state machine error. 605f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 606f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 607f8122d35SGreg Clayton FailedWithMessage("DW_CFA_restore_state without a matching " 608f8122d35SGreg Clayton "previous DW_CFA_remember_state")); 609f8122d35SGreg Clayton } 610f8122d35SGreg Clayton 611f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 612f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 613f8122d35SGreg Clayton /*Offset=*/0x0, 614f8122d35SGreg Clayton /*Length=*/0xff); 615f8122d35SGreg Clayton 616f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 617f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 618f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 619f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 620f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 621f8122d35SGreg Clayton /*AddressRange=*/0x1000, 622f8122d35SGreg Clayton /*Cie=*/&TestCIE, 623b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 624f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 625f8122d35SGreg Clayton 626f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 627f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 628f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 629f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 630f8122d35SGreg Clayton Succeeded()); 631f8122d35SGreg Clayton 632f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 633f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 634f8122d35SGreg Clayton // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 635f8122d35SGreg Clayton // found any documentation that describes what this does after some brief 636f8122d35SGreg Clayton // searching. 637f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 638f8122d35SGreg Clayton Succeeded()); 639f8122d35SGreg Clayton 640f8122d35SGreg Clayton // Verify we catch state machine error. 641f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 642f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 643f8122d35SGreg Clayton FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 644f8122d35SGreg Clayton "architecture x86_64")); 645f8122d35SGreg Clayton } 646f8122d35SGreg Clayton 647f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 648f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 649f8122d35SGreg Clayton /*Offset=*/0x0, 650f8122d35SGreg Clayton /*Length=*/0xff); 651f8122d35SGreg Clayton 652f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 653f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 654f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 655f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 656f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 657f8122d35SGreg Clayton /*AddressRange=*/0x1000, 658f8122d35SGreg Clayton /*Cie=*/&TestCIE, 659b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 660f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 661f8122d35SGreg Clayton 662f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 663f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 664f8122d35SGreg Clayton // error back. 665f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 666f8122d35SGreg Clayton 667f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 668f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 669f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 670f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 671f8122d35SGreg Clayton // cause an error. 672f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 673f8122d35SGreg Clayton Succeeded()); 674f8122d35SGreg Clayton 675f8122d35SGreg Clayton // Verify we catch state machine error. 676f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 677f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 678f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 679f8122d35SGreg Clayton "rule was not RegPlusOffset")); 680f8122d35SGreg Clayton } 681f8122d35SGreg Clayton 682f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 683f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 684f8122d35SGreg Clayton /*Offset=*/0x0, 685f8122d35SGreg Clayton /*Length=*/0xff); 686f8122d35SGreg Clayton 687f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 688f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 689f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 690f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 691f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 692f8122d35SGreg Clayton /*AddressRange=*/0x1000, 693f8122d35SGreg Clayton /*Cie=*/&TestCIE, 694b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 695f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 696f8122d35SGreg Clayton 697f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 698f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 699f8122d35SGreg Clayton // appropriate error back. 700f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 701f8122d35SGreg Clayton 702f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 703f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 704f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 705f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 706f8122d35SGreg Clayton // cause an error. 707f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 708f8122d35SGreg Clayton Succeeded()); 709f8122d35SGreg Clayton 710f8122d35SGreg Clayton // Verify we catch state machine error. 711f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 712f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 713f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 714f8122d35SGreg Clayton "rule was not RegPlusOffset")); 715f8122d35SGreg Clayton } 716f8122d35SGreg Clayton 717f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 718f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 719f8122d35SGreg Clayton /*Offset=*/0x0, 720f8122d35SGreg Clayton /*Length=*/0xff); 721f8122d35SGreg Clayton 722f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 723f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 724f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 725f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 726f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 727f8122d35SGreg Clayton /*AddressRange=*/0x1000, 728f8122d35SGreg Clayton /*Cie=*/&TestCIE, 729b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 730f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 731f8122d35SGreg Clayton 732f8122d35SGreg Clayton // Make a CIE that has only defines the CFA register with no offset. Some 733f8122d35SGreg Clayton // architectures do this and we must ensure that we set the CFA value to be 734f8122d35SGreg Clayton // equal to that register with no offset. 735f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 736f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 737f8122d35SGreg Clayton Succeeded()); 738f8122d35SGreg Clayton 739f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 740f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 741f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 742f8122d35SGreg Clayton // our CIE didn't define the CFA in terms of a register plus offset, so this 743f8122d35SGreg Clayton // should cause an error. 744f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 745f8122d35SGreg Clayton 746f8122d35SGreg Clayton // Verify we catch state machine error. 747f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 748f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 749f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 750f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 751f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 752f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getCFAValue(), 753f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 754f8122d35SGreg Clayton } 755f8122d35SGreg Clayton 756f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 757f8122d35SGreg Clayton // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 758f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 759f8122d35SGreg Clayton /*Offset=*/0x0, 760f8122d35SGreg Clayton /*Length=*/0xff); 761f8122d35SGreg Clayton 762f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 763f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 764f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 765f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 766f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 767f8122d35SGreg Clayton /*AddressRange=*/0x1000, 768f8122d35SGreg Clayton /*Cie=*/&TestCIE, 769b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 770f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 771f8122d35SGreg Clayton 772f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 773f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 774f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 775f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 776f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 777f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 778f8122d35SGreg Clayton 779f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 780f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 781f8122d35SGreg Clayton Succeeded()); 782f8122d35SGreg Clayton 783f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 784f8122d35SGreg Clayton // row pushing opcodes. This will verify that all opcodes that should create 785f8122d35SGreg Clayton // a row are correctly working. Each opcode will push a row prior to 786f8122d35SGreg Clayton // advancing the address, and then a row will be automatically pushed at the 787f8122d35SGreg Clayton // end of the parsing, so we should end up with 6 rows starting at address 788f8122d35SGreg Clayton // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 789f8122d35SGreg Clayton // from the CIE. 790f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 791f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc1, 792f8122d35SGreg Clayton 4, 793f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc2, 794f8122d35SGreg Clayton 4, 795f8122d35SGreg Clayton 0, 796f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc4, 797f8122d35SGreg Clayton 4, 798f8122d35SGreg Clayton 0, 799f8122d35SGreg Clayton 0, 800f8122d35SGreg Clayton 0, 801f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 802f8122d35SGreg Clayton 0x14, 803f8122d35SGreg Clayton 0x10, 804f8122d35SGreg Clayton 0, 805f8122d35SGreg Clayton 0, 806f8122d35SGreg Clayton 0, 807f8122d35SGreg Clayton 0, 808f8122d35SGreg Clayton 0, 809f8122d35SGreg Clayton 0}), 810f8122d35SGreg Clayton Succeeded()); 811f8122d35SGreg Clayton 812f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 813f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 814f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 815f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 816f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 817f8122d35SGreg Clayton 818f8122d35SGreg Clayton // Verify we catch state machine error. 819f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 820f8122d35SGreg Clayton ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 821f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 822f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 6u); 823f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 824f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 825f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 826f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 827f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 828f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 829f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 830f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 831f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 832f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 833f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 834f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 835f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 836f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 837f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 838f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 839f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 840f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 841f8122d35SGreg Clayton } 842f8122d35SGreg Clayton 843f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 844f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 845f8122d35SGreg Clayton // machine. 846f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 847f8122d35SGreg Clayton /*Offset=*/0x0, 848f8122d35SGreg Clayton /*Length=*/0xff); 849f8122d35SGreg Clayton 850f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 851f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 852f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 853f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 854f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 855f8122d35SGreg Clayton /*AddressRange=*/0x1000, 856f8122d35SGreg Clayton /*Cie=*/&TestCIE, 857b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 858f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 859f8122d35SGreg Clayton 860f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 861f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 862f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 863f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 864f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 865f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 866f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 867f8122d35SGreg Clayton 868f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 869f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 870f8122d35SGreg Clayton Succeeded()); 871f8122d35SGreg Clayton 872f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 873f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 874f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 875f8122d35SGreg Clayton // two rows: 876f8122d35SGreg Clayton // - one with Reg = [CFA-8] 877f8122d35SGreg Clayton // - one with Reg = InReg 878f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 879f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 880f8122d35SGreg Clayton dwarf::DW_CFA_restore | Reg}), 881f8122d35SGreg Clayton Succeeded()); 882f8122d35SGreg Clayton 883f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 884f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 885f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 886f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 887f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 888f8122d35SGreg Clayton 889f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 890f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 891f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 892f8122d35SGreg Clayton 893f8122d35SGreg Clayton // Verify we catch state machine error. 894f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 895f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 896f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 897f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 898f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 899f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 900f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 901f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 902f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 903f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 904f8122d35SGreg Clayton } 905f8122d35SGreg Clayton 906f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 907f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 908f8122d35SGreg Clayton // machine. 909f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 910f8122d35SGreg Clayton /*Offset=*/0x0, 911f8122d35SGreg Clayton /*Length=*/0xff); 912f8122d35SGreg Clayton 913f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 914f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 915f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 916f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 917f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 918f8122d35SGreg Clayton /*AddressRange=*/0x1000, 919f8122d35SGreg Clayton /*Cie=*/&TestCIE, 920b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 921f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 922f8122d35SGreg Clayton 923f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 924f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 925f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 926f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 927f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 928f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 929f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 930f8122d35SGreg Clayton 931f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 932f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 933f8122d35SGreg Clayton Succeeded()); 934f8122d35SGreg Clayton 935f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 936f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 937f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 938f8122d35SGreg Clayton // end up with two rows: 939f8122d35SGreg Clayton // - one with Reg = [CFA-8] 940f8122d35SGreg Clayton // - one with Reg = InReg 941f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 942f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 943f8122d35SGreg Clayton dwarf::DW_CFA_restore_extended, Reg}), 944f8122d35SGreg Clayton Succeeded()); 945f8122d35SGreg Clayton 946f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 947f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 948f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 949f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 950f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 951f8122d35SGreg Clayton 952f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 953f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 954f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 955f8122d35SGreg Clayton 956f8122d35SGreg Clayton // Verify we catch state machine error. 957f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 958f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 959f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 960f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 961f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 962f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 963f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 964f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 965f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 966f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 967f8122d35SGreg Clayton } 968f8122d35SGreg Clayton 969f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 970f8122d35SGreg Clayton // Test that DW_CFA_offset, DW_CFA_offset_extended and 971f8122d35SGreg Clayton // DW_CFA_offset_extended_sf work as expected when parsed in the state 972f8122d35SGreg Clayton // machine. 973f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 974f8122d35SGreg Clayton /*Offset=*/0x0, 975f8122d35SGreg Clayton /*Length=*/0xff); 976f8122d35SGreg Clayton 977f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 978f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 979f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 980f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 981f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 982f8122d35SGreg Clayton /*AddressRange=*/0x1000, 983f8122d35SGreg Clayton /*Cie=*/&TestCIE, 984b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 985f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 986f8122d35SGreg Clayton 987f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 988f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 989f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 990f8122d35SGreg Clayton Succeeded()); 991f8122d35SGreg Clayton 992f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 993f8122d35SGreg Clayton // unwind rules for the follwing registers: 994f8122d35SGreg Clayton // Reg1 = [CFA-8] 995f8122d35SGreg Clayton // Reg2 = [CFA-16] 996f8122d35SGreg Clayton // Reg3 = [CFA+8] 997a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 998a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 999a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 1000f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 1001f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1002f8122d35SGreg Clayton parseCFI(TestFDE, 1003f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 1004f8122d35SGreg Clayton Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 1005f8122d35SGreg Clayton Succeeded()); 1006f8122d35SGreg Clayton 1007f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1008f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1009f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1010f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1011f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1012f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1013f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1014f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1015f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 1016f8122d35SGreg Clayton 1017f8122d35SGreg Clayton // Verify we catch state machine error. 1018f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1019f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1020f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1021f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1022f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1023f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1024f8122d35SGreg Clayton } 1025f8122d35SGreg Clayton 1026f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 1027f8122d35SGreg Clayton // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 1028f8122d35SGreg Clayton // parsed in the state machine. 1029f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1030f8122d35SGreg Clayton /*Offset=*/0x0, 1031f8122d35SGreg Clayton /*Length=*/0xff); 1032f8122d35SGreg Clayton 1033f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1034f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1035f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1036f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1037f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1038f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1039f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1040b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1041f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1042f8122d35SGreg Clayton 1043f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1044f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1045f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1046f8122d35SGreg Clayton Succeeded()); 1047f8122d35SGreg Clayton 1048f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1049f8122d35SGreg Clayton // unwind rules for the follwing registers: 1050f8122d35SGreg Clayton // Reg1 = [CFA-8] 1051f8122d35SGreg Clayton // Reg2 = [CFA-16] 1052f8122d35SGreg Clayton // Reg3 = [CFA+8] 1053a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1054a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1055f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 1056f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1057f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 1058f8122d35SGreg Clayton dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 1059f8122d35SGreg Clayton Succeeded()); 1060f8122d35SGreg Clayton 1061f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1062f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1063f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1064f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1065f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 1066f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1067f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 1068f8122d35SGreg Clayton 1069f8122d35SGreg Clayton // Verify we catch state machine error. 1070f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1071f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1072f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1073f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1074f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1075f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1076f8122d35SGreg Clayton } 1077f8122d35SGreg Clayton 1078f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 1079f8122d35SGreg Clayton // Test that DW_CFA_nop works as expected when parsed in the state machine. 1080f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1081f8122d35SGreg Clayton /*Offset=*/0x0, 1082f8122d35SGreg Clayton /*Length=*/0xff); 1083f8122d35SGreg Clayton 1084f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1085f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1086f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1087f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1088f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1089f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1090f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1091b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1092f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1093f8122d35SGreg Clayton 1094f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1095f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1096f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1097f8122d35SGreg Clayton Succeeded()); 1098f8122d35SGreg Clayton 1099f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1100f8122d35SGreg Clayton // unwind rules for the follwing registers: 1101f8122d35SGreg Clayton // Reg1 = [CFA-8] 1102f8122d35SGreg Clayton // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1103a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1104f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1105f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1106f8122d35SGreg Clayton Succeeded()); 1107f8122d35SGreg Clayton 1108f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1109f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1110f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1111f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1112f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1113f8122d35SGreg Clayton 1114f8122d35SGreg Clayton // Verify we catch state machine error. 1115f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1116f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1117f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1118f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1119f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1120f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1121f8122d35SGreg Clayton } 1122f8122d35SGreg Clayton 1123f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1124f8122d35SGreg Clayton // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1125f8122d35SGreg Clayton // when parsed in the state machine. 1126f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1127f8122d35SGreg Clayton /*Offset=*/0x0, 1128f8122d35SGreg Clayton /*Length=*/0xff); 1129f8122d35SGreg Clayton 1130f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1131f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1132f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1133f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1134f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1135f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1136f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1137b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1138f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1139f8122d35SGreg Clayton 1140f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1141f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1142f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1143f8122d35SGreg Clayton Succeeded()); 1144f8122d35SGreg Clayton 1145f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1146f8122d35SGreg Clayton // follwing rows: 1147f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=[CFA-8] 1148f8122d35SGreg Clayton // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1149f8122d35SGreg Clayton // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1150f8122d35SGreg Clayton // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1151f8122d35SGreg Clayton // 0x1010: CFA=reg12+32: Reg1=[CFA-8] 1152f8122d35SGreg Clayton // This state machine will: 1153f8122d35SGreg Clayton // - set Reg1 location 1154f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1155f8122d35SGreg Clayton // - remember the state 1156f8122d35SGreg Clayton // - set Reg2 location 1157f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1158f8122d35SGreg Clayton // - remember the state 1159f8122d35SGreg Clayton // - set Reg3 location 1160f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1161f8122d35SGreg Clayton // - remember the state where Reg1 and Reg2 were set 1162f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1163f8122d35SGreg Clayton // - remember the state where only Reg1 was set 1164f8122d35SGreg Clayton // - push a row (automatically at the end of instruction parsing) 1165f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1166a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1167a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1168a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 1169f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1170f8122d35SGreg Clayton parseCFI(TestFDE, 1171f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1172f8122d35SGreg Clayton dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1173f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1174f8122d35SGreg Clayton dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1175f8122d35SGreg Clayton dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1176f8122d35SGreg Clayton dwarf::DW_CFA_restore_state}), 1177f8122d35SGreg Clayton Succeeded()); 1178f8122d35SGreg Clayton 1179f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1180f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1181f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 1182f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 1183f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1184f8122d35SGreg Clayton 1185f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 1186f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1187f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1188f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1189f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1190f8122d35SGreg Clayton 1191f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs3; 1192f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1193f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1194f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1195f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1196f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1197f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 1198f8122d35SGreg Clayton 1199f8122d35SGreg Clayton // Verify we catch state machine error. 1200f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1201f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1202f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1203f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1204f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1205f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1206f8122d35SGreg Clayton 1207f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1208f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1209f8122d35SGreg Clayton 1210f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1211f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1212f8122d35SGreg Clayton 1213f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1214f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1215f8122d35SGreg Clayton 1216f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1217f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1218f8122d35SGreg Clayton } 1219f8122d35SGreg Clayton 1220f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1221f8122d35SGreg Clayton // Test that DW_CFA_undefined works as expected when parsed in the state 1222f8122d35SGreg Clayton // machine. 1223f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1224f8122d35SGreg Clayton /*Offset=*/0x0, 1225f8122d35SGreg Clayton /*Length=*/0xff); 1226f8122d35SGreg Clayton 1227f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1228f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1229f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1230f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1231f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1232f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1233f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1234b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1235f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1236f8122d35SGreg Clayton 1237f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1238f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1239f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1240f8122d35SGreg Clayton Succeeded()); 1241f8122d35SGreg Clayton 1242f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1243f8122d35SGreg Clayton // follwing rows: 1244f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=undefined 1245f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1246a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1247f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1248f8122d35SGreg Clayton Succeeded()); 1249f8122d35SGreg Clayton 1250f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1251f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1252f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1253f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, 1254f8122d35SGreg Clayton dwarf::UnwindLocation::createUndefined()); 1255f8122d35SGreg Clayton 1256f8122d35SGreg Clayton // Verify we catch state machine error. 1257f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1258f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1259f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1260f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1261f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1262f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1263f8122d35SGreg Clayton } 1264f8122d35SGreg Clayton 1265f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1266f8122d35SGreg Clayton // Test that DW_CFA_same_value works as expected when parsed in the state 1267f8122d35SGreg Clayton // machine. 1268f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1269f8122d35SGreg Clayton /*Offset=*/0x0, 1270f8122d35SGreg Clayton /*Length=*/0xff); 1271f8122d35SGreg Clayton 1272f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1273f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1274f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1275f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1276f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1277f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1278f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1279b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1280f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1281f8122d35SGreg Clayton 1282f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1283f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1284f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1285f8122d35SGreg Clayton Succeeded()); 1286f8122d35SGreg Clayton 1287f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1288f8122d35SGreg Clayton // follwing rows: 1289f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1290f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1291a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1292f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1293f8122d35SGreg Clayton Succeeded()); 1294f8122d35SGreg Clayton 1295f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1296f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1297f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1298f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1299f8122d35SGreg Clayton 1300f8122d35SGreg Clayton // Verify we catch state machine error. 1301f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1302f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1303f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1304f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1305f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1306f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1307f8122d35SGreg Clayton } 1308f8122d35SGreg Clayton 1309f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1310f8122d35SGreg Clayton // Test that DW_CFA_register works as expected when parsed in the state 1311f8122d35SGreg Clayton // machine. 1312f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1313f8122d35SGreg Clayton /*Offset=*/0x0, 1314f8122d35SGreg Clayton /*Length=*/0xff); 1315f8122d35SGreg Clayton 1316f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1317f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1318f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1319f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1320f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1321f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1322f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1323b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1324f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1325f8122d35SGreg Clayton 1326f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1327f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1328f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1329f8122d35SGreg Clayton Succeeded()); 1330f8122d35SGreg Clayton 1331f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1332f8122d35SGreg Clayton // follwing rows: 1333f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1334f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1335f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1336f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1337f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1338f8122d35SGreg Clayton Succeeded()); 1339f8122d35SGreg Clayton 1340f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1341f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1342f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1343f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1344f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1345f8122d35SGreg Clayton 1346f8122d35SGreg Clayton // Verify we catch state machine error. 1347f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1348f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1349f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1350f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1351f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1352f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1353f8122d35SGreg Clayton } 1354f8122d35SGreg Clayton 1355f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1356f8122d35SGreg Clayton // Test that DW_CFA_expression works as expected when parsed in the state 1357f8122d35SGreg Clayton // machine. 1358f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1359f8122d35SGreg Clayton /*Offset=*/0x0, 1360f8122d35SGreg Clayton /*Length=*/0xff); 1361f8122d35SGreg Clayton 1362f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1363f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1364f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1365f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1366f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1367f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1368f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1369b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1370f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1371f8122d35SGreg Clayton 1372f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1373f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1374f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1375f8122d35SGreg Clayton Succeeded()); 1376f8122d35SGreg Clayton 1377f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1378f8122d35SGreg Clayton // follwing rows: 1379f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1380f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1381f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1382f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1383f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1384f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1385f8122d35SGreg Clayton 1386f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1387f8122d35SGreg Clayton 1388f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1389f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1390f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1391f8122d35SGreg Clayton 1392f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1393f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1394f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1395f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1396f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1397f8122d35SGreg Clayton 1398f8122d35SGreg Clayton // Verify we catch state machine error. 1399f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1400f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1401f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1402f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1403f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1404f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1405f8122d35SGreg Clayton } 1406f8122d35SGreg Clayton 1407f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1408f8122d35SGreg Clayton // Test that DW_CFA_val_expression works as expected when parsed in the state 1409f8122d35SGreg Clayton // machine. 1410f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1411f8122d35SGreg Clayton /*Offset=*/0x0, 1412f8122d35SGreg Clayton /*Length=*/0xff); 1413f8122d35SGreg Clayton 1414f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1415f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1416f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1417f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1418f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1419f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1420f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1421b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1422f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1423f8122d35SGreg Clayton 1424f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1425f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1426f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1427f8122d35SGreg Clayton Succeeded()); 1428f8122d35SGreg Clayton 1429f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1430f8122d35SGreg Clayton // follwing rows: 1431f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1432f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1433f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1434f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1435f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1436f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1437f8122d35SGreg Clayton 1438f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1439f8122d35SGreg Clayton 1440f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1441f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1442f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1443f8122d35SGreg Clayton 1444f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1445f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1446f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1447f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1448f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1449f8122d35SGreg Clayton 1450f8122d35SGreg Clayton // Verify we catch state machine error. 1451f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1452f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1453f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1454f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1455f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1456f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1457f8122d35SGreg Clayton } 1458f8122d35SGreg Clayton 1459f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1460f8122d35SGreg Clayton // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1461f8122d35SGreg Clayton // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1462f8122d35SGreg Clayton // parsed in the state machine. 1463f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1464f8122d35SGreg Clayton /*Offset=*/0x0, 1465f8122d35SGreg Clayton /*Length=*/0xff); 1466f8122d35SGreg Clayton 1467f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1468f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1469f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1470f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1471f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1472f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1473f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1474b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1475f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1476f8122d35SGreg Clayton 1477f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1478f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1479f8122d35SGreg Clayton constexpr uint8_t CFAReg1 = 12; 1480f8122d35SGreg Clayton constexpr uint8_t CFAOff1 = 32; 1481f8122d35SGreg Clayton constexpr uint8_t CFAReg2 = 13; 1482f8122d35SGreg Clayton constexpr uint8_t CFAOff2 = 48; 1483f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1484f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1485f8122d35SGreg Clayton 1486f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1487f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 1488f8122d35SGreg Clayton Succeeded()); 1489f8122d35SGreg Clayton 1490f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 1491f8122d35SGreg Clayton // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1492f8122d35SGreg Clayton // create a row are correctly working. 1493f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1494f8122d35SGreg Clayton parseCFI( 1495f8122d35SGreg Clayton TestFDE, 1496f8122d35SGreg Clayton { 1497f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1498f8122d35SGreg Clayton CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1499f8122d35SGreg Clayton dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1500f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1501f8122d35SGreg Clayton 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1502f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1503f8122d35SGreg Clayton 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1504f8122d35SGreg Clayton }), 1505f8122d35SGreg Clayton Succeeded()); 1506f8122d35SGreg Clayton 1507f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1508f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1509f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1510f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1511f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1512f8122d35SGreg Clayton 1513f8122d35SGreg Clayton // Verify we catch state machine error. 1514f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1515f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1516f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1517f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1518f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1519f8122d35SGreg Clayton EXPECT_EQ( 1520f8122d35SGreg Clayton Rows[0].getCFAValue(), 1521f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1522f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1523f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1524f8122d35SGreg Clayton 1525f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1526f8122d35SGreg Clayton EXPECT_EQ( 1527f8122d35SGreg Clayton Rows[1].getCFAValue(), 1528f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1529f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1530f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1531f8122d35SGreg Clayton 1532f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1533f8122d35SGreg Clayton EXPECT_EQ( 1534f8122d35SGreg Clayton Rows[2].getCFAValue(), 1535f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1536f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1537f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1538f8122d35SGreg Clayton 1539f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1540f8122d35SGreg Clayton EXPECT_EQ( 1541f8122d35SGreg Clayton Rows[3].getCFAValue(), 1542f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1543f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1544f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1545f8122d35SGreg Clayton 1546f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1547f8122d35SGreg Clayton EXPECT_EQ( 1548f8122d35SGreg Clayton Rows[4].getCFAValue(), 1549f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1550f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1551f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1552f8122d35SGreg Clayton } 1553f8122d35SGreg Clayton 1554167e7afcSRamNalamothu TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) { 1555167e7afcSRamNalamothu // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf, 1556167e7afcSRamNalamothu // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and 1557167e7afcSRamNalamothu // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state 1558167e7afcSRamNalamothu // machine. 1559167e7afcSRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1560167e7afcSRamNalamothu /*Offset=*/0x0, 1561167e7afcSRamNalamothu /*Length=*/0xff); 1562167e7afcSRamNalamothu 1563167e7afcSRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1564167e7afcSRamNalamothu /*Offset=*/0x3333abcdabcd, 1565167e7afcSRamNalamothu /*Length=*/0x4444abcdabcd, 1566167e7afcSRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 1567167e7afcSRamNalamothu /*InitialLocation=*/0x1000, 1568167e7afcSRamNalamothu /*AddressRange=*/0x1000, 1569167e7afcSRamNalamothu /*Cie=*/&TestCIE, 1570b6a01caaSKazu Hirata /*LSDAAddress=*/std::nullopt, 1571167e7afcSRamNalamothu /*Arch=*/Triple::x86_64); 1572167e7afcSRamNalamothu 1573167e7afcSRamNalamothu // Make a CIE that has a valid CFA definition and a single register unwind 1574167e7afcSRamNalamothu // rule for register that we will verify is in all of the pushed rows. 1575167e7afcSRamNalamothu constexpr uint8_t CFAReg1 = 12; 1576167e7afcSRamNalamothu constexpr uint8_t CFAOff1 = 32; 1577167e7afcSRamNalamothu constexpr uint8_t CFAReg2 = 13; 1578167e7afcSRamNalamothu constexpr uint8_t CFAOff2 = 48; 1579167e7afcSRamNalamothu constexpr uint8_t Reg = 13; 1580167e7afcSRamNalamothu constexpr uint8_t InReg = 14; 1581167e7afcSRamNalamothu constexpr uint8_t AddrSpace = 2; 1582167e7afcSRamNalamothu 1583167e7afcSRamNalamothu EXPECT_THAT_ERROR( 1584167e7afcSRamNalamothu parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1, 1585167e7afcSRamNalamothu AddrSpace, dwarf::DW_CFA_register, Reg, InReg}), 1586167e7afcSRamNalamothu Succeeded()); 1587167e7afcSRamNalamothu 1588167e7afcSRamNalamothu // Make a FDE with DWARF call frame instruction opcodes that use all of the 1589167e7afcSRamNalamothu // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1590167e7afcSRamNalamothu // create a row are correctly working. 1591167e7afcSRamNalamothu EXPECT_THAT_ERROR( 1592167e7afcSRamNalamothu parseCFI( 1593167e7afcSRamNalamothu TestFDE, 1594167e7afcSRamNalamothu { 1595167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1596167e7afcSRamNalamothu CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1597167e7afcSRamNalamothu dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1598167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1599167e7afcSRamNalamothu 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1600167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1601167e7afcSRamNalamothu 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1602167e7afcSRamNalamothu }), 1603167e7afcSRamNalamothu Succeeded()); 1604167e7afcSRamNalamothu 1605167e7afcSRamNalamothu // Create locations that we expect the UnwindRow objects to contain after 1606167e7afcSRamNalamothu // parsing the DWARF call frame instructions. 1607167e7afcSRamNalamothu dwarf::RegisterLocations VerifyLocs; 1608167e7afcSRamNalamothu VerifyLocs.setRegisterLocation( 1609167e7afcSRamNalamothu Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1610167e7afcSRamNalamothu 1611167e7afcSRamNalamothu // Verify we catch state machine error. 1612167e7afcSRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1613167e7afcSRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1614167e7afcSRamNalamothu const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1615167e7afcSRamNalamothu EXPECT_EQ(Rows.size(), 5u); 1616167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1617167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getCFAValue(), 1618167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1, 1619167e7afcSRamNalamothu AddrSpace)); 1620167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1621167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1622167e7afcSRamNalamothu 1623167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1624167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getCFAValue(), 1625167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1626167e7afcSRamNalamothu AddrSpace)); 1627167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1628167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1629167e7afcSRamNalamothu 1630167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1631167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getCFAValue(), 1632167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2, 1633167e7afcSRamNalamothu AddrSpace)); 1634167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1635167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1636167e7afcSRamNalamothu 1637167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1638167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getCFAValue(), 1639167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1640167e7afcSRamNalamothu AddrSpace)); 1641167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1642167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1643167e7afcSRamNalamothu 1644167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1645167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getCFAValue(), 1646167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2, 1647167e7afcSRamNalamothu AddrSpace)); 1648167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1649167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1650167e7afcSRamNalamothu } 1651167e7afcSRamNalamothu 1652cada5b88SIgor Kudrin } // end anonymous namespace 1653