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; 346a1a3fdcdSGreg 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 450*223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when 451*223852d7SRamNalamothu // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty. 452*223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows) { 453*223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 454*223852d7SRamNalamothu /*Offset=*/0x0, 455*223852d7SRamNalamothu /*Length=*/0xff); 456*223852d7SRamNalamothu 457*223852d7SRamNalamothu // Having an empty instructions list is fine. 458*223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 459*223852d7SRamNalamothu EXPECT_TRUE(TestCIE.cfis().empty()); 460*223852d7SRamNalamothu 461*223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 462*223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 463*223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 464*223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 465*223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 466*223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 467*223852d7SRamNalamothu 468*223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 469*223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 470*223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 471*223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 472*223852d7SRamNalamothu /*InitialLocation=*/0x1000, 473*223852d7SRamNalamothu /*AddressRange=*/0x1000, 474*223852d7SRamNalamothu /*Cie=*/&TestCIE, 475*223852d7SRamNalamothu /*LSDAAddress=*/None, 476*223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 477*223852d7SRamNalamothu 478*223852d7SRamNalamothu // Having an empty instructions list is fine. 479*223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 480*223852d7SRamNalamothu EXPECT_TRUE(TestFDE.cfis().empty()); 481*223852d7SRamNalamothu 482*223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 483*223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 484*223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 485*223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 486*223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 487*223852d7SRamNalamothu } 488*223852d7SRamNalamothu 489*223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs 490*223852d7SRamNalamothu // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions. 491*223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) { 492*223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 493*223852d7SRamNalamothu /*Offset=*/0x0, 494*223852d7SRamNalamothu /*Length=*/0xff); 495*223852d7SRamNalamothu 496*223852d7SRamNalamothu // Make a CIE that has only DW_CFA_nop instructions. 497*223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded()); 498*223852d7SRamNalamothu EXPECT_TRUE(!TestCIE.cfis().empty()); 499*223852d7SRamNalamothu 500*223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 501*223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 502*223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 503*223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 504*223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 505*223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 506*223852d7SRamNalamothu 507*223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 508*223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 509*223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 510*223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 511*223852d7SRamNalamothu /*InitialLocation=*/0x1000, 512*223852d7SRamNalamothu /*AddressRange=*/0x1000, 513*223852d7SRamNalamothu /*Cie=*/&TestCIE, 514*223852d7SRamNalamothu /*LSDAAddress=*/None, 515*223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 516*223852d7SRamNalamothu 517*223852d7SRamNalamothu // Make an FDE that has only DW_CFA_nop instructions. 518*223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded()); 519*223852d7SRamNalamothu EXPECT_TRUE(!TestFDE.cfis().empty()); 520*223852d7SRamNalamothu 521*223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 522*223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 523*223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 524*223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 525*223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 526*223852d7SRamNalamothu } 527*223852d7SRamNalamothu 528f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 529f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 530f8122d35SGreg Clayton /*Offset=*/0x0, 531f8122d35SGreg Clayton /*Length=*/0xff); 532f8122d35SGreg Clayton 533f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 534f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 535f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 536f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 537f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 538f8122d35SGreg Clayton /*AddressRange=*/0x1000, 539f8122d35SGreg Clayton /*Cie=*/&TestCIE, 540f8122d35SGreg Clayton /*LSDAAddress=*/None, 541f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 542f8122d35SGreg Clayton 543f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 544f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 545f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 546f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 547f8122d35SGreg Clayton Succeeded()); 548f8122d35SGreg Clayton 549f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 550f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 551f8122d35SGreg Clayton // Here we encode two DW_CFA_set_loc opcodes: 552f8122d35SGreg Clayton // DW_CFA_set_loc(0x1100) 553f8122d35SGreg Clayton // DW_CFA_set_loc(0x1000) 554f8122d35SGreg Clayton // These opcodes cause a new row to be appended to the rows in a UnwindTable 555f8122d35SGreg Clayton // and the resulting rows are not in ascending address order and should cause 556f8122d35SGreg Clayton // a state machine error. 557f8122d35SGreg Clayton EXPECT_THAT_ERROR( 558f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 559f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 560f8122d35SGreg Clayton Succeeded()); 561f8122d35SGreg Clayton 562f8122d35SGreg Clayton // Verify we catch state machine error. 563f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 564f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 565f8122d35SGreg Clayton FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 566f8122d35SGreg Clayton " must be greater than the current row " 567f8122d35SGreg Clayton "address 0x1100")); 568f8122d35SGreg Clayton } 569f8122d35SGreg Clayton 570f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 571f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 572f8122d35SGreg Clayton /*Offset=*/0x0, 573f8122d35SGreg Clayton /*Length=*/0xff); 574f8122d35SGreg Clayton 575f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 576f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 577f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 578f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 579f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 580f8122d35SGreg Clayton /*AddressRange=*/0x1000, 581f8122d35SGreg Clayton /*Cie=*/&TestCIE, 582f8122d35SGreg Clayton /*LSDAAddress=*/None, 583f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 584f8122d35SGreg Clayton 585f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 586f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 587f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 588f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 589f8122d35SGreg Clayton Succeeded()); 590f8122d35SGreg Clayton 591f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 592f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 593f8122d35SGreg Clayton // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 594f8122d35SGreg Clayton // DW_CFA_remember_state, and an error should be returned. 595f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 596f8122d35SGreg Clayton Succeeded()); 597f8122d35SGreg Clayton 598f8122d35SGreg Clayton // Verify we catch state machine error. 599f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 600f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 601f8122d35SGreg Clayton FailedWithMessage("DW_CFA_restore_state without a matching " 602f8122d35SGreg Clayton "previous DW_CFA_remember_state")); 603f8122d35SGreg Clayton } 604f8122d35SGreg Clayton 605f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 606f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 607f8122d35SGreg Clayton /*Offset=*/0x0, 608f8122d35SGreg Clayton /*Length=*/0xff); 609f8122d35SGreg Clayton 610f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 611f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 612f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 613f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 614f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 615f8122d35SGreg Clayton /*AddressRange=*/0x1000, 616f8122d35SGreg Clayton /*Cie=*/&TestCIE, 617f8122d35SGreg Clayton /*LSDAAddress=*/None, 618f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 619f8122d35SGreg Clayton 620f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 621f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 622f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 623f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 624f8122d35SGreg Clayton Succeeded()); 625f8122d35SGreg Clayton 626f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 627f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 628f8122d35SGreg Clayton // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 629f8122d35SGreg Clayton // found any documentation that describes what this does after some brief 630f8122d35SGreg Clayton // searching. 631f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 632f8122d35SGreg Clayton Succeeded()); 633f8122d35SGreg Clayton 634f8122d35SGreg Clayton // Verify we catch state machine error. 635f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 636f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 637f8122d35SGreg Clayton FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 638f8122d35SGreg Clayton "architecture x86_64")); 639f8122d35SGreg Clayton } 640f8122d35SGreg Clayton 641f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 642f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 643f8122d35SGreg Clayton /*Offset=*/0x0, 644f8122d35SGreg Clayton /*Length=*/0xff); 645f8122d35SGreg Clayton 646f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 647f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 648f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 649f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 650f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 651f8122d35SGreg Clayton /*AddressRange=*/0x1000, 652f8122d35SGreg Clayton /*Cie=*/&TestCIE, 653f8122d35SGreg Clayton /*LSDAAddress=*/None, 654f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 655f8122d35SGreg Clayton 656f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 657f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 658f8122d35SGreg Clayton // error back. 659f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 660f8122d35SGreg Clayton 661f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 662f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 663f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 664f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 665f8122d35SGreg Clayton // cause an error. 666f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 667f8122d35SGreg Clayton Succeeded()); 668f8122d35SGreg Clayton 669f8122d35SGreg Clayton // Verify we catch state machine error. 670f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 671f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 672f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 673f8122d35SGreg Clayton "rule was not RegPlusOffset")); 674f8122d35SGreg Clayton } 675f8122d35SGreg Clayton 676f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 677f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 678f8122d35SGreg Clayton /*Offset=*/0x0, 679f8122d35SGreg Clayton /*Length=*/0xff); 680f8122d35SGreg Clayton 681f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 682f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 683f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 684f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 685f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 686f8122d35SGreg Clayton /*AddressRange=*/0x1000, 687f8122d35SGreg Clayton /*Cie=*/&TestCIE, 688f8122d35SGreg Clayton /*LSDAAddress=*/None, 689f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 690f8122d35SGreg Clayton 691f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 692f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 693f8122d35SGreg Clayton // appropriate error back. 694f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 695f8122d35SGreg Clayton 696f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 697f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 698f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 699f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 700f8122d35SGreg Clayton // cause an error. 701f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 702f8122d35SGreg Clayton Succeeded()); 703f8122d35SGreg Clayton 704f8122d35SGreg Clayton // Verify we catch state machine error. 705f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 706f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 707f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 708f8122d35SGreg Clayton "rule was not RegPlusOffset")); 709f8122d35SGreg Clayton } 710f8122d35SGreg Clayton 711f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 712f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 713f8122d35SGreg Clayton /*Offset=*/0x0, 714f8122d35SGreg Clayton /*Length=*/0xff); 715f8122d35SGreg Clayton 716f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 717f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 718f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 719f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 720f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 721f8122d35SGreg Clayton /*AddressRange=*/0x1000, 722f8122d35SGreg Clayton /*Cie=*/&TestCIE, 723f8122d35SGreg Clayton /*LSDAAddress=*/None, 724f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 725f8122d35SGreg Clayton 726f8122d35SGreg Clayton // Make a CIE that has only defines the CFA register with no offset. Some 727f8122d35SGreg Clayton // architectures do this and we must ensure that we set the CFA value to be 728f8122d35SGreg Clayton // equal to that register with no offset. 729f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 730f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 731f8122d35SGreg Clayton Succeeded()); 732f8122d35SGreg Clayton 733f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 734f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 735f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 736f8122d35SGreg Clayton // our CIE didn't define the CFA in terms of a register plus offset, so this 737f8122d35SGreg Clayton // should cause an error. 738f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 739f8122d35SGreg Clayton 740f8122d35SGreg Clayton // Verify we catch state machine error. 741f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 742f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 743f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 744f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 745f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 746f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getCFAValue(), 747f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 748f8122d35SGreg Clayton } 749f8122d35SGreg Clayton 750f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 751f8122d35SGreg Clayton // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 752f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 753f8122d35SGreg Clayton /*Offset=*/0x0, 754f8122d35SGreg Clayton /*Length=*/0xff); 755f8122d35SGreg Clayton 756f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 757f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 758f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 759f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 760f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 761f8122d35SGreg Clayton /*AddressRange=*/0x1000, 762f8122d35SGreg Clayton /*Cie=*/&TestCIE, 763f8122d35SGreg Clayton /*LSDAAddress=*/None, 764f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 765f8122d35SGreg Clayton 766f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 767f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 768f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 769f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 770f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 771f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 772f8122d35SGreg Clayton 773f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 774f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 775f8122d35SGreg Clayton Succeeded()); 776f8122d35SGreg Clayton 777f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 778f8122d35SGreg Clayton // row pushing opcodes. This will verify that all opcodes that should create 779f8122d35SGreg Clayton // a row are correctly working. Each opcode will push a row prior to 780f8122d35SGreg Clayton // advancing the address, and then a row will be automatically pushed at the 781f8122d35SGreg Clayton // end of the parsing, so we should end up with 6 rows starting at address 782f8122d35SGreg Clayton // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 783f8122d35SGreg Clayton // from the CIE. 784f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 785f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc1, 786f8122d35SGreg Clayton 4, 787f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc2, 788f8122d35SGreg Clayton 4, 789f8122d35SGreg Clayton 0, 790f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc4, 791f8122d35SGreg Clayton 4, 792f8122d35SGreg Clayton 0, 793f8122d35SGreg Clayton 0, 794f8122d35SGreg Clayton 0, 795f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 796f8122d35SGreg Clayton 0x14, 797f8122d35SGreg Clayton 0x10, 798f8122d35SGreg Clayton 0, 799f8122d35SGreg Clayton 0, 800f8122d35SGreg Clayton 0, 801f8122d35SGreg Clayton 0, 802f8122d35SGreg Clayton 0, 803f8122d35SGreg Clayton 0}), 804f8122d35SGreg Clayton Succeeded()); 805f8122d35SGreg Clayton 806f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 807f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 808f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 809f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 810f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 811f8122d35SGreg Clayton 812f8122d35SGreg Clayton // Verify we catch state machine error. 813f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 814f8122d35SGreg Clayton ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 815f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 816f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 6u); 817f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 818f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 819f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 820f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 821f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 822f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 823f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 824f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 825f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 826f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 827f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 828f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 829f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 830f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 831f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 832f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 833f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 834f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 835f8122d35SGreg Clayton } 836f8122d35SGreg Clayton 837f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 838f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 839f8122d35SGreg Clayton // machine. 840f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 841f8122d35SGreg Clayton /*Offset=*/0x0, 842f8122d35SGreg Clayton /*Length=*/0xff); 843f8122d35SGreg Clayton 844f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 845f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 846f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 847f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 848f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 849f8122d35SGreg Clayton /*AddressRange=*/0x1000, 850f8122d35SGreg Clayton /*Cie=*/&TestCIE, 851f8122d35SGreg Clayton /*LSDAAddress=*/None, 852f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 853f8122d35SGreg Clayton 854f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 855f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 856f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 857f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 858f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 859f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 860f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 861f8122d35SGreg Clayton 862f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 863f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 864f8122d35SGreg Clayton Succeeded()); 865f8122d35SGreg Clayton 866f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 867f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 868f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 869f8122d35SGreg Clayton // two rows: 870f8122d35SGreg Clayton // - one with Reg = [CFA-8] 871f8122d35SGreg Clayton // - one with Reg = InReg 872f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 873f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 874f8122d35SGreg Clayton dwarf::DW_CFA_restore | Reg}), 875f8122d35SGreg Clayton Succeeded()); 876f8122d35SGreg Clayton 877f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 878f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 879f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 880f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 881f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 882f8122d35SGreg Clayton 883f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 884f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 885f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 886f8122d35SGreg Clayton 887f8122d35SGreg Clayton // Verify we catch state machine error. 888f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 889f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 890f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 891f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 892f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 893f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 894f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 895f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 896f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 897f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 898f8122d35SGreg Clayton } 899f8122d35SGreg Clayton 900f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 901f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 902f8122d35SGreg Clayton // machine. 903f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 904f8122d35SGreg Clayton /*Offset=*/0x0, 905f8122d35SGreg Clayton /*Length=*/0xff); 906f8122d35SGreg Clayton 907f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 908f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 909f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 910f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 911f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 912f8122d35SGreg Clayton /*AddressRange=*/0x1000, 913f8122d35SGreg Clayton /*Cie=*/&TestCIE, 914f8122d35SGreg Clayton /*LSDAAddress=*/None, 915f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 916f8122d35SGreg Clayton 917f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 918f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 919f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 920f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 921f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 922f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 923f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 924f8122d35SGreg Clayton 925f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 926f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 927f8122d35SGreg Clayton Succeeded()); 928f8122d35SGreg Clayton 929f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 930f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 931f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 932f8122d35SGreg Clayton // end up with two rows: 933f8122d35SGreg Clayton // - one with Reg = [CFA-8] 934f8122d35SGreg Clayton // - one with Reg = InReg 935f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 936f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 937f8122d35SGreg Clayton dwarf::DW_CFA_restore_extended, Reg}), 938f8122d35SGreg Clayton Succeeded()); 939f8122d35SGreg Clayton 940f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 941f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 942f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 943f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 944f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 945f8122d35SGreg Clayton 946f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 947f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 948f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 949f8122d35SGreg Clayton 950f8122d35SGreg Clayton // Verify we catch state machine error. 951f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 952f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 953f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 954f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 955f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 956f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 957f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 958f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 959f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 960f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 961f8122d35SGreg Clayton } 962f8122d35SGreg Clayton 963f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 964f8122d35SGreg Clayton // Test that DW_CFA_offset, DW_CFA_offset_extended and 965f8122d35SGreg Clayton // DW_CFA_offset_extended_sf work as expected when parsed in the state 966f8122d35SGreg Clayton // machine. 967f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 968f8122d35SGreg Clayton /*Offset=*/0x0, 969f8122d35SGreg Clayton /*Length=*/0xff); 970f8122d35SGreg Clayton 971f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 972f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 973f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 974f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 975f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 976f8122d35SGreg Clayton /*AddressRange=*/0x1000, 977f8122d35SGreg Clayton /*Cie=*/&TestCIE, 978f8122d35SGreg Clayton /*LSDAAddress=*/None, 979f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 980f8122d35SGreg Clayton 981f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 982f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 983f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 984f8122d35SGreg Clayton Succeeded()); 985f8122d35SGreg Clayton 986f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 987f8122d35SGreg Clayton // unwind rules for the follwing registers: 988f8122d35SGreg Clayton // Reg1 = [CFA-8] 989f8122d35SGreg Clayton // Reg2 = [CFA-16] 990f8122d35SGreg Clayton // Reg3 = [CFA+8] 991a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 992a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 993a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 994f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 995f8122d35SGreg Clayton EXPECT_THAT_ERROR( 996f8122d35SGreg Clayton parseCFI(TestFDE, 997f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 998f8122d35SGreg Clayton Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 999f8122d35SGreg Clayton Succeeded()); 1000f8122d35SGreg Clayton 1001f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1002f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1003f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1004f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1005f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1006f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1007f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1008f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1009f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 1010f8122d35SGreg Clayton 1011f8122d35SGreg Clayton // Verify we catch state machine error. 1012f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1013f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1014f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1015f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1016f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1017f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1018f8122d35SGreg Clayton } 1019f8122d35SGreg Clayton 1020f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 1021f8122d35SGreg Clayton // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 1022f8122d35SGreg Clayton // parsed in the state machine. 1023f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1024f8122d35SGreg Clayton /*Offset=*/0x0, 1025f8122d35SGreg Clayton /*Length=*/0xff); 1026f8122d35SGreg Clayton 1027f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1028f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1029f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1030f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1031f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1032f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1033f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1034f8122d35SGreg Clayton /*LSDAAddress=*/None, 1035f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1036f8122d35SGreg Clayton 1037f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1038f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1039f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1040f8122d35SGreg Clayton Succeeded()); 1041f8122d35SGreg Clayton 1042f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1043f8122d35SGreg Clayton // unwind rules for the follwing registers: 1044f8122d35SGreg Clayton // Reg1 = [CFA-8] 1045f8122d35SGreg Clayton // Reg2 = [CFA-16] 1046f8122d35SGreg Clayton // Reg3 = [CFA+8] 1047a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1048a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1049f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 1050f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1051f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 1052f8122d35SGreg Clayton dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 1053f8122d35SGreg Clayton Succeeded()); 1054f8122d35SGreg Clayton 1055f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1056f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1057f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1058f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1059f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 1060f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1061f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 1062f8122d35SGreg Clayton 1063f8122d35SGreg Clayton // Verify we catch state machine error. 1064f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1065f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1066f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1067f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1068f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1069f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1070f8122d35SGreg Clayton } 1071f8122d35SGreg Clayton 1072f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 1073f8122d35SGreg Clayton // Test that DW_CFA_nop works as expected when parsed in the state machine. 1074f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1075f8122d35SGreg Clayton /*Offset=*/0x0, 1076f8122d35SGreg Clayton /*Length=*/0xff); 1077f8122d35SGreg Clayton 1078f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1079f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1080f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1081f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1082f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1083f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1084f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1085f8122d35SGreg Clayton /*LSDAAddress=*/None, 1086f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1087f8122d35SGreg Clayton 1088f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1089f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1090f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1091f8122d35SGreg Clayton Succeeded()); 1092f8122d35SGreg Clayton 1093f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1094f8122d35SGreg Clayton // unwind rules for the follwing registers: 1095f8122d35SGreg Clayton // Reg1 = [CFA-8] 1096f8122d35SGreg Clayton // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1097a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1098f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1099f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1100f8122d35SGreg Clayton Succeeded()); 1101f8122d35SGreg Clayton 1102f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1103f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1104f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1105f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1106f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1107f8122d35SGreg Clayton 1108f8122d35SGreg Clayton // Verify we catch state machine error. 1109f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1110f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1111f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1112f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1113f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1114f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1115f8122d35SGreg Clayton } 1116f8122d35SGreg Clayton 1117f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1118f8122d35SGreg Clayton // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1119f8122d35SGreg Clayton // when parsed in the state machine. 1120f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1121f8122d35SGreg Clayton /*Offset=*/0x0, 1122f8122d35SGreg Clayton /*Length=*/0xff); 1123f8122d35SGreg Clayton 1124f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1125f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1126f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1127f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1128f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1129f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1130f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1131f8122d35SGreg Clayton /*LSDAAddress=*/None, 1132f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1133f8122d35SGreg Clayton 1134f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1135f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1136f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1137f8122d35SGreg Clayton Succeeded()); 1138f8122d35SGreg Clayton 1139f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1140f8122d35SGreg Clayton // follwing rows: 1141f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=[CFA-8] 1142f8122d35SGreg Clayton // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1143f8122d35SGreg Clayton // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1144f8122d35SGreg Clayton // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1145f8122d35SGreg Clayton // 0x1010: CFA=reg12+32: Reg1=[CFA-8] 1146f8122d35SGreg Clayton // This state machine will: 1147f8122d35SGreg Clayton // - set Reg1 location 1148f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1149f8122d35SGreg Clayton // - remember the state 1150f8122d35SGreg Clayton // - set Reg2 location 1151f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1152f8122d35SGreg Clayton // - remember the state 1153f8122d35SGreg Clayton // - set Reg3 location 1154f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1155f8122d35SGreg Clayton // - remember the state where Reg1 and Reg2 were set 1156f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1157f8122d35SGreg Clayton // - remember the state where only Reg1 was set 1158f8122d35SGreg Clayton // - push a row (automatically at the end of instruction parsing) 1159f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1160a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1161a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1162a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 1163f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1164f8122d35SGreg Clayton parseCFI(TestFDE, 1165f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1166f8122d35SGreg Clayton dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1167f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1168f8122d35SGreg Clayton dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1169f8122d35SGreg Clayton dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1170f8122d35SGreg Clayton dwarf::DW_CFA_restore_state}), 1171f8122d35SGreg Clayton Succeeded()); 1172f8122d35SGreg Clayton 1173f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1174f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1175f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 1176f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 1177f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1178f8122d35SGreg Clayton 1179f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 1180f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1181f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1182f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1183f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1184f8122d35SGreg Clayton 1185f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs3; 1186f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1187f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1188f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1189f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1190f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1191f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 1192f8122d35SGreg Clayton 1193f8122d35SGreg Clayton // Verify we catch state machine error. 1194f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1195f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1196f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1197f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1198f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1199f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1200f8122d35SGreg Clayton 1201f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1202f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1203f8122d35SGreg Clayton 1204f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1205f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1206f8122d35SGreg Clayton 1207f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1208f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1209f8122d35SGreg Clayton 1210f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1211f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1212f8122d35SGreg Clayton } 1213f8122d35SGreg Clayton 1214f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1215f8122d35SGreg Clayton // Test that DW_CFA_undefined works as expected when parsed in the state 1216f8122d35SGreg Clayton // machine. 1217f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1218f8122d35SGreg Clayton /*Offset=*/0x0, 1219f8122d35SGreg Clayton /*Length=*/0xff); 1220f8122d35SGreg Clayton 1221f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1222f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1223f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1224f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1225f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1226f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1227f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1228f8122d35SGreg Clayton /*LSDAAddress=*/None, 1229f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1230f8122d35SGreg Clayton 1231f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1232f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1233f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1234f8122d35SGreg Clayton Succeeded()); 1235f8122d35SGreg Clayton 1236f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1237f8122d35SGreg Clayton // follwing rows: 1238f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=undefined 1239f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1240a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1241f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1242f8122d35SGreg Clayton Succeeded()); 1243f8122d35SGreg Clayton 1244f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1245f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1246f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1247f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, 1248f8122d35SGreg Clayton dwarf::UnwindLocation::createUndefined()); 1249f8122d35SGreg Clayton 1250f8122d35SGreg Clayton // Verify we catch state machine error. 1251f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1252f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1253f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1254f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1255f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1256f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1257f8122d35SGreg Clayton } 1258f8122d35SGreg Clayton 1259f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1260f8122d35SGreg Clayton // Test that DW_CFA_same_value works as expected when parsed in the state 1261f8122d35SGreg Clayton // machine. 1262f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1263f8122d35SGreg Clayton /*Offset=*/0x0, 1264f8122d35SGreg Clayton /*Length=*/0xff); 1265f8122d35SGreg Clayton 1266f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1267f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1268f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1269f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1270f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1271f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1272f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1273f8122d35SGreg Clayton /*LSDAAddress=*/None, 1274f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1275f8122d35SGreg Clayton 1276f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1277f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1278f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1279f8122d35SGreg Clayton Succeeded()); 1280f8122d35SGreg Clayton 1281f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1282f8122d35SGreg Clayton // follwing rows: 1283f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1284f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1285a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1286f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1287f8122d35SGreg Clayton Succeeded()); 1288f8122d35SGreg Clayton 1289f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1290f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1291f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1292f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1293f8122d35SGreg Clayton 1294f8122d35SGreg Clayton // Verify we catch state machine error. 1295f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1296f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1297f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1298f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1299f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1300f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1301f8122d35SGreg Clayton } 1302f8122d35SGreg Clayton 1303f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1304f8122d35SGreg Clayton // Test that DW_CFA_register works as expected when parsed in the state 1305f8122d35SGreg Clayton // machine. 1306f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1307f8122d35SGreg Clayton /*Offset=*/0x0, 1308f8122d35SGreg Clayton /*Length=*/0xff); 1309f8122d35SGreg Clayton 1310f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1311f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1312f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1313f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1314f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1315f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1316f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1317f8122d35SGreg Clayton /*LSDAAddress=*/None, 1318f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1319f8122d35SGreg Clayton 1320f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1321f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1322f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1323f8122d35SGreg Clayton Succeeded()); 1324f8122d35SGreg Clayton 1325f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1326f8122d35SGreg Clayton // follwing rows: 1327f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1328f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1329f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1330f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1331f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1332f8122d35SGreg Clayton Succeeded()); 1333f8122d35SGreg Clayton 1334f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1335f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1336f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1337f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1338f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1339f8122d35SGreg Clayton 1340f8122d35SGreg Clayton // Verify we catch state machine error. 1341f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1342f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1343f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1344f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1345f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1346f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1347f8122d35SGreg Clayton } 1348f8122d35SGreg Clayton 1349f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1350f8122d35SGreg Clayton // Test that DW_CFA_expression works as expected when parsed in the state 1351f8122d35SGreg Clayton // machine. 1352f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1353f8122d35SGreg Clayton /*Offset=*/0x0, 1354f8122d35SGreg Clayton /*Length=*/0xff); 1355f8122d35SGreg Clayton 1356f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1357f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1358f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1359f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1360f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1361f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1362f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1363f8122d35SGreg Clayton /*LSDAAddress=*/None, 1364f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1365f8122d35SGreg Clayton 1366f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1367f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1368f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1369f8122d35SGreg Clayton Succeeded()); 1370f8122d35SGreg Clayton 1371f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1372f8122d35SGreg Clayton // follwing rows: 1373f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1374f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1375f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1376f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1377f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1378f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1379f8122d35SGreg Clayton 1380f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1381f8122d35SGreg Clayton 1382f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1383f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1384f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1385f8122d35SGreg Clayton 1386f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1387f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1388f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1389f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1390f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1391f8122d35SGreg Clayton 1392f8122d35SGreg Clayton // Verify we catch state machine error. 1393f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1394f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1395f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1396f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1397f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1398f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1399f8122d35SGreg Clayton } 1400f8122d35SGreg Clayton 1401f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1402f8122d35SGreg Clayton // Test that DW_CFA_val_expression works as expected when parsed in the state 1403f8122d35SGreg Clayton // machine. 1404f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1405f8122d35SGreg Clayton /*Offset=*/0x0, 1406f8122d35SGreg Clayton /*Length=*/0xff); 1407f8122d35SGreg Clayton 1408f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1409f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1410f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1411f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1412f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1413f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1414f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1415f8122d35SGreg Clayton /*LSDAAddress=*/None, 1416f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1417f8122d35SGreg Clayton 1418f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1419f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1420f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1421f8122d35SGreg Clayton Succeeded()); 1422f8122d35SGreg Clayton 1423f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1424f8122d35SGreg Clayton // follwing rows: 1425f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1426f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1427f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1428f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1429f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1430f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1431f8122d35SGreg Clayton 1432f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1433f8122d35SGreg Clayton 1434f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1435f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1436f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1437f8122d35SGreg Clayton 1438f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1439f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1440f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1441f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1442f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1443f8122d35SGreg Clayton 1444f8122d35SGreg Clayton // Verify we catch state machine error. 1445f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1446f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1447f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1448f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1449f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1450f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1451f8122d35SGreg Clayton } 1452f8122d35SGreg Clayton 1453f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1454f8122d35SGreg Clayton // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1455f8122d35SGreg Clayton // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1456f8122d35SGreg Clayton // parsed in the state machine. 1457f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1458f8122d35SGreg Clayton /*Offset=*/0x0, 1459f8122d35SGreg Clayton /*Length=*/0xff); 1460f8122d35SGreg Clayton 1461f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1462f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1463f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1464f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1465f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1466f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1467f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1468f8122d35SGreg Clayton /*LSDAAddress=*/None, 1469f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1470f8122d35SGreg Clayton 1471f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1472f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1473f8122d35SGreg Clayton constexpr uint8_t CFAReg1 = 12; 1474f8122d35SGreg Clayton constexpr uint8_t CFAOff1 = 32; 1475f8122d35SGreg Clayton constexpr uint8_t CFAReg2 = 13; 1476f8122d35SGreg Clayton constexpr uint8_t CFAOff2 = 48; 1477f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1478f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1479f8122d35SGreg Clayton 1480f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1481f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 1482f8122d35SGreg Clayton Succeeded()); 1483f8122d35SGreg Clayton 1484f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 1485f8122d35SGreg Clayton // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1486f8122d35SGreg Clayton // create a row are correctly working. 1487f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1488f8122d35SGreg Clayton parseCFI( 1489f8122d35SGreg Clayton TestFDE, 1490f8122d35SGreg Clayton { 1491f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1492f8122d35SGreg Clayton CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1493f8122d35SGreg Clayton dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1494f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1495f8122d35SGreg Clayton 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1496f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1497f8122d35SGreg Clayton 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1498f8122d35SGreg Clayton }), 1499f8122d35SGreg Clayton Succeeded()); 1500f8122d35SGreg Clayton 1501f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1502f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1503f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1504f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1505f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1506f8122d35SGreg Clayton 1507f8122d35SGreg Clayton // Verify we catch state machine error. 1508f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1509f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1510f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1511f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1512f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1513f8122d35SGreg Clayton EXPECT_EQ( 1514f8122d35SGreg Clayton Rows[0].getCFAValue(), 1515f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1516f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1517f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1518f8122d35SGreg Clayton 1519f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1520f8122d35SGreg Clayton EXPECT_EQ( 1521f8122d35SGreg Clayton Rows[1].getCFAValue(), 1522f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1523f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1524f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1525f8122d35SGreg Clayton 1526f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1527f8122d35SGreg Clayton EXPECT_EQ( 1528f8122d35SGreg Clayton Rows[2].getCFAValue(), 1529f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1530f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1531f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1532f8122d35SGreg Clayton 1533f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1534f8122d35SGreg Clayton EXPECT_EQ( 1535f8122d35SGreg Clayton Rows[3].getCFAValue(), 1536f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1537f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1538f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1539f8122d35SGreg Clayton 1540f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1541f8122d35SGreg Clayton EXPECT_EQ( 1542f8122d35SGreg Clayton Rows[4].getCFAValue(), 1543f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1544f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1545f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1546f8122d35SGreg Clayton } 1547f8122d35SGreg Clayton 1548cada5b88SIgor Kudrin } // end anonymous namespace 1549