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