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 9bee8cdcaSGeorgii Rymar #include "llvm/ADT/DenseSet.h" 10cada5b88SIgor Kudrin #include "llvm/ADT/SmallVector.h" 11cada5b88SIgor Kudrin #include "llvm/ADT/StringRef.h" 12cada5b88SIgor Kudrin #include "llvm/BinaryFormat/Dwarf.h" 13cada5b88SIgor Kudrin #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 141e820e82SGeorgii Rymar #include "llvm/Testing/Support/Error.h" 15cada5b88SIgor Kudrin #include "gtest/gtest.h" 16cada5b88SIgor Kudrin 17cada5b88SIgor Kudrin using namespace llvm; 18cada5b88SIgor Kudrin 19cada5b88SIgor Kudrin namespace { 20cada5b88SIgor Kudrin 21cada5b88SIgor Kudrin dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) { 22cada5b88SIgor Kudrin return dwarf::CIE(IsDWARF64, Offset, Length, 23cada5b88SIgor Kudrin /*Version=*/3, 24cada5b88SIgor Kudrin /*Augmentation=*/StringRef(), 25cada5b88SIgor Kudrin /*AddressSize=*/8, 26cada5b88SIgor Kudrin /*SegmentDescriptorSize=*/0, 27cada5b88SIgor Kudrin /*CodeAlignmentFactor=*/1, 28cada5b88SIgor Kudrin /*DataAlignmentFactor=*/-8, 29cada5b88SIgor Kudrin /*ReturnAddressRegister=*/16, 30cada5b88SIgor Kudrin /*AugmentationData=*/StringRef(), 31cada5b88SIgor Kudrin /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr, 32cada5b88SIgor Kudrin /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit, 33cada5b88SIgor Kudrin /*Personality=*/None, 34cada5b88SIgor Kudrin /*PersonalityEnc=*/None, 35cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 36cada5b88SIgor Kudrin } 37cada5b88SIgor Kudrin 38cada5b88SIgor Kudrin void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH, 39cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 40cada5b88SIgor Kudrin std::string Output; 41cada5b88SIgor Kudrin raw_string_ostream OS(Output); 420ec5baa1SDavid Blaikie TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); 43cada5b88SIgor Kudrin OS.flush(); 44cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 45cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 46cada5b88SIgor Kudrin } 47cada5b88SIgor Kudrin 48cada5b88SIgor Kudrin void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH, 49cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 50cada5b88SIgor Kudrin std::string Output; 51cada5b88SIgor Kudrin raw_string_ostream OS(Output); 520ec5baa1SDavid Blaikie TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH); 53cada5b88SIgor Kudrin OS.flush(); 54cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 55cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 56cada5b88SIgor Kudrin } 57cada5b88SIgor Kudrin 58cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF32CIE) { 59cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 60cada5b88SIgor Kudrin /*Offset=*/0x1111abcd, 61cada5b88SIgor Kudrin /*Length=*/0x2222abcd); 62cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE"); 63cada5b88SIgor Kudrin } 64cada5b88SIgor Kudrin 65cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64CIE) { 66cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 67cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 68cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 69cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, 70cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE"); 71cada5b88SIgor Kudrin } 72cada5b88SIgor Kudrin 73cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEHCIE) { 74cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 75cada5b88SIgor Kudrin /*Offset=*/0x1000, 76cada5b88SIgor Kudrin /*Length=*/0x20); 77cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE"); 78cada5b88SIgor Kudrin } 79cada5b88SIgor Kudrin 80cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64CIE) { 81cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 82cada5b88SIgor Kudrin /*Offset=*/0x1000, 83cada5b88SIgor Kudrin /*Length=*/0x20); 84cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, 85cada5b88SIgor Kudrin "00001000 0000000000000020 00000000 CIE"); 86cada5b88SIgor Kudrin } 87cada5b88SIgor Kudrin 88cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64FDE) { 89cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 90cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 91cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 92cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 93cada5b88SIgor Kudrin /*Offset=*/0x3333abcdabcd, 94cada5b88SIgor Kudrin /*Length=*/0x4444abcdabcd, 95cada5b88SIgor Kudrin /*CIEPointer=*/0x1111abcdabcd, 96cada5b88SIgor Kudrin /*InitialLocation=*/0x5555abcdabcd, 97cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 98cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 99cada5b88SIgor Kudrin /*LSDAAddress=*/None, 100cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 101cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/false, 102cada5b88SIgor Kudrin "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE " 103cada5b88SIgor Kudrin "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde"); 104cada5b88SIgor Kudrin } 105cada5b88SIgor Kudrin 106cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64FDE) { 107cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 108cada5b88SIgor Kudrin /*Offset=*/0x1111ab9a000c, 109cada5b88SIgor Kudrin /*Length=*/0x20); 110cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 111cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 112cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd, 113cada5b88SIgor Kudrin /*CIEPointer=*/0x33abcd, 114cada5b88SIgor Kudrin /*InitialLocation=*/0x4444abcdabcd, 115cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 116cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 117cada5b88SIgor Kudrin /*LSDAAddress=*/None, 118cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 119cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/true, 120cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd 0033abcd FDE " 121cada5b88SIgor Kudrin "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde"); 122cada5b88SIgor Kudrin } 123cada5b88SIgor Kudrin 124bee8cdcaSGeorgii Rymar static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions, 1251e820e82SGeorgii Rymar Optional<uint64_t> Size = None) { 1261e820e82SGeorgii Rymar DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 1271e820e82SGeorgii Rymar /*AddressSize=*/8); 1281e820e82SGeorgii Rymar uint64_t Offset = 0; 1291e820e82SGeorgii Rymar const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size(); 1301e820e82SGeorgii Rymar return C.cfis().parse(Data, &Offset, EndOffset); 131bee8cdcaSGeorgii Rymar } 132bee8cdcaSGeorgii Rymar 133f8122d35SGreg Clayton static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) { 134f8122d35SGreg Clayton DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 135f8122d35SGreg Clayton /*AddressSize=*/8); 136f8122d35SGreg Clayton uint64_t Offset = 0; 137f8122d35SGreg Clayton return FDE.cfis().parse(Data, &Offset, Instructions.size()); 138f8122d35SGreg Clayton } 139f8122d35SGreg Clayton 140bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) { 141bee8cdcaSGeorgii Rymar llvm::DenseSet<uint8_t> ValidExtendedOpcodes = { 142bee8cdcaSGeorgii Rymar dwarf::DW_CFA_nop, 143bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc, 144bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset, 145bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore, 146bee8cdcaSGeorgii Rymar dwarf::DW_CFA_set_loc, 147bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc1, 148bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc2, 149bee8cdcaSGeorgii Rymar dwarf::DW_CFA_advance_loc4, 150bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset_extended, 151bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore_extended, 152bee8cdcaSGeorgii Rymar dwarf::DW_CFA_undefined, 153bee8cdcaSGeorgii Rymar dwarf::DW_CFA_same_value, 154bee8cdcaSGeorgii Rymar dwarf::DW_CFA_register, 155bee8cdcaSGeorgii Rymar dwarf::DW_CFA_remember_state, 156bee8cdcaSGeorgii Rymar dwarf::DW_CFA_restore_state, 157bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa, 158bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_register, 159bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, 160bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_expression, 161bee8cdcaSGeorgii Rymar dwarf::DW_CFA_expression, 162bee8cdcaSGeorgii Rymar dwarf::DW_CFA_offset_extended_sf, 163bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_sf, 164bee8cdcaSGeorgii Rymar dwarf::DW_CFA_def_cfa_offset_sf, 165bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset, 166bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset_sf, 167bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_expression, 168bee8cdcaSGeorgii Rymar dwarf::DW_CFA_MIPS_advance_loc8, 169bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_window_save, 170bee8cdcaSGeorgii Rymar dwarf::DW_CFA_AARCH64_negate_ra_state, 171bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_args_size}; 1721e820e82SGeorgii Rymar 1731e820e82SGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1741e820e82SGeorgii Rymar /*Offset=*/0x0, 1751e820e82SGeorgii Rymar /*Length=*/0xff); 1761e820e82SGeorgii Rymar 177bee8cdcaSGeorgii Rymar // See DWARF standard v3, section 7.23: low 6 bits are used to encode an 178bee8cdcaSGeorgii Rymar // extended opcode. 179bee8cdcaSGeorgii Rymar for (uint8_t Code = 0; Code <= 63; ++Code) { 180bee8cdcaSGeorgii Rymar if (ValidExtendedOpcodes.count(Code)) 181bee8cdcaSGeorgii Rymar continue; 182bee8cdcaSGeorgii Rymar 183bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, Code), 184bee8cdcaSGeorgii Rymar FailedWithMessage(("invalid extended CFI opcode 0x" + 185bee8cdcaSGeorgii Rymar Twine::utohexstr(Code)) 186bee8cdcaSGeorgii Rymar .str() 187bee8cdcaSGeorgii Rymar .c_str())); 188bee8cdcaSGeorgii Rymar } 189bee8cdcaSGeorgii Rymar } 190bee8cdcaSGeorgii Rymar 191bee8cdcaSGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed. 192bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) { 193bee8cdcaSGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 194bee8cdcaSGeorgii Rymar /*Offset=*/0x0, 195bee8cdcaSGeorgii Rymar /*Length=*/0xff); 196bee8cdcaSGeorgii Rymar 1971e820e82SGeorgii Rymar // Having an empty instructions list is fine. 198bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 1991e820e82SGeorgii Rymar 2001e820e82SGeorgii Rymar // Unable to read an opcode, because the instructions list is empty, but we 2011e820e82SGeorgii Rymar // say to the parser that it is not. 2021e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 203bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {}, /*Size=*/1), 2041e820e82SGeorgii Rymar FailedWithMessage( 2051e820e82SGeorgii Rymar "unexpected end of data at offset 0x0 while reading [0x0, 0x1)")); 2061e820e82SGeorgii Rymar 2071e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_offset instruction. 2081e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 209bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_offset}), 2101e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2111e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2121e820e82SGeorgii Rymar 2131e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_set_loc instruction. 2141e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 215bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}), 2161e820e82SGeorgii Rymar FailedWithMessage( 2171e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x9)")); 2181e820e82SGeorgii Rymar 2191e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc1 instruction. 2201e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 221bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}), 2221e820e82SGeorgii Rymar FailedWithMessage( 2231e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x2)")); 2241e820e82SGeorgii Rymar 2251e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc2 instruction. 2261e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 227bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}), 2281e820e82SGeorgii Rymar FailedWithMessage( 2291e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x3)")); 2301e820e82SGeorgii Rymar 2311e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc4 instruction. 2321e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 233bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}), 2341e820e82SGeorgii Rymar FailedWithMessage( 2351e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x5)")); 2361e820e82SGeorgii Rymar 2371e820e82SGeorgii Rymar // A test for an instruction with a single ULEB128 operand. 2381e820e82SGeorgii Rymar auto CheckOp_ULEB128 = [&](uint8_t Inst) { 2391e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 240bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2411e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2421e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2431e820e82SGeorgii Rymar }; 2441e820e82SGeorgii Rymar 2451e820e82SGeorgii Rymar for (uint8_t Inst : 2461e820e82SGeorgii Rymar {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined, 2471e820e82SGeorgii Rymar dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register, 2481e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size}) 2491e820e82SGeorgii Rymar CheckOp_ULEB128(Inst); 2501e820e82SGeorgii Rymar 2511e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction. 2521e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 253bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}), 2541e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2551e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2561e820e82SGeorgii Rymar 2571e820e82SGeorgii Rymar // A test for an instruction with two ULEB128 operands. 2581e820e82SGeorgii Rymar auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) { 2591e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 260bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2611e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2621e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2631e820e82SGeorgii Rymar 2641e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 265bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2661e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2671e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2681e820e82SGeorgii Rymar }; 2691e820e82SGeorgii Rymar 2701e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register, 2711e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_val_offset}) 2721e820e82SGeorgii Rymar CheckOp_ULEB128_ULEB128(Inst); 2731e820e82SGeorgii Rymar 2741e820e82SGeorgii Rymar // A test for an instruction with two operands: ULEB128, SLEB128. 2751e820e82SGeorgii Rymar auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) { 2761e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 277bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2781e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2791e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2801e820e82SGeorgii Rymar 2811e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 282bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2831e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2841e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2851e820e82SGeorgii Rymar }; 2861e820e82SGeorgii Rymar 2871e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended_sf, 2881e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_sf, dwarf::DW_CFA_val_offset_sf}) 2891e820e82SGeorgii Rymar CheckOp_ULEB128_SLEB128(Inst); 2901e820e82SGeorgii Rymar 2911e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_expression instruction. 2921e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 293bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}), 2941e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2951e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2961e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 297bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 2981e820e82SGeorgii Rymar /*expression length=*/0x1}), 2991e820e82SGeorgii Rymar FailedWithMessage( 3001e820e82SGeorgii Rymar "unexpected end of data at offset 0x2 while reading [0x2, 0x3)")); 3011e820e82SGeorgii Rymar // The DW_CFA_def_cfa_expression can contain a zero length expression. 302bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 3031e820e82SGeorgii Rymar /*ExprLen=*/0}), 3041e820e82SGeorgii Rymar Succeeded()); 3051e820e82SGeorgii Rymar 3061e820e82SGeorgii Rymar // A test for an instruction with three operands: ULEB128, expression length 3071e820e82SGeorgii Rymar // (ULEB128) and expression bytes. 3081e820e82SGeorgii Rymar auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) { 3091e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 310bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst}), 3111e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 3121e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3131e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 314bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 3151e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 3161e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3171e820e82SGeorgii Rymar // A zero length expression is fine 318bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst, 3191e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/0}), 3201e820e82SGeorgii Rymar Succeeded()); 3211e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 322bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, 3231e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/1}), 3241e820e82SGeorgii Rymar FailedWithMessage( 3251e820e82SGeorgii Rymar "unexpected end of data at offset 0x3 while reading [0x3, 0x4)")); 3261e820e82SGeorgii Rymar }; 3271e820e82SGeorgii Rymar 3281e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression}) 3291e820e82SGeorgii Rymar CheckOp_ULEB128_Expr(Inst); 3301e820e82SGeorgii Rymar } 3311e820e82SGeorgii Rymar 332f8122d35SGreg Clayton void expectDumpResult(const dwarf::UnwindLocation &Loc, 333f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 334f8122d35SGreg Clayton std::string Output; 335f8122d35SGreg Clayton raw_string_ostream OS(Output); 336f8122d35SGreg Clayton OS << Loc; 337f8122d35SGreg Clayton OS.flush(); 338f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 339f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 340f8122d35SGreg Clayton } 341f8122d35SGreg Clayton 342f8122d35SGreg Clayton TEST(DWARFDebugFrame, DumpUnwindLocations) { 343f8122d35SGreg Clayton // Test constructing unwind locations and dumping each kind. 344f8122d35SGreg Clayton constexpr int32_t PlusOff = 8; 345f8122d35SGreg Clayton constexpr int32_t MinusOff = -8; 346*a1a3fdcdSGreg Clayton constexpr uint8_t RegNum = 12; 347f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified"); 348f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined"); 349f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createSame(), "same"); 350f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff), 351f8122d35SGreg Clayton "CFA+8"); 352f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff), 353f8122d35SGreg Clayton "CFA-8"); 354f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff), 355f8122d35SGreg Clayton "[CFA+8]"); 356f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff), 357f8122d35SGreg Clayton "[CFA-8]"); 358f8122d35SGreg Clayton 359f8122d35SGreg Clayton expectDumpResult( 360f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff), 361f8122d35SGreg Clayton "reg12+8"); 362f8122d35SGreg Clayton expectDumpResult( 363f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff), 364f8122d35SGreg Clayton "reg12-8"); 365f8122d35SGreg Clayton expectDumpResult( 366f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff), 367f8122d35SGreg Clayton "[reg12+8]"); 368f8122d35SGreg Clayton expectDumpResult( 369f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff), 370f8122d35SGreg Clayton "[reg12-8]"); 371f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12"); 372f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32"); 373f8122d35SGreg Clayton } 374f8122d35SGreg Clayton 375f8122d35SGreg Clayton void expectDumpResult(const dwarf::RegisterLocations &Locs, 376f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 377f8122d35SGreg Clayton std::string Output; 378f8122d35SGreg Clayton raw_string_ostream OS(Output); 379f8122d35SGreg Clayton OS << Locs; 380f8122d35SGreg Clayton OS.flush(); 381f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 382f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 383f8122d35SGreg Clayton } 384f8122d35SGreg Clayton 385f8122d35SGreg Clayton TEST(DWARFDebugFrame, RegisterLocations) { 386f8122d35SGreg Clayton // Test the functionality of the RegisterLocations class. 387f8122d35SGreg Clayton dwarf::RegisterLocations Locs; 388f8122d35SGreg Clayton expectDumpResult(Locs, ""); 389f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 390f8122d35SGreg Clayton // Set a register location for reg12 to unspecified and verify it dumps 391f8122d35SGreg Clayton // correctly. 392f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified()); 393f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 394f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=unspecified"); 395f8122d35SGreg Clayton 396f8122d35SGreg Clayton // Replace the register location for reg12 to "same" and verify it dumps 397f8122d35SGreg Clayton // correctly after it is modified 398f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame()); 399f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 400f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=same"); 401f8122d35SGreg Clayton 402f8122d35SGreg Clayton // Remove the register location for reg12 verify it dumps correctly after it 403f8122d35SGreg Clayton // is removed. 404f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 405f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 406f8122d35SGreg Clayton expectDumpResult(Locs, ""); 407f8122d35SGreg Clayton 408f8122d35SGreg Clayton // Verify multiple registers added to the list dump correctly. 409f8122d35SGreg Clayton auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4); 410f8122d35SGreg Clayton auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8); 411f8122d35SGreg Clayton auto Reg14Loc = dwarf::UnwindLocation::createSame(); 412f8122d35SGreg Clayton Locs.setRegisterLocation(12, Reg12Loc); 413f8122d35SGreg Clayton Locs.setRegisterLocation(13, Reg13Loc); 414f8122d35SGreg Clayton Locs.setRegisterLocation(14, Reg14Loc); 415f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 416f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same"); 417f8122d35SGreg Clayton 418f8122d35SGreg Clayton // Verify RegisterLocations::getRegisterLocation() works as expected. 419f8122d35SGreg Clayton Optional<dwarf::UnwindLocation> OptionalLoc; 420f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(0); 421f8122d35SGreg Clayton EXPECT_FALSE(OptionalLoc.hasValue()); 422f8122d35SGreg Clayton 423f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(12); 424f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 425f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg12Loc); 426f8122d35SGreg Clayton 427f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(13); 428f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 429f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg13Loc); 430f8122d35SGreg Clayton 431f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(14); 432f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 433f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg14Loc); 434f8122d35SGreg Clayton 435f8122d35SGreg Clayton // Verify registers are correctly removed when multiple exist in the list. 436f8122d35SGreg Clayton Locs.removeRegisterLocation(13); 437f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(13).hasValue()); 438f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 439f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg14=same"); 440f8122d35SGreg Clayton Locs.removeRegisterLocation(14); 441f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(14).hasValue()); 442f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 443f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4]"); 444f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 445f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(12).hasValue()); 446f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 447f8122d35SGreg Clayton expectDumpResult(Locs, ""); 448f8122d35SGreg Clayton } 449f8122d35SGreg Clayton 450f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 451f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 452f8122d35SGreg Clayton /*Offset=*/0x0, 453f8122d35SGreg Clayton /*Length=*/0xff); 454f8122d35SGreg Clayton 455f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 456f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 457f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 458f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 459f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 460f8122d35SGreg Clayton /*AddressRange=*/0x1000, 461f8122d35SGreg Clayton /*Cie=*/&TestCIE, 462f8122d35SGreg Clayton /*LSDAAddress=*/None, 463f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 464f8122d35SGreg Clayton 465f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 466f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 467f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 468f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 469f8122d35SGreg Clayton Succeeded()); 470f8122d35SGreg Clayton 471f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 472f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 473f8122d35SGreg Clayton // Here we encode two DW_CFA_set_loc opcodes: 474f8122d35SGreg Clayton // DW_CFA_set_loc(0x1100) 475f8122d35SGreg Clayton // DW_CFA_set_loc(0x1000) 476f8122d35SGreg Clayton // These opcodes cause a new row to be appended to the rows in a UnwindTable 477f8122d35SGreg Clayton // and the resulting rows are not in ascending address order and should cause 478f8122d35SGreg Clayton // a state machine error. 479f8122d35SGreg Clayton EXPECT_THAT_ERROR( 480f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 481f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 482f8122d35SGreg Clayton Succeeded()); 483f8122d35SGreg Clayton 484f8122d35SGreg Clayton // Verify we catch state machine error. 485f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 486f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 487f8122d35SGreg Clayton FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 488f8122d35SGreg Clayton " must be greater than the current row " 489f8122d35SGreg Clayton "address 0x1100")); 490f8122d35SGreg Clayton } 491f8122d35SGreg Clayton 492f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 493f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 494f8122d35SGreg Clayton /*Offset=*/0x0, 495f8122d35SGreg Clayton /*Length=*/0xff); 496f8122d35SGreg Clayton 497f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 498f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 499f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 500f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 501f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 502f8122d35SGreg Clayton /*AddressRange=*/0x1000, 503f8122d35SGreg Clayton /*Cie=*/&TestCIE, 504f8122d35SGreg Clayton /*LSDAAddress=*/None, 505f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 506f8122d35SGreg Clayton 507f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 508f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 509f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 510f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 511f8122d35SGreg Clayton Succeeded()); 512f8122d35SGreg Clayton 513f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 514f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 515f8122d35SGreg Clayton // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 516f8122d35SGreg Clayton // DW_CFA_remember_state, and an error should be returned. 517f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 518f8122d35SGreg Clayton Succeeded()); 519f8122d35SGreg Clayton 520f8122d35SGreg Clayton // Verify we catch state machine error. 521f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 522f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 523f8122d35SGreg Clayton FailedWithMessage("DW_CFA_restore_state without a matching " 524f8122d35SGreg Clayton "previous DW_CFA_remember_state")); 525f8122d35SGreg Clayton } 526f8122d35SGreg Clayton 527f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 528f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 529f8122d35SGreg Clayton /*Offset=*/0x0, 530f8122d35SGreg Clayton /*Length=*/0xff); 531f8122d35SGreg Clayton 532f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 533f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 534f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 535f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 536f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 537f8122d35SGreg Clayton /*AddressRange=*/0x1000, 538f8122d35SGreg Clayton /*Cie=*/&TestCIE, 539f8122d35SGreg Clayton /*LSDAAddress=*/None, 540f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 541f8122d35SGreg Clayton 542f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 543f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 544f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 545f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 546f8122d35SGreg Clayton Succeeded()); 547f8122d35SGreg Clayton 548f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 549f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 550f8122d35SGreg Clayton // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 551f8122d35SGreg Clayton // found any documentation that describes what this does after some brief 552f8122d35SGreg Clayton // searching. 553f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 554f8122d35SGreg Clayton Succeeded()); 555f8122d35SGreg Clayton 556f8122d35SGreg Clayton // Verify we catch state machine error. 557f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 558f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 559f8122d35SGreg Clayton FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 560f8122d35SGreg Clayton "architecture x86_64")); 561f8122d35SGreg Clayton } 562f8122d35SGreg Clayton 563f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 564f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 565f8122d35SGreg Clayton /*Offset=*/0x0, 566f8122d35SGreg Clayton /*Length=*/0xff); 567f8122d35SGreg Clayton 568f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 569f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 570f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 571f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 572f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 573f8122d35SGreg Clayton /*AddressRange=*/0x1000, 574f8122d35SGreg Clayton /*Cie=*/&TestCIE, 575f8122d35SGreg Clayton /*LSDAAddress=*/None, 576f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 577f8122d35SGreg Clayton 578f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 579f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 580f8122d35SGreg Clayton // error back. 581f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 582f8122d35SGreg Clayton 583f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 584f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 585f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 586f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 587f8122d35SGreg Clayton // cause an error. 588f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 589f8122d35SGreg Clayton Succeeded()); 590f8122d35SGreg Clayton 591f8122d35SGreg Clayton // Verify we catch state machine error. 592f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 593f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 594f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 595f8122d35SGreg Clayton "rule was not RegPlusOffset")); 596f8122d35SGreg Clayton } 597f8122d35SGreg Clayton 598f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 599f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 600f8122d35SGreg Clayton /*Offset=*/0x0, 601f8122d35SGreg Clayton /*Length=*/0xff); 602f8122d35SGreg Clayton 603f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 604f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 605f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 606f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 607f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 608f8122d35SGreg Clayton /*AddressRange=*/0x1000, 609f8122d35SGreg Clayton /*Cie=*/&TestCIE, 610f8122d35SGreg Clayton /*LSDAAddress=*/None, 611f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 612f8122d35SGreg Clayton 613f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 614f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 615f8122d35SGreg Clayton // appropriate error back. 616f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 617f8122d35SGreg Clayton 618f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 619f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 620f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 621f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 622f8122d35SGreg Clayton // cause an error. 623f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 624f8122d35SGreg Clayton Succeeded()); 625f8122d35SGreg Clayton 626f8122d35SGreg Clayton // Verify we catch state machine error. 627f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 628f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 629f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 630f8122d35SGreg Clayton "rule was not RegPlusOffset")); 631f8122d35SGreg Clayton } 632f8122d35SGreg Clayton 633f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 634f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 635f8122d35SGreg Clayton /*Offset=*/0x0, 636f8122d35SGreg Clayton /*Length=*/0xff); 637f8122d35SGreg Clayton 638f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 639f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 640f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 641f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 642f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 643f8122d35SGreg Clayton /*AddressRange=*/0x1000, 644f8122d35SGreg Clayton /*Cie=*/&TestCIE, 645f8122d35SGreg Clayton /*LSDAAddress=*/None, 646f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 647f8122d35SGreg Clayton 648f8122d35SGreg Clayton // Make a CIE that has only defines the CFA register with no offset. Some 649f8122d35SGreg Clayton // architectures do this and we must ensure that we set the CFA value to be 650f8122d35SGreg Clayton // equal to that register with no offset. 651f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 652f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 653f8122d35SGreg Clayton Succeeded()); 654f8122d35SGreg Clayton 655f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 656f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 657f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 658f8122d35SGreg Clayton // our CIE didn't define the CFA in terms of a register plus offset, so this 659f8122d35SGreg Clayton // should cause an error. 660f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 661f8122d35SGreg Clayton 662f8122d35SGreg Clayton // Verify we catch state machine error. 663f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 664f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 665f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 666f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 667f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 668f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getCFAValue(), 669f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 670f8122d35SGreg Clayton } 671f8122d35SGreg Clayton 672f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 673f8122d35SGreg Clayton // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 674f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 675f8122d35SGreg Clayton /*Offset=*/0x0, 676f8122d35SGreg Clayton /*Length=*/0xff); 677f8122d35SGreg Clayton 678f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 679f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 680f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 681f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 682f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 683f8122d35SGreg Clayton /*AddressRange=*/0x1000, 684f8122d35SGreg Clayton /*Cie=*/&TestCIE, 685f8122d35SGreg Clayton /*LSDAAddress=*/None, 686f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 687f8122d35SGreg Clayton 688f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 689f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 690f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 691f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 692f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 693f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 694f8122d35SGreg Clayton 695f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 696f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 697f8122d35SGreg Clayton Succeeded()); 698f8122d35SGreg Clayton 699f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 700f8122d35SGreg Clayton // row pushing opcodes. This will verify that all opcodes that should create 701f8122d35SGreg Clayton // a row are correctly working. Each opcode will push a row prior to 702f8122d35SGreg Clayton // advancing the address, and then a row will be automatically pushed at the 703f8122d35SGreg Clayton // end of the parsing, so we should end up with 6 rows starting at address 704f8122d35SGreg Clayton // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 705f8122d35SGreg Clayton // from the CIE. 706f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 707f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc1, 708f8122d35SGreg Clayton 4, 709f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc2, 710f8122d35SGreg Clayton 4, 711f8122d35SGreg Clayton 0, 712f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc4, 713f8122d35SGreg Clayton 4, 714f8122d35SGreg Clayton 0, 715f8122d35SGreg Clayton 0, 716f8122d35SGreg Clayton 0, 717f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 718f8122d35SGreg Clayton 0x14, 719f8122d35SGreg Clayton 0x10, 720f8122d35SGreg Clayton 0, 721f8122d35SGreg Clayton 0, 722f8122d35SGreg Clayton 0, 723f8122d35SGreg Clayton 0, 724f8122d35SGreg Clayton 0, 725f8122d35SGreg Clayton 0}), 726f8122d35SGreg Clayton Succeeded()); 727f8122d35SGreg Clayton 728f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 729f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 730f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 731f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 732f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 733f8122d35SGreg Clayton 734f8122d35SGreg Clayton // Verify we catch state machine error. 735f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 736f8122d35SGreg Clayton ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 737f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 738f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 6u); 739f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 740f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 741f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 742f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 743f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 744f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 745f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 746f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 747f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 748f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 749f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 750f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 751f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 752f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 753f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 754f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 755f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 756f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 757f8122d35SGreg Clayton } 758f8122d35SGreg Clayton 759f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 760f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 761f8122d35SGreg Clayton // machine. 762f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 763f8122d35SGreg Clayton /*Offset=*/0x0, 764f8122d35SGreg Clayton /*Length=*/0xff); 765f8122d35SGreg Clayton 766f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 767f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 768f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 769f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 770f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 771f8122d35SGreg Clayton /*AddressRange=*/0x1000, 772f8122d35SGreg Clayton /*Cie=*/&TestCIE, 773f8122d35SGreg Clayton /*LSDAAddress=*/None, 774f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 775f8122d35SGreg Clayton 776f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 777f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 778f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 779f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 780f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 781f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 782f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 783f8122d35SGreg Clayton 784f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 785f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 786f8122d35SGreg Clayton Succeeded()); 787f8122d35SGreg Clayton 788f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 789f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 790f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 791f8122d35SGreg Clayton // two rows: 792f8122d35SGreg Clayton // - one with Reg = [CFA-8] 793f8122d35SGreg Clayton // - one with Reg = InReg 794f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 795f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 796f8122d35SGreg Clayton dwarf::DW_CFA_restore | Reg}), 797f8122d35SGreg Clayton Succeeded()); 798f8122d35SGreg Clayton 799f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 800f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 801f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 802f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 803f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 804f8122d35SGreg Clayton 805f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 806f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 807f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 808f8122d35SGreg Clayton 809f8122d35SGreg Clayton // Verify we catch state machine error. 810f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 811f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 812f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 813f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 814f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 815f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 816f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 817f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 818f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 819f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 820f8122d35SGreg Clayton } 821f8122d35SGreg Clayton 822f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 823f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 824f8122d35SGreg Clayton // machine. 825f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 826f8122d35SGreg Clayton /*Offset=*/0x0, 827f8122d35SGreg Clayton /*Length=*/0xff); 828f8122d35SGreg Clayton 829f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 830f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 831f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 832f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 833f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 834f8122d35SGreg Clayton /*AddressRange=*/0x1000, 835f8122d35SGreg Clayton /*Cie=*/&TestCIE, 836f8122d35SGreg Clayton /*LSDAAddress=*/None, 837f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 838f8122d35SGreg Clayton 839f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 840f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 841f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 842f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 843f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 844f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 845f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 846f8122d35SGreg Clayton 847f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 848f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 849f8122d35SGreg Clayton Succeeded()); 850f8122d35SGreg Clayton 851f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 852f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 853f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 854f8122d35SGreg Clayton // end up with two rows: 855f8122d35SGreg Clayton // - one with Reg = [CFA-8] 856f8122d35SGreg Clayton // - one with Reg = InReg 857f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 858f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 859f8122d35SGreg Clayton dwarf::DW_CFA_restore_extended, Reg}), 860f8122d35SGreg Clayton Succeeded()); 861f8122d35SGreg Clayton 862f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 863f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 864f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 865f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 866f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 867f8122d35SGreg Clayton 868f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 869f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 870f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 871f8122d35SGreg Clayton 872f8122d35SGreg Clayton // Verify we catch state machine error. 873f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 874f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 875f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 876f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 877f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 878f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 879f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 880f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 881f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 882f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 883f8122d35SGreg Clayton } 884f8122d35SGreg Clayton 885f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 886f8122d35SGreg Clayton // Test that DW_CFA_offset, DW_CFA_offset_extended and 887f8122d35SGreg Clayton // DW_CFA_offset_extended_sf work as expected when parsed in the state 888f8122d35SGreg Clayton // machine. 889f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 890f8122d35SGreg Clayton /*Offset=*/0x0, 891f8122d35SGreg Clayton /*Length=*/0xff); 892f8122d35SGreg Clayton 893f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 894f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 895f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 896f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 897f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 898f8122d35SGreg Clayton /*AddressRange=*/0x1000, 899f8122d35SGreg Clayton /*Cie=*/&TestCIE, 900f8122d35SGreg Clayton /*LSDAAddress=*/None, 901f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 902f8122d35SGreg Clayton 903f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 904f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 905f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 906f8122d35SGreg Clayton Succeeded()); 907f8122d35SGreg Clayton 908f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 909f8122d35SGreg Clayton // unwind rules for the follwing registers: 910f8122d35SGreg Clayton // Reg1 = [CFA-8] 911f8122d35SGreg Clayton // Reg2 = [CFA-16] 912f8122d35SGreg Clayton // Reg3 = [CFA+8] 913*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 914*a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 915*a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 916f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 917f8122d35SGreg Clayton EXPECT_THAT_ERROR( 918f8122d35SGreg Clayton parseCFI(TestFDE, 919f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 920f8122d35SGreg Clayton Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 921f8122d35SGreg Clayton Succeeded()); 922f8122d35SGreg Clayton 923f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 924f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 925f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 926f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 927f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 928f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 929f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 930f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 931f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 932f8122d35SGreg Clayton 933f8122d35SGreg Clayton // Verify we catch state machine error. 934f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 935f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 936f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 937f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 938f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 939f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 940f8122d35SGreg Clayton } 941f8122d35SGreg Clayton 942f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 943f8122d35SGreg Clayton // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 944f8122d35SGreg Clayton // parsed in the state machine. 945f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 946f8122d35SGreg Clayton /*Offset=*/0x0, 947f8122d35SGreg Clayton /*Length=*/0xff); 948f8122d35SGreg Clayton 949f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 950f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 951f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 952f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 953f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 954f8122d35SGreg Clayton /*AddressRange=*/0x1000, 955f8122d35SGreg Clayton /*Cie=*/&TestCIE, 956f8122d35SGreg Clayton /*LSDAAddress=*/None, 957f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 958f8122d35SGreg Clayton 959f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 960f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 961f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 962f8122d35SGreg Clayton Succeeded()); 963f8122d35SGreg Clayton 964f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 965f8122d35SGreg Clayton // unwind rules for the follwing registers: 966f8122d35SGreg Clayton // Reg1 = [CFA-8] 967f8122d35SGreg Clayton // Reg2 = [CFA-16] 968f8122d35SGreg Clayton // Reg3 = [CFA+8] 969*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 970*a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 971f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 972f8122d35SGreg Clayton EXPECT_THAT_ERROR( 973f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 974f8122d35SGreg Clayton dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 975f8122d35SGreg Clayton Succeeded()); 976f8122d35SGreg Clayton 977f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 978f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 979f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 980f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 981f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 982f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 983f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 984f8122d35SGreg Clayton 985f8122d35SGreg Clayton // Verify we catch state machine error. 986f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 987f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 988f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 989f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 990f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 991f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 992f8122d35SGreg Clayton } 993f8122d35SGreg Clayton 994f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 995f8122d35SGreg Clayton // Test that DW_CFA_nop works as expected when parsed in the state machine. 996f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 997f8122d35SGreg Clayton /*Offset=*/0x0, 998f8122d35SGreg Clayton /*Length=*/0xff); 999f8122d35SGreg Clayton 1000f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1001f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1002f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1003f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1004f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1005f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1006f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1007f8122d35SGreg Clayton /*LSDAAddress=*/None, 1008f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1009f8122d35SGreg Clayton 1010f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1011f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1012f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1013f8122d35SGreg Clayton Succeeded()); 1014f8122d35SGreg Clayton 1015f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1016f8122d35SGreg Clayton // unwind rules for the follwing registers: 1017f8122d35SGreg Clayton // Reg1 = [CFA-8] 1018f8122d35SGreg Clayton // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1019*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1020f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1021f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1022f8122d35SGreg Clayton Succeeded()); 1023f8122d35SGreg Clayton 1024f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1025f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1026f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1027f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1028f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1029f8122d35SGreg Clayton 1030f8122d35SGreg Clayton // Verify we catch state machine error. 1031f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1032f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1033f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1034f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1035f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1036f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1037f8122d35SGreg Clayton } 1038f8122d35SGreg Clayton 1039f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1040f8122d35SGreg Clayton // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1041f8122d35SGreg Clayton // when parsed in the state machine. 1042f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1043f8122d35SGreg Clayton /*Offset=*/0x0, 1044f8122d35SGreg Clayton /*Length=*/0xff); 1045f8122d35SGreg Clayton 1046f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1047f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1048f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1049f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1050f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1051f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1052f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1053f8122d35SGreg Clayton /*LSDAAddress=*/None, 1054f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1055f8122d35SGreg Clayton 1056f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1057f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1058f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1059f8122d35SGreg Clayton Succeeded()); 1060f8122d35SGreg Clayton 1061f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1062f8122d35SGreg Clayton // follwing rows: 1063f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=[CFA-8] 1064f8122d35SGreg Clayton // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1065f8122d35SGreg Clayton // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1066f8122d35SGreg Clayton // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1067f8122d35SGreg Clayton // 0x1010: CFA=reg12+32: Reg1=[CFA-8] 1068f8122d35SGreg Clayton // This state machine will: 1069f8122d35SGreg Clayton // - set Reg1 location 1070f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1071f8122d35SGreg Clayton // - remember the state 1072f8122d35SGreg Clayton // - set Reg2 location 1073f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1074f8122d35SGreg Clayton // - remember the state 1075f8122d35SGreg Clayton // - set Reg3 location 1076f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1077f8122d35SGreg Clayton // - remember the state where Reg1 and Reg2 were set 1078f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1079f8122d35SGreg Clayton // - remember the state where only Reg1 was set 1080f8122d35SGreg Clayton // - push a row (automatically at the end of instruction parsing) 1081f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1082*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1083*a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1084*a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 1085f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1086f8122d35SGreg Clayton parseCFI(TestFDE, 1087f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1088f8122d35SGreg Clayton dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1089f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1090f8122d35SGreg Clayton dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1091f8122d35SGreg Clayton dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1092f8122d35SGreg Clayton dwarf::DW_CFA_restore_state}), 1093f8122d35SGreg Clayton Succeeded()); 1094f8122d35SGreg Clayton 1095f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1096f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1097f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 1098f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 1099f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1100f8122d35SGreg Clayton 1101f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 1102f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1103f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1104f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1105f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1106f8122d35SGreg Clayton 1107f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs3; 1108f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1109f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1110f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1111f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1112f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1113f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 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(), 5u); 1120f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1121f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1122f8122d35SGreg Clayton 1123f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1124f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1125f8122d35SGreg Clayton 1126f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1127f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1128f8122d35SGreg Clayton 1129f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1130f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1131f8122d35SGreg Clayton 1132f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1133f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1134f8122d35SGreg Clayton } 1135f8122d35SGreg Clayton 1136f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1137f8122d35SGreg Clayton // Test that DW_CFA_undefined works as expected when parsed in the state 1138f8122d35SGreg Clayton // machine. 1139f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1140f8122d35SGreg Clayton /*Offset=*/0x0, 1141f8122d35SGreg Clayton /*Length=*/0xff); 1142f8122d35SGreg Clayton 1143f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1144f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1145f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1146f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1147f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1148f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1149f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1150f8122d35SGreg Clayton /*LSDAAddress=*/None, 1151f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1152f8122d35SGreg Clayton 1153f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1154f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1155f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1156f8122d35SGreg Clayton Succeeded()); 1157f8122d35SGreg Clayton 1158f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1159f8122d35SGreg Clayton // follwing rows: 1160f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=undefined 1161f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1162*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1163f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1164f8122d35SGreg Clayton Succeeded()); 1165f8122d35SGreg Clayton 1166f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1167f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1168f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1169f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, 1170f8122d35SGreg Clayton dwarf::UnwindLocation::createUndefined()); 1171f8122d35SGreg Clayton 1172f8122d35SGreg Clayton // Verify we catch state machine error. 1173f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1174f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1175f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1176f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1177f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1178f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1179f8122d35SGreg Clayton } 1180f8122d35SGreg Clayton 1181f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1182f8122d35SGreg Clayton // Test that DW_CFA_same_value works as expected when parsed in the state 1183f8122d35SGreg Clayton // machine. 1184f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1185f8122d35SGreg Clayton /*Offset=*/0x0, 1186f8122d35SGreg Clayton /*Length=*/0xff); 1187f8122d35SGreg Clayton 1188f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1189f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1190f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1191f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1192f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1193f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1194f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1195f8122d35SGreg Clayton /*LSDAAddress=*/None, 1196f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1197f8122d35SGreg Clayton 1198f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1199f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1200f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1201f8122d35SGreg Clayton Succeeded()); 1202f8122d35SGreg Clayton 1203f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1204f8122d35SGreg Clayton // follwing rows: 1205f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1206f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1207*a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1208f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1209f8122d35SGreg Clayton Succeeded()); 1210f8122d35SGreg Clayton 1211f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1212f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1213f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1214f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1215f8122d35SGreg Clayton 1216f8122d35SGreg Clayton // Verify we catch state machine error. 1217f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1218f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1219f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1220f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1221f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1222f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1223f8122d35SGreg Clayton } 1224f8122d35SGreg Clayton 1225f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1226f8122d35SGreg Clayton // Test that DW_CFA_register works as expected when parsed in the state 1227f8122d35SGreg Clayton // machine. 1228f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1229f8122d35SGreg Clayton /*Offset=*/0x0, 1230f8122d35SGreg Clayton /*Length=*/0xff); 1231f8122d35SGreg Clayton 1232f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1233f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1234f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1235f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1236f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1237f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1238f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1239f8122d35SGreg Clayton /*LSDAAddress=*/None, 1240f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1241f8122d35SGreg Clayton 1242f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1243f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1244f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1245f8122d35SGreg Clayton Succeeded()); 1246f8122d35SGreg Clayton 1247f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1248f8122d35SGreg Clayton // follwing rows: 1249f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1250f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1251f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1252f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1253f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1254f8122d35SGreg Clayton Succeeded()); 1255f8122d35SGreg Clayton 1256f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1257f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1258f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1259f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1260f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1261f8122d35SGreg Clayton 1262f8122d35SGreg Clayton // Verify we catch state machine error. 1263f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1264f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1265f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1266f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1267f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1268f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1269f8122d35SGreg Clayton } 1270f8122d35SGreg Clayton 1271f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1272f8122d35SGreg Clayton // Test that DW_CFA_expression works as expected when parsed in the state 1273f8122d35SGreg Clayton // machine. 1274f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1275f8122d35SGreg Clayton /*Offset=*/0x0, 1276f8122d35SGreg Clayton /*Length=*/0xff); 1277f8122d35SGreg Clayton 1278f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1279f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1280f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1281f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1282f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1283f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1284f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1285f8122d35SGreg Clayton /*LSDAAddress=*/None, 1286f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1287f8122d35SGreg Clayton 1288f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1289f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1290f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1291f8122d35SGreg Clayton Succeeded()); 1292f8122d35SGreg Clayton 1293f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1294f8122d35SGreg Clayton // follwing rows: 1295f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1296f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1297f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1298f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1299f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1300f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1301f8122d35SGreg Clayton 1302f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1303f8122d35SGreg Clayton 1304f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1305f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1306f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1307f8122d35SGreg Clayton 1308f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1309f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1310f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1311f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1312f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1313f8122d35SGreg Clayton 1314f8122d35SGreg Clayton // Verify we catch state machine error. 1315f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1316f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1317f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1318f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1319f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1320f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1321f8122d35SGreg Clayton } 1322f8122d35SGreg Clayton 1323f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1324f8122d35SGreg Clayton // Test that DW_CFA_val_expression works as expected when parsed in the state 1325f8122d35SGreg Clayton // machine. 1326f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1327f8122d35SGreg Clayton /*Offset=*/0x0, 1328f8122d35SGreg Clayton /*Length=*/0xff); 1329f8122d35SGreg Clayton 1330f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1331f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1332f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1333f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1334f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1335f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1336f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1337f8122d35SGreg Clayton /*LSDAAddress=*/None, 1338f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1339f8122d35SGreg Clayton 1340f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1341f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1342f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1343f8122d35SGreg Clayton Succeeded()); 1344f8122d35SGreg Clayton 1345f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1346f8122d35SGreg Clayton // follwing rows: 1347f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1348f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1349f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1350f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1351f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1352f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1353f8122d35SGreg Clayton 1354f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), 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 1360f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1361f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1362f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1363f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1364f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1365f8122d35SGreg Clayton 1366f8122d35SGreg Clayton // Verify we catch state machine error. 1367f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1368f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1369f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1370f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1371f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1372f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1373f8122d35SGreg Clayton } 1374f8122d35SGreg Clayton 1375f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1376f8122d35SGreg Clayton // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1377f8122d35SGreg Clayton // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1378f8122d35SGreg Clayton // parsed in the state machine. 1379f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1380f8122d35SGreg Clayton /*Offset=*/0x0, 1381f8122d35SGreg Clayton /*Length=*/0xff); 1382f8122d35SGreg Clayton 1383f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1384f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1385f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1386f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1387f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1388f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1389f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1390f8122d35SGreg Clayton /*LSDAAddress=*/None, 1391f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1392f8122d35SGreg Clayton 1393f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1394f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1395f8122d35SGreg Clayton constexpr uint8_t CFAReg1 = 12; 1396f8122d35SGreg Clayton constexpr uint8_t CFAOff1 = 32; 1397f8122d35SGreg Clayton constexpr uint8_t CFAReg2 = 13; 1398f8122d35SGreg Clayton constexpr uint8_t CFAOff2 = 48; 1399f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1400f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1401f8122d35SGreg Clayton 1402f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1403f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 1404f8122d35SGreg Clayton Succeeded()); 1405f8122d35SGreg Clayton 1406f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 1407f8122d35SGreg Clayton // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1408f8122d35SGreg Clayton // create a row are correctly working. 1409f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1410f8122d35SGreg Clayton parseCFI( 1411f8122d35SGreg Clayton TestFDE, 1412f8122d35SGreg Clayton { 1413f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1414f8122d35SGreg Clayton CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1415f8122d35SGreg Clayton dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1416f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1417f8122d35SGreg Clayton 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1418f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1419f8122d35SGreg Clayton 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1420f8122d35SGreg Clayton }), 1421f8122d35SGreg Clayton Succeeded()); 1422f8122d35SGreg Clayton 1423f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1424f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1425f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1426f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1427f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1428f8122d35SGreg Clayton 1429f8122d35SGreg Clayton // Verify we catch state machine error. 1430f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1431f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1432f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1433f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1434f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1435f8122d35SGreg Clayton EXPECT_EQ( 1436f8122d35SGreg Clayton Rows[0].getCFAValue(), 1437f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1438f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1439f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1440f8122d35SGreg Clayton 1441f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1442f8122d35SGreg Clayton EXPECT_EQ( 1443f8122d35SGreg Clayton Rows[1].getCFAValue(), 1444f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1445f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1446f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1447f8122d35SGreg Clayton 1448f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1449f8122d35SGreg Clayton EXPECT_EQ( 1450f8122d35SGreg Clayton Rows[2].getCFAValue(), 1451f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1452f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1453f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1454f8122d35SGreg Clayton 1455f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1456f8122d35SGreg Clayton EXPECT_EQ( 1457f8122d35SGreg Clayton Rows[3].getCFAValue(), 1458f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1459f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1460f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1461f8122d35SGreg Clayton 1462f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1463f8122d35SGreg Clayton EXPECT_EQ( 1464f8122d35SGreg Clayton Rows[4].getCFAValue(), 1465f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1466f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1467f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1468f8122d35SGreg Clayton } 1469f8122d35SGreg Clayton 1470cada5b88SIgor Kudrin } // end anonymous namespace 1471