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, 165*167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa, 166*167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, 167bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset, 168bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_offset_sf, 169bee8cdcaSGeorgii Rymar dwarf::DW_CFA_val_expression, 170bee8cdcaSGeorgii Rymar dwarf::DW_CFA_MIPS_advance_loc8, 171bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_window_save, 172bee8cdcaSGeorgii Rymar dwarf::DW_CFA_AARCH64_negate_ra_state, 173bee8cdcaSGeorgii Rymar dwarf::DW_CFA_GNU_args_size}; 1741e820e82SGeorgii Rymar 1751e820e82SGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1761e820e82SGeorgii Rymar /*Offset=*/0x0, 1771e820e82SGeorgii Rymar /*Length=*/0xff); 1781e820e82SGeorgii Rymar 179bee8cdcaSGeorgii Rymar // See DWARF standard v3, section 7.23: low 6 bits are used to encode an 180bee8cdcaSGeorgii Rymar // extended opcode. 181bee8cdcaSGeorgii Rymar for (uint8_t Code = 0; Code <= 63; ++Code) { 182bee8cdcaSGeorgii Rymar if (ValidExtendedOpcodes.count(Code)) 183bee8cdcaSGeorgii Rymar continue; 184bee8cdcaSGeorgii Rymar 185bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, Code), 186bee8cdcaSGeorgii Rymar FailedWithMessage(("invalid extended CFI opcode 0x" + 187bee8cdcaSGeorgii Rymar Twine::utohexstr(Code)) 188bee8cdcaSGeorgii Rymar .str() 189bee8cdcaSGeorgii Rymar .c_str())); 190bee8cdcaSGeorgii Rymar } 191bee8cdcaSGeorgii Rymar } 192bee8cdcaSGeorgii Rymar 193bee8cdcaSGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed. 194bee8cdcaSGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) { 195bee8cdcaSGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 196bee8cdcaSGeorgii Rymar /*Offset=*/0x0, 197bee8cdcaSGeorgii Rymar /*Length=*/0xff); 198bee8cdcaSGeorgii Rymar 1991e820e82SGeorgii Rymar // Having an empty instructions list is fine. 200bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 2011e820e82SGeorgii Rymar 2021e820e82SGeorgii Rymar // Unable to read an opcode, because the instructions list is empty, but we 2031e820e82SGeorgii Rymar // say to the parser that it is not. 2041e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 205bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {}, /*Size=*/1), 2061e820e82SGeorgii Rymar FailedWithMessage( 2071e820e82SGeorgii Rymar "unexpected end of data at offset 0x0 while reading [0x0, 0x1)")); 2081e820e82SGeorgii Rymar 2091e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_offset instruction. 2101e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 211bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_offset}), 2121e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2131e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2141e820e82SGeorgii Rymar 2151e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_set_loc instruction. 2161e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 217bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}), 2181e820e82SGeorgii Rymar FailedWithMessage( 2191e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x9)")); 2201e820e82SGeorgii Rymar 2211e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc1 instruction. 2221e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 223bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}), 2241e820e82SGeorgii Rymar FailedWithMessage( 2251e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x2)")); 2261e820e82SGeorgii Rymar 2271e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc2 instruction. 2281e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 229bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}), 2301e820e82SGeorgii Rymar FailedWithMessage( 2311e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x3)")); 2321e820e82SGeorgii Rymar 2331e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc4 instruction. 2341e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 235bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}), 2361e820e82SGeorgii Rymar FailedWithMessage( 2371e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x5)")); 2381e820e82SGeorgii Rymar 2391e820e82SGeorgii Rymar // A test for an instruction with a single ULEB128 operand. 2401e820e82SGeorgii Rymar auto CheckOp_ULEB128 = [&](uint8_t Inst) { 2411e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 242bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2431e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2441e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2451e820e82SGeorgii Rymar }; 2461e820e82SGeorgii Rymar 2471e820e82SGeorgii Rymar for (uint8_t Inst : 2481e820e82SGeorgii Rymar {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined, 2491e820e82SGeorgii Rymar dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register, 2501e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size}) 2511e820e82SGeorgii Rymar CheckOp_ULEB128(Inst); 2521e820e82SGeorgii Rymar 2531e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction. 2541e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 255bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}), 2561e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2571e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2581e820e82SGeorgii Rymar 2591e820e82SGeorgii Rymar // A test for an instruction with two ULEB128 operands. 2601e820e82SGeorgii Rymar auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) { 2611e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 262bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2631e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2641e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2651e820e82SGeorgii Rymar 2661e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 267bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2681e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2691e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2701e820e82SGeorgii Rymar }; 2711e820e82SGeorgii Rymar 2721e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register, 273*167e7afcSRamNalamothu dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa, 274*167e7afcSRamNalamothu dwarf::DW_CFA_val_offset}) 2751e820e82SGeorgii Rymar CheckOp_ULEB128_ULEB128(Inst); 2761e820e82SGeorgii Rymar 2771e820e82SGeorgii Rymar // A test for an instruction with two operands: ULEB128, SLEB128. 2781e820e82SGeorgii Rymar auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) { 2791e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 280bee8cdcaSGeorgii Rymar parseCFI(TestCIE, Inst), 2811e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2821e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 2831e820e82SGeorgii Rymar 2841e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 285bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 2861e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 2871e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 2881e820e82SGeorgii Rymar }; 2891e820e82SGeorgii Rymar 290*167e7afcSRamNalamothu for (uint8_t Inst : 291*167e7afcSRamNalamothu {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf, 292*167e7afcSRamNalamothu dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf}) 2931e820e82SGeorgii Rymar CheckOp_ULEB128_SLEB128(Inst); 2941e820e82SGeorgii Rymar 2951e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_expression instruction. 2961e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 297bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}), 2981e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 2991e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3001e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 301bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 3021e820e82SGeorgii Rymar /*expression length=*/0x1}), 3031e820e82SGeorgii Rymar FailedWithMessage( 3041e820e82SGeorgii Rymar "unexpected end of data at offset 0x2 while reading [0x2, 0x3)")); 3051e820e82SGeorgii Rymar // The DW_CFA_def_cfa_expression can contain a zero length expression. 306bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 3071e820e82SGeorgii Rymar /*ExprLen=*/0}), 3081e820e82SGeorgii Rymar Succeeded()); 3091e820e82SGeorgii Rymar 3101e820e82SGeorgii Rymar // A test for an instruction with three operands: ULEB128, expression length 3111e820e82SGeorgii Rymar // (ULEB128) and expression bytes. 3121e820e82SGeorgii Rymar auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) { 3131e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 314bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst}), 3151e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 3161e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3171e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 318bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, /*Op1=*/0}), 3191e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 3201e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 3211e820e82SGeorgii Rymar // A zero length expression is fine 322bee8cdcaSGeorgii Rymar EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst, 3231e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/0}), 3241e820e82SGeorgii Rymar Succeeded()); 3251e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 326bee8cdcaSGeorgii Rymar parseCFI(TestCIE, {Inst, 3271e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/1}), 3281e820e82SGeorgii Rymar FailedWithMessage( 3291e820e82SGeorgii Rymar "unexpected end of data at offset 0x3 while reading [0x3, 0x4)")); 3301e820e82SGeorgii Rymar }; 3311e820e82SGeorgii Rymar 3321e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression}) 3331e820e82SGeorgii Rymar CheckOp_ULEB128_Expr(Inst); 3341e820e82SGeorgii Rymar } 3351e820e82SGeorgii Rymar 336f8122d35SGreg Clayton void expectDumpResult(const dwarf::UnwindLocation &Loc, 337f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 338f8122d35SGreg Clayton std::string Output; 339f8122d35SGreg Clayton raw_string_ostream OS(Output); 340f8122d35SGreg Clayton OS << Loc; 341f8122d35SGreg Clayton OS.flush(); 342f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 343f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 344f8122d35SGreg Clayton } 345f8122d35SGreg Clayton 346f8122d35SGreg Clayton TEST(DWARFDebugFrame, DumpUnwindLocations) { 347f8122d35SGreg Clayton // Test constructing unwind locations and dumping each kind. 348f8122d35SGreg Clayton constexpr int32_t PlusOff = 8; 349f8122d35SGreg Clayton constexpr int32_t MinusOff = -8; 350a1a3fdcdSGreg Clayton constexpr uint8_t RegNum = 12; 351f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified"); 352f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined"); 353f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createSame(), "same"); 354f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff), 355f8122d35SGreg Clayton "CFA+8"); 356f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff), 357f8122d35SGreg Clayton "CFA-8"); 358f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff), 359f8122d35SGreg Clayton "[CFA+8]"); 360f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff), 361f8122d35SGreg Clayton "[CFA-8]"); 362f8122d35SGreg Clayton 363f8122d35SGreg Clayton expectDumpResult( 364f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff), 365f8122d35SGreg Clayton "reg12+8"); 366f8122d35SGreg Clayton expectDumpResult( 367f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff), 368f8122d35SGreg Clayton "reg12-8"); 369f8122d35SGreg Clayton expectDumpResult( 370f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff), 371f8122d35SGreg Clayton "[reg12+8]"); 372f8122d35SGreg Clayton expectDumpResult( 373f8122d35SGreg Clayton dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff), 374f8122d35SGreg Clayton "[reg12-8]"); 375f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12"); 376f8122d35SGreg Clayton expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32"); 377f8122d35SGreg Clayton } 378f8122d35SGreg Clayton 379f8122d35SGreg Clayton void expectDumpResult(const dwarf::RegisterLocations &Locs, 380f8122d35SGreg Clayton StringRef ExpectedFirstLine) { 381f8122d35SGreg Clayton std::string Output; 382f8122d35SGreg Clayton raw_string_ostream OS(Output); 383f8122d35SGreg Clayton OS << Locs; 384f8122d35SGreg Clayton OS.flush(); 385f8122d35SGreg Clayton StringRef FirstLine = StringRef(Output).split('\n').first; 386f8122d35SGreg Clayton EXPECT_EQ(FirstLine, ExpectedFirstLine); 387f8122d35SGreg Clayton } 388f8122d35SGreg Clayton 389f8122d35SGreg Clayton TEST(DWARFDebugFrame, RegisterLocations) { 390f8122d35SGreg Clayton // Test the functionality of the RegisterLocations class. 391f8122d35SGreg Clayton dwarf::RegisterLocations Locs; 392f8122d35SGreg Clayton expectDumpResult(Locs, ""); 393f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 394f8122d35SGreg Clayton // Set a register location for reg12 to unspecified and verify it dumps 395f8122d35SGreg Clayton // correctly. 396f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified()); 397f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 398f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=unspecified"); 399f8122d35SGreg Clayton 400f8122d35SGreg Clayton // Replace the register location for reg12 to "same" and verify it dumps 401f8122d35SGreg Clayton // correctly after it is modified 402f8122d35SGreg Clayton Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame()); 403f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 404f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=same"); 405f8122d35SGreg Clayton 406f8122d35SGreg Clayton // Remove the register location for reg12 verify it dumps correctly after it 407f8122d35SGreg Clayton // is removed. 408f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 409f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 410f8122d35SGreg Clayton expectDumpResult(Locs, ""); 411f8122d35SGreg Clayton 412f8122d35SGreg Clayton // Verify multiple registers added to the list dump correctly. 413f8122d35SGreg Clayton auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4); 414f8122d35SGreg Clayton auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8); 415f8122d35SGreg Clayton auto Reg14Loc = dwarf::UnwindLocation::createSame(); 416f8122d35SGreg Clayton Locs.setRegisterLocation(12, Reg12Loc); 417f8122d35SGreg Clayton Locs.setRegisterLocation(13, Reg13Loc); 418f8122d35SGreg Clayton Locs.setRegisterLocation(14, Reg14Loc); 419f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 420f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same"); 421f8122d35SGreg Clayton 422f8122d35SGreg Clayton // Verify RegisterLocations::getRegisterLocation() works as expected. 423f8122d35SGreg Clayton Optional<dwarf::UnwindLocation> OptionalLoc; 424f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(0); 425f8122d35SGreg Clayton EXPECT_FALSE(OptionalLoc.hasValue()); 426f8122d35SGreg Clayton 427f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(12); 428f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 429f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg12Loc); 430f8122d35SGreg Clayton 431f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(13); 432f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 433f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg13Loc); 434f8122d35SGreg Clayton 435f8122d35SGreg Clayton OptionalLoc = Locs.getRegisterLocation(14); 436f8122d35SGreg Clayton EXPECT_TRUE(OptionalLoc.hasValue()); 437f8122d35SGreg Clayton EXPECT_EQ(*OptionalLoc, Reg14Loc); 438f8122d35SGreg Clayton 439f8122d35SGreg Clayton // Verify registers are correctly removed when multiple exist in the list. 440f8122d35SGreg Clayton Locs.removeRegisterLocation(13); 441f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(13).hasValue()); 442f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 443f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4], reg14=same"); 444f8122d35SGreg Clayton Locs.removeRegisterLocation(14); 445f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(14).hasValue()); 446f8122d35SGreg Clayton EXPECT_TRUE(Locs.hasLocations()); 447f8122d35SGreg Clayton expectDumpResult(Locs, "reg12=[CFA+4]"); 448f8122d35SGreg Clayton Locs.removeRegisterLocation(12); 449f8122d35SGreg Clayton EXPECT_FALSE(Locs.getRegisterLocation(12).hasValue()); 450f8122d35SGreg Clayton EXPECT_FALSE(Locs.hasLocations()); 451f8122d35SGreg Clayton expectDumpResult(Locs, ""); 452f8122d35SGreg Clayton } 453f8122d35SGreg Clayton 454223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when 455223852d7SRamNalamothu // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty. 456223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows) { 457223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 458223852d7SRamNalamothu /*Offset=*/0x0, 459223852d7SRamNalamothu /*Length=*/0xff); 460223852d7SRamNalamothu 461223852d7SRamNalamothu // Having an empty instructions list is fine. 462223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 463223852d7SRamNalamothu EXPECT_TRUE(TestCIE.cfis().empty()); 464223852d7SRamNalamothu 465223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 466223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 467223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 468223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 469223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 470223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 471223852d7SRamNalamothu 472223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 473223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 474223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 475223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 476223852d7SRamNalamothu /*InitialLocation=*/0x1000, 477223852d7SRamNalamothu /*AddressRange=*/0x1000, 478223852d7SRamNalamothu /*Cie=*/&TestCIE, 479223852d7SRamNalamothu /*LSDAAddress=*/None, 480223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 481223852d7SRamNalamothu 482223852d7SRamNalamothu // Having an empty instructions list is fine. 483223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 484223852d7SRamNalamothu EXPECT_TRUE(TestFDE.cfis().empty()); 485223852d7SRamNalamothu 486223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 487223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 488223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 489223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 490223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 491223852d7SRamNalamothu } 492223852d7SRamNalamothu 493223852d7SRamNalamothu // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs 494223852d7SRamNalamothu // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions. 495223852d7SRamNalamothu TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) { 496223852d7SRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 497223852d7SRamNalamothu /*Offset=*/0x0, 498223852d7SRamNalamothu /*Length=*/0xff); 499223852d7SRamNalamothu 500223852d7SRamNalamothu // Make a CIE that has only DW_CFA_nop instructions. 501223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded()); 502223852d7SRamNalamothu EXPECT_TRUE(!TestCIE.cfis().empty()); 503223852d7SRamNalamothu 504223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 505223852d7SRamNalamothu // and empty rows are not added to CIE UnwindTable. 506223852d7SRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 507223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 508223852d7SRamNalamothu const size_t ExpectedNumOfRows = 0; 509223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 510223852d7SRamNalamothu 511223852d7SRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 512223852d7SRamNalamothu /*Offset=*/0x3333abcdabcd, 513223852d7SRamNalamothu /*Length=*/0x4444abcdabcd, 514223852d7SRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 515223852d7SRamNalamothu /*InitialLocation=*/0x1000, 516223852d7SRamNalamothu /*AddressRange=*/0x1000, 517223852d7SRamNalamothu /*Cie=*/&TestCIE, 518223852d7SRamNalamothu /*LSDAAddress=*/None, 519223852d7SRamNalamothu /*Arch=*/Triple::x86_64); 520223852d7SRamNalamothu 521223852d7SRamNalamothu // Make an FDE that has only DW_CFA_nop instructions. 522223852d7SRamNalamothu EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded()); 523223852d7SRamNalamothu EXPECT_TRUE(!TestFDE.cfis().empty()); 524223852d7SRamNalamothu 525223852d7SRamNalamothu // Verify dwarf::UnwindTable::create() won't result in errors and 526223852d7SRamNalamothu // and empty rows are not added to FDE UnwindTable. 527223852d7SRamNalamothu RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 528223852d7SRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 529223852d7SRamNalamothu EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 530223852d7SRamNalamothu } 531223852d7SRamNalamothu 532f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 533f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 534f8122d35SGreg Clayton /*Offset=*/0x0, 535f8122d35SGreg Clayton /*Length=*/0xff); 536f8122d35SGreg Clayton 537f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 538f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 539f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 540f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 541f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 542f8122d35SGreg Clayton /*AddressRange=*/0x1000, 543f8122d35SGreg Clayton /*Cie=*/&TestCIE, 544f8122d35SGreg Clayton /*LSDAAddress=*/None, 545f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 546f8122d35SGreg Clayton 547f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 548f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 549f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 550f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 551f8122d35SGreg Clayton Succeeded()); 552f8122d35SGreg Clayton 553f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 554f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 555f8122d35SGreg Clayton // Here we encode two DW_CFA_set_loc opcodes: 556f8122d35SGreg Clayton // DW_CFA_set_loc(0x1100) 557f8122d35SGreg Clayton // DW_CFA_set_loc(0x1000) 558f8122d35SGreg Clayton // These opcodes cause a new row to be appended to the rows in a UnwindTable 559f8122d35SGreg Clayton // and the resulting rows are not in ascending address order and should cause 560f8122d35SGreg Clayton // a state machine error. 561f8122d35SGreg Clayton EXPECT_THAT_ERROR( 562f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 563f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 564f8122d35SGreg Clayton Succeeded()); 565f8122d35SGreg Clayton 566f8122d35SGreg Clayton // Verify we catch state machine error. 567f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 568f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 569f8122d35SGreg Clayton FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 570f8122d35SGreg Clayton " must be greater than the current row " 571f8122d35SGreg Clayton "address 0x1100")); 572f8122d35SGreg Clayton } 573f8122d35SGreg Clayton 574f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 575f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 576f8122d35SGreg Clayton /*Offset=*/0x0, 577f8122d35SGreg Clayton /*Length=*/0xff); 578f8122d35SGreg Clayton 579f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 580f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 581f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 582f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 583f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 584f8122d35SGreg Clayton /*AddressRange=*/0x1000, 585f8122d35SGreg Clayton /*Cie=*/&TestCIE, 586f8122d35SGreg Clayton /*LSDAAddress=*/None, 587f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 588f8122d35SGreg Clayton 589f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 590f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 591f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 592f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 593f8122d35SGreg Clayton Succeeded()); 594f8122d35SGreg Clayton 595f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 596f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 597f8122d35SGreg Clayton // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 598f8122d35SGreg Clayton // DW_CFA_remember_state, and an error should be returned. 599f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 600f8122d35SGreg Clayton Succeeded()); 601f8122d35SGreg Clayton 602f8122d35SGreg Clayton // Verify we catch state machine error. 603f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 604f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 605f8122d35SGreg Clayton FailedWithMessage("DW_CFA_restore_state without a matching " 606f8122d35SGreg Clayton "previous DW_CFA_remember_state")); 607f8122d35SGreg Clayton } 608f8122d35SGreg Clayton 609f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 610f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 611f8122d35SGreg Clayton /*Offset=*/0x0, 612f8122d35SGreg Clayton /*Length=*/0xff); 613f8122d35SGreg Clayton 614f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 615f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 616f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 617f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 618f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 619f8122d35SGreg Clayton /*AddressRange=*/0x1000, 620f8122d35SGreg Clayton /*Cie=*/&TestCIE, 621f8122d35SGreg Clayton /*LSDAAddress=*/None, 622f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 623f8122d35SGreg Clayton 624f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition. 625f8122d35SGreg Clayton constexpr uint8_t Reg = 12; 626f8122d35SGreg Clayton constexpr uint8_t Offset = 32; 627f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 628f8122d35SGreg Clayton Succeeded()); 629f8122d35SGreg Clayton 630f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 631f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 632f8122d35SGreg Clayton // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 633f8122d35SGreg Clayton // found any documentation that describes what this does after some brief 634f8122d35SGreg Clayton // searching. 635f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 636f8122d35SGreg Clayton Succeeded()); 637f8122d35SGreg Clayton 638f8122d35SGreg Clayton // Verify we catch state machine error. 639f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 640f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 641f8122d35SGreg Clayton FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 642f8122d35SGreg Clayton "architecture x86_64")); 643f8122d35SGreg Clayton } 644f8122d35SGreg Clayton 645f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 646f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 647f8122d35SGreg Clayton /*Offset=*/0x0, 648f8122d35SGreg Clayton /*Length=*/0xff); 649f8122d35SGreg Clayton 650f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 651f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 652f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 653f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 654f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 655f8122d35SGreg Clayton /*AddressRange=*/0x1000, 656f8122d35SGreg Clayton /*Cie=*/&TestCIE, 657f8122d35SGreg Clayton /*LSDAAddress=*/None, 658f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 659f8122d35SGreg Clayton 660f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 661f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 662f8122d35SGreg Clayton // error back. 663f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 664f8122d35SGreg Clayton 665f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 666f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 667f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 668f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 669f8122d35SGreg Clayton // cause an error. 670f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 671f8122d35SGreg Clayton Succeeded()); 672f8122d35SGreg Clayton 673f8122d35SGreg Clayton // Verify we catch state machine error. 674f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 675f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 676f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 677f8122d35SGreg Clayton "rule was not RegPlusOffset")); 678f8122d35SGreg Clayton } 679f8122d35SGreg Clayton 680f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 681f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 682f8122d35SGreg Clayton /*Offset=*/0x0, 683f8122d35SGreg Clayton /*Length=*/0xff); 684f8122d35SGreg Clayton 685f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 686f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 687f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 688f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 689f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 690f8122d35SGreg Clayton /*AddressRange=*/0x1000, 691f8122d35SGreg Clayton /*Cie=*/&TestCIE, 692f8122d35SGreg Clayton /*LSDAAddress=*/None, 693f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 694f8122d35SGreg Clayton 695f8122d35SGreg Clayton // Make a CIE that has an invalid CFA definition. We do this so we can try 696f8122d35SGreg Clayton // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 697f8122d35SGreg Clayton // appropriate error back. 698f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 699f8122d35SGreg Clayton 700f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 701f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 702f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 703f8122d35SGreg Clayton // didn't define the CFA in terms of a register plus offset, so this should 704f8122d35SGreg Clayton // cause an error. 705f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 706f8122d35SGreg Clayton Succeeded()); 707f8122d35SGreg Clayton 708f8122d35SGreg Clayton // Verify we catch state machine error. 709f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 710f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), 711f8122d35SGreg Clayton FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 712f8122d35SGreg Clayton "rule was not RegPlusOffset")); 713f8122d35SGreg Clayton } 714f8122d35SGreg Clayton 715f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 716f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 717f8122d35SGreg Clayton /*Offset=*/0x0, 718f8122d35SGreg Clayton /*Length=*/0xff); 719f8122d35SGreg Clayton 720f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 721f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 722f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 723f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 724f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 725f8122d35SGreg Clayton /*AddressRange=*/0x1000, 726f8122d35SGreg Clayton /*Cie=*/&TestCIE, 727f8122d35SGreg Clayton /*LSDAAddress=*/None, 728f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 729f8122d35SGreg Clayton 730f8122d35SGreg Clayton // Make a CIE that has only defines the CFA register with no offset. Some 731f8122d35SGreg Clayton // architectures do this and we must ensure that we set the CFA value to be 732f8122d35SGreg Clayton // equal to that register with no offset. 733f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 734f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 735f8122d35SGreg Clayton Succeeded()); 736f8122d35SGreg Clayton 737f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that have valid 738f8122d35SGreg Clayton // syntax, but will cause an error when we parse them into a UnwindTable. 739f8122d35SGreg Clayton // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 740f8122d35SGreg Clayton // our CIE didn't define the CFA in terms of a register plus offset, so this 741f8122d35SGreg Clayton // should cause an error. 742f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 743f8122d35SGreg Clayton 744f8122d35SGreg Clayton // Verify we catch state machine error. 745f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 746f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 747f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 748f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 749f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 750f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getCFAValue(), 751f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 752f8122d35SGreg Clayton } 753f8122d35SGreg Clayton 754f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 755f8122d35SGreg Clayton // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 756f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 757f8122d35SGreg Clayton /*Offset=*/0x0, 758f8122d35SGreg Clayton /*Length=*/0xff); 759f8122d35SGreg Clayton 760f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 761f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 762f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 763f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 764f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 765f8122d35SGreg Clayton /*AddressRange=*/0x1000, 766f8122d35SGreg Clayton /*Cie=*/&TestCIE, 767f8122d35SGreg Clayton /*LSDAAddress=*/None, 768f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 769f8122d35SGreg Clayton 770f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 771f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 772f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 773f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 774f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 775f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 776f8122d35SGreg Clayton 777f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 778f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 779f8122d35SGreg Clayton Succeeded()); 780f8122d35SGreg Clayton 781f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 782f8122d35SGreg Clayton // row pushing opcodes. This will verify that all opcodes that should create 783f8122d35SGreg Clayton // a row are correctly working. Each opcode will push a row prior to 784f8122d35SGreg Clayton // advancing the address, and then a row will be automatically pushed at the 785f8122d35SGreg Clayton // end of the parsing, so we should end up with 6 rows starting at address 786f8122d35SGreg Clayton // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 787f8122d35SGreg Clayton // from the CIE. 788f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 789f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc1, 790f8122d35SGreg Clayton 4, 791f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc2, 792f8122d35SGreg Clayton 4, 793f8122d35SGreg Clayton 0, 794f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc4, 795f8122d35SGreg Clayton 4, 796f8122d35SGreg Clayton 0, 797f8122d35SGreg Clayton 0, 798f8122d35SGreg Clayton 0, 799f8122d35SGreg Clayton dwarf::DW_CFA_set_loc, 800f8122d35SGreg Clayton 0x14, 801f8122d35SGreg Clayton 0x10, 802f8122d35SGreg Clayton 0, 803f8122d35SGreg Clayton 0, 804f8122d35SGreg Clayton 0, 805f8122d35SGreg Clayton 0, 806f8122d35SGreg Clayton 0, 807f8122d35SGreg Clayton 0}), 808f8122d35SGreg Clayton Succeeded()); 809f8122d35SGreg Clayton 810f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 811f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 812f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 813f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 814f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 815f8122d35SGreg Clayton 816f8122d35SGreg Clayton // Verify we catch state machine error. 817f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 818f8122d35SGreg Clayton ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 819f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 820f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 6u); 821f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 822f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 823f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 824f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 825f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 826f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 827f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 828f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 829f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 830f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 831f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 832f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 833f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 834f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 835f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 836f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 837f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 838f8122d35SGreg Clayton EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 839f8122d35SGreg Clayton } 840f8122d35SGreg Clayton 841f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 842f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 843f8122d35SGreg Clayton // machine. 844f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 845f8122d35SGreg Clayton /*Offset=*/0x0, 846f8122d35SGreg Clayton /*Length=*/0xff); 847f8122d35SGreg Clayton 848f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 849f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 850f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 851f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 852f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 853f8122d35SGreg Clayton /*AddressRange=*/0x1000, 854f8122d35SGreg Clayton /*Cie=*/&TestCIE, 855f8122d35SGreg Clayton /*LSDAAddress=*/None, 856f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 857f8122d35SGreg Clayton 858f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 859f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 860f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 861f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 862f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 863f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 864f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 865f8122d35SGreg Clayton 866f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 867f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 868f8122d35SGreg Clayton Succeeded()); 869f8122d35SGreg Clayton 870f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 871f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 872f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 873f8122d35SGreg Clayton // two rows: 874f8122d35SGreg Clayton // - one with Reg = [CFA-8] 875f8122d35SGreg Clayton // - one with Reg = InReg 876f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 877f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 878f8122d35SGreg Clayton dwarf::DW_CFA_restore | Reg}), 879f8122d35SGreg Clayton Succeeded()); 880f8122d35SGreg Clayton 881f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 882f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 883f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 884f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 885f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 886f8122d35SGreg Clayton 887f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 888f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 889f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 890f8122d35SGreg Clayton 891f8122d35SGreg Clayton // Verify we catch state machine error. 892f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 893f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 894f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 895f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 896f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 897f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 898f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 899f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 900f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 901f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 902f8122d35SGreg Clayton } 903f8122d35SGreg Clayton 904f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 905f8122d35SGreg Clayton // Test that DW_CFA_restore works as expected when parsed in the state 906f8122d35SGreg Clayton // machine. 907f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 908f8122d35SGreg Clayton /*Offset=*/0x0, 909f8122d35SGreg Clayton /*Length=*/0xff); 910f8122d35SGreg Clayton 911f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 912f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 913f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 914f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 915f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 916f8122d35SGreg Clayton /*AddressRange=*/0x1000, 917f8122d35SGreg Clayton /*Cie=*/&TestCIE, 918f8122d35SGreg Clayton /*LSDAAddress=*/None, 919f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 920f8122d35SGreg Clayton 921f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 922f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 923f8122d35SGreg Clayton constexpr uint8_t CFAReg = 12; 924f8122d35SGreg Clayton constexpr uint8_t CFAOffset = 32; 925f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 926f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 927f8122d35SGreg Clayton constexpr int32_t RegCFAOffset = -8; 928f8122d35SGreg Clayton 929f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 930f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 931f8122d35SGreg Clayton Succeeded()); 932f8122d35SGreg Clayton 933f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the rule 934f8122d35SGreg Clayton // for register "Reg" to be [CFA-8], then push a row, and then restore the 935f8122d35SGreg Clayton // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 936f8122d35SGreg Clayton // end up with two rows: 937f8122d35SGreg Clayton // - one with Reg = [CFA-8] 938f8122d35SGreg Clayton // - one with Reg = InReg 939f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 940f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, 941f8122d35SGreg Clayton dwarf::DW_CFA_restore_extended, Reg}), 942f8122d35SGreg Clayton Succeeded()); 943f8122d35SGreg Clayton 944f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 945f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 946f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 947f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 948f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 949f8122d35SGreg Clayton 950f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 951f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 952f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 953f8122d35SGreg Clayton 954f8122d35SGreg Clayton // Verify we catch state machine error. 955f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 956f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 957f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 958f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 2u); 959f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 960f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 961f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 962f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 963f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 964f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 965f8122d35SGreg Clayton } 966f8122d35SGreg Clayton 967f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 968f8122d35SGreg Clayton // Test that DW_CFA_offset, DW_CFA_offset_extended and 969f8122d35SGreg Clayton // DW_CFA_offset_extended_sf work as expected when parsed in the state 970f8122d35SGreg Clayton // machine. 971f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 972f8122d35SGreg Clayton /*Offset=*/0x0, 973f8122d35SGreg Clayton /*Length=*/0xff); 974f8122d35SGreg Clayton 975f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 976f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 977f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 978f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 979f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 980f8122d35SGreg Clayton /*AddressRange=*/0x1000, 981f8122d35SGreg Clayton /*Cie=*/&TestCIE, 982f8122d35SGreg Clayton /*LSDAAddress=*/None, 983f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 984f8122d35SGreg Clayton 985f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 986f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 987f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 988f8122d35SGreg Clayton Succeeded()); 989f8122d35SGreg Clayton 990f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 991f8122d35SGreg Clayton // unwind rules for the follwing registers: 992f8122d35SGreg Clayton // Reg1 = [CFA-8] 993f8122d35SGreg Clayton // Reg2 = [CFA-16] 994f8122d35SGreg Clayton // Reg3 = [CFA+8] 995a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 996a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 997a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 998f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 999f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1000f8122d35SGreg Clayton parseCFI(TestFDE, 1001f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 1002f8122d35SGreg Clayton Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 1003f8122d35SGreg Clayton Succeeded()); 1004f8122d35SGreg Clayton 1005f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1006f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1007f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1008f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1009f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1010f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1011f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1012f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1013f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 1014f8122d35SGreg Clayton 1015f8122d35SGreg Clayton // Verify we catch state machine error. 1016f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1017f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1018f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1019f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1020f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1021f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1022f8122d35SGreg Clayton } 1023f8122d35SGreg Clayton 1024f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 1025f8122d35SGreg Clayton // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 1026f8122d35SGreg Clayton // parsed in the state machine. 1027f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1028f8122d35SGreg Clayton /*Offset=*/0x0, 1029f8122d35SGreg Clayton /*Length=*/0xff); 1030f8122d35SGreg Clayton 1031f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1032f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1033f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1034f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1035f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1036f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1037f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1038f8122d35SGreg Clayton /*LSDAAddress=*/None, 1039f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1040f8122d35SGreg Clayton 1041f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1042f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1043f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1044f8122d35SGreg Clayton Succeeded()); 1045f8122d35SGreg Clayton 1046f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1047f8122d35SGreg Clayton // unwind rules for the follwing registers: 1048f8122d35SGreg Clayton // Reg1 = [CFA-8] 1049f8122d35SGreg Clayton // Reg2 = [CFA-16] 1050f8122d35SGreg Clayton // Reg3 = [CFA+8] 1051a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1052a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1053f8122d35SGreg Clayton constexpr uint8_t Neg1SLEB = 0x7f; 1054f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1055f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 1056f8122d35SGreg Clayton dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 1057f8122d35SGreg Clayton Succeeded()); 1058f8122d35SGreg Clayton 1059f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1060f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1061f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1062f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1063f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 1064f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1065f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 1066f8122d35SGreg Clayton 1067f8122d35SGreg Clayton // Verify we catch state machine error. 1068f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1069f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1070f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1071f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1072f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1073f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1074f8122d35SGreg Clayton } 1075f8122d35SGreg Clayton 1076f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 1077f8122d35SGreg Clayton // Test that DW_CFA_nop works as expected when parsed in the state machine. 1078f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1079f8122d35SGreg Clayton /*Offset=*/0x0, 1080f8122d35SGreg Clayton /*Length=*/0xff); 1081f8122d35SGreg Clayton 1082f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1083f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1084f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1085f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1086f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1087f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1088f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1089f8122d35SGreg Clayton /*LSDAAddress=*/None, 1090f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1091f8122d35SGreg Clayton 1092f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1093f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1094f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1095f8122d35SGreg Clayton Succeeded()); 1096f8122d35SGreg Clayton 1097f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that changes the 1098f8122d35SGreg Clayton // unwind rules for the follwing registers: 1099f8122d35SGreg Clayton // Reg1 = [CFA-8] 1100f8122d35SGreg Clayton // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1101a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1102f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1103f8122d35SGreg Clayton parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1104f8122d35SGreg Clayton Succeeded()); 1105f8122d35SGreg Clayton 1106f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1107f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1108f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1109f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1110f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1111f8122d35SGreg Clayton 1112f8122d35SGreg Clayton // Verify we catch state machine error. 1113f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1114f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1115f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1116f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1117f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1118f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1119f8122d35SGreg Clayton } 1120f8122d35SGreg Clayton 1121f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1122f8122d35SGreg Clayton // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1123f8122d35SGreg Clayton // when parsed in the state machine. 1124f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1125f8122d35SGreg Clayton /*Offset=*/0x0, 1126f8122d35SGreg Clayton /*Length=*/0xff); 1127f8122d35SGreg Clayton 1128f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1129f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1130f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1131f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1132f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1133f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1134f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1135f8122d35SGreg Clayton /*LSDAAddress=*/None, 1136f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1137f8122d35SGreg Clayton 1138f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1139f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1140f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1141f8122d35SGreg Clayton Succeeded()); 1142f8122d35SGreg Clayton 1143f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1144f8122d35SGreg Clayton // follwing rows: 1145f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=[CFA-8] 1146f8122d35SGreg Clayton // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1147f8122d35SGreg Clayton // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1148f8122d35SGreg Clayton // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1149f8122d35SGreg Clayton // 0x1010: CFA=reg12+32: Reg1=[CFA-8] 1150f8122d35SGreg Clayton // This state machine will: 1151f8122d35SGreg Clayton // - set Reg1 location 1152f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1153f8122d35SGreg Clayton // - remember the state 1154f8122d35SGreg Clayton // - set Reg2 location 1155f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1156f8122d35SGreg Clayton // - remember the state 1157f8122d35SGreg Clayton // - set Reg3 location 1158f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1159f8122d35SGreg Clayton // - remember the state where Reg1 and Reg2 were set 1160f8122d35SGreg Clayton // - push a row (from DW_CFA_advance_loc) 1161f8122d35SGreg Clayton // - remember the state where only Reg1 was set 1162f8122d35SGreg Clayton // - push a row (automatically at the end of instruction parsing) 1163f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1164a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1165a1a3fdcdSGreg Clayton constexpr uint8_t Reg2 = 15; 1166a1a3fdcdSGreg Clayton constexpr uint8_t Reg3 = 16; 1167f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1168f8122d35SGreg Clayton parseCFI(TestFDE, 1169f8122d35SGreg Clayton {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1170f8122d35SGreg Clayton dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1171f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1172f8122d35SGreg Clayton dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1173f8122d35SGreg Clayton dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1174f8122d35SGreg Clayton dwarf::DW_CFA_restore_state}), 1175f8122d35SGreg Clayton Succeeded()); 1176f8122d35SGreg Clayton 1177f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1178f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1179f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs1; 1180f8122d35SGreg Clayton VerifyLocs1.setRegisterLocation( 1181f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1182f8122d35SGreg Clayton 1183f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs2; 1184f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1185f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1186f8122d35SGreg Clayton VerifyLocs2.setRegisterLocation( 1187f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1188f8122d35SGreg Clayton 1189f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs3; 1190f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1191f8122d35SGreg Clayton Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1192f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1193f8122d35SGreg Clayton Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1194f8122d35SGreg Clayton VerifyLocs3.setRegisterLocation( 1195f8122d35SGreg Clayton Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 1196f8122d35SGreg Clayton 1197f8122d35SGreg Clayton // Verify we catch state machine error. 1198f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1199f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1200f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1201f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1202f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1203f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1204f8122d35SGreg Clayton 1205f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1206f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1207f8122d35SGreg Clayton 1208f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1209f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1210f8122d35SGreg Clayton 1211f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1212f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1213f8122d35SGreg Clayton 1214f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1215f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1216f8122d35SGreg Clayton } 1217f8122d35SGreg Clayton 1218f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1219f8122d35SGreg Clayton // Test that DW_CFA_undefined works as expected when parsed in the state 1220f8122d35SGreg Clayton // machine. 1221f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1222f8122d35SGreg Clayton /*Offset=*/0x0, 1223f8122d35SGreg Clayton /*Length=*/0xff); 1224f8122d35SGreg Clayton 1225f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1226f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1227f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1228f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1229f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1230f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1231f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1232f8122d35SGreg Clayton /*LSDAAddress=*/None, 1233f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1234f8122d35SGreg Clayton 1235f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1236f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1237f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1238f8122d35SGreg Clayton Succeeded()); 1239f8122d35SGreg Clayton 1240f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1241f8122d35SGreg Clayton // follwing rows: 1242f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=undefined 1243f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1244a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1245f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1246f8122d35SGreg Clayton Succeeded()); 1247f8122d35SGreg Clayton 1248f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1249f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1250f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1251f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, 1252f8122d35SGreg Clayton dwarf::UnwindLocation::createUndefined()); 1253f8122d35SGreg Clayton 1254f8122d35SGreg Clayton // Verify we catch state machine error. 1255f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1256f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1257f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1258f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1259f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1260f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1261f8122d35SGreg Clayton } 1262f8122d35SGreg Clayton 1263f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1264f8122d35SGreg Clayton // Test that DW_CFA_same_value works as expected when parsed in the state 1265f8122d35SGreg Clayton // machine. 1266f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1267f8122d35SGreg Clayton /*Offset=*/0x0, 1268f8122d35SGreg Clayton /*Length=*/0xff); 1269f8122d35SGreg Clayton 1270f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1271f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1272f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1273f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1274f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1275f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1276f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1277f8122d35SGreg Clayton /*LSDAAddress=*/None, 1278f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1279f8122d35SGreg Clayton 1280f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1281f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1282f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1283f8122d35SGreg Clayton Succeeded()); 1284f8122d35SGreg Clayton 1285f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1286f8122d35SGreg Clayton // follwing rows: 1287f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1288f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1289a1a3fdcdSGreg Clayton constexpr uint8_t Reg1 = 14; 1290f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1291f8122d35SGreg Clayton Succeeded()); 1292f8122d35SGreg Clayton 1293f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1294f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1295f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1296f8122d35SGreg Clayton VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1297f8122d35SGreg Clayton 1298f8122d35SGreg Clayton // Verify we catch state machine error. 1299f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1300f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1301f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1302f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1303f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1304f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1305f8122d35SGreg Clayton } 1306f8122d35SGreg Clayton 1307f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1308f8122d35SGreg Clayton // Test that DW_CFA_register works as expected when parsed in the state 1309f8122d35SGreg Clayton // machine. 1310f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1311f8122d35SGreg Clayton /*Offset=*/0x0, 1312f8122d35SGreg Clayton /*Length=*/0xff); 1313f8122d35SGreg Clayton 1314f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1315f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1316f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1317f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1318f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1319f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1320f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1321f8122d35SGreg Clayton /*LSDAAddress=*/None, 1322f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1323f8122d35SGreg Clayton 1324f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1325f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1326f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1327f8122d35SGreg Clayton Succeeded()); 1328f8122d35SGreg Clayton 1329f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1330f8122d35SGreg Clayton // follwing rows: 1331f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=same 1332f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1333f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1334f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1335f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1336f8122d35SGreg Clayton Succeeded()); 1337f8122d35SGreg Clayton 1338f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1339f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1340f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1341f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1342f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1343f8122d35SGreg Clayton 1344f8122d35SGreg Clayton // Verify we catch state machine error. 1345f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1346f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1347f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1348f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1349f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1350f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1351f8122d35SGreg Clayton } 1352f8122d35SGreg Clayton 1353f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1354f8122d35SGreg Clayton // Test that DW_CFA_expression works as expected when parsed in the state 1355f8122d35SGreg Clayton // machine. 1356f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1357f8122d35SGreg Clayton /*Offset=*/0x0, 1358f8122d35SGreg Clayton /*Length=*/0xff); 1359f8122d35SGreg Clayton 1360f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1361f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1362f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1363f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1364f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1365f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1366f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1367f8122d35SGreg Clayton /*LSDAAddress=*/None, 1368f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1369f8122d35SGreg Clayton 1370f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1371f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1372f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1373f8122d35SGreg Clayton Succeeded()); 1374f8122d35SGreg Clayton 1375f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1376f8122d35SGreg Clayton // follwing rows: 1377f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1378f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1379f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1380f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1381f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1382f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1383f8122d35SGreg Clayton 1384f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1385f8122d35SGreg Clayton 1386f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1387f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1388f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1389f8122d35SGreg Clayton 1390f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1391f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1392f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1393f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1394f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1395f8122d35SGreg Clayton 1396f8122d35SGreg Clayton // Verify we catch state machine error. 1397f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1398f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1399f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1400f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1401f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1402f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1403f8122d35SGreg Clayton } 1404f8122d35SGreg Clayton 1405f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1406f8122d35SGreg Clayton // Test that DW_CFA_val_expression works as expected when parsed in the state 1407f8122d35SGreg Clayton // machine. 1408f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1409f8122d35SGreg Clayton /*Offset=*/0x0, 1410f8122d35SGreg Clayton /*Length=*/0xff); 1411f8122d35SGreg Clayton 1412f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1413f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1414f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1415f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1416f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1417f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1418f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1419f8122d35SGreg Clayton /*LSDAAddress=*/None, 1420f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1421f8122d35SGreg Clayton 1422f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1423f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1424f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1425f8122d35SGreg Clayton Succeeded()); 1426f8122d35SGreg Clayton 1427f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that encodes the 1428f8122d35SGreg Clayton // follwing rows: 1429f8122d35SGreg Clayton // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1430f8122d35SGreg Clayton // Then we verify that all registers are correct in all generated rows. 1431f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1432f8122d35SGreg Clayton constexpr uint8_t AddrSize = 8; 1433f8122d35SGreg Clayton std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1434f8122d35SGreg Clayton dwarf::DW_OP_reg12}; 1435f8122d35SGreg Clayton 1436f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1437f8122d35SGreg Clayton 1438f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1439f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1440f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1441f8122d35SGreg Clayton 1442f8122d35SGreg Clayton std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1443f8122d35SGreg Clayton DataExtractor ExprData(ExprBytes, true, AddrSize); 1444f8122d35SGreg Clayton DWARFExpression Expr(ExprData, AddrSize); 1445f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1446f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1447f8122d35SGreg Clayton 1448f8122d35SGreg Clayton // Verify we catch state machine error. 1449f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1450f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1451f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1452f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 1u); 1453f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1454f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1455f8122d35SGreg Clayton } 1456f8122d35SGreg Clayton 1457f8122d35SGreg Clayton TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1458f8122d35SGreg Clayton // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1459f8122d35SGreg Clayton // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1460f8122d35SGreg Clayton // parsed in the state machine. 1461f8122d35SGreg Clayton dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1462f8122d35SGreg Clayton /*Offset=*/0x0, 1463f8122d35SGreg Clayton /*Length=*/0xff); 1464f8122d35SGreg Clayton 1465f8122d35SGreg Clayton dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1466f8122d35SGreg Clayton /*Offset=*/0x3333abcdabcd, 1467f8122d35SGreg Clayton /*Length=*/0x4444abcdabcd, 1468f8122d35SGreg Clayton /*CIEPointer=*/0x1111abcdabcd, 1469f8122d35SGreg Clayton /*InitialLocation=*/0x1000, 1470f8122d35SGreg Clayton /*AddressRange=*/0x1000, 1471f8122d35SGreg Clayton /*Cie=*/&TestCIE, 1472f8122d35SGreg Clayton /*LSDAAddress=*/None, 1473f8122d35SGreg Clayton /*Arch=*/Triple::x86_64); 1474f8122d35SGreg Clayton 1475f8122d35SGreg Clayton // Make a CIE that has a valid CFA definition and a single register unwind 1476f8122d35SGreg Clayton // rule for register that we will verify is in all of the pushed rows. 1477f8122d35SGreg Clayton constexpr uint8_t CFAReg1 = 12; 1478f8122d35SGreg Clayton constexpr uint8_t CFAOff1 = 32; 1479f8122d35SGreg Clayton constexpr uint8_t CFAReg2 = 13; 1480f8122d35SGreg Clayton constexpr uint8_t CFAOff2 = 48; 1481f8122d35SGreg Clayton constexpr uint8_t Reg = 13; 1482f8122d35SGreg Clayton constexpr uint8_t InReg = 14; 1483f8122d35SGreg Clayton 1484f8122d35SGreg Clayton EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1485f8122d35SGreg Clayton dwarf::DW_CFA_register, Reg, InReg}), 1486f8122d35SGreg Clayton Succeeded()); 1487f8122d35SGreg Clayton 1488f8122d35SGreg Clayton // Make a FDE with DWARF call frame instruction opcodes that use all of the 1489f8122d35SGreg Clayton // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1490f8122d35SGreg Clayton // create a row are correctly working. 1491f8122d35SGreg Clayton EXPECT_THAT_ERROR( 1492f8122d35SGreg Clayton parseCFI( 1493f8122d35SGreg Clayton TestFDE, 1494f8122d35SGreg Clayton { 1495f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1496f8122d35SGreg Clayton CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1497f8122d35SGreg Clayton dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1498f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1499f8122d35SGreg Clayton 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1500f8122d35SGreg Clayton dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1501f8122d35SGreg Clayton 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1502f8122d35SGreg Clayton }), 1503f8122d35SGreg Clayton Succeeded()); 1504f8122d35SGreg Clayton 1505f8122d35SGreg Clayton // Create locations that we expect the UnwindRow objects to contain after 1506f8122d35SGreg Clayton // parsing the DWARF call frame instructions. 1507f8122d35SGreg Clayton dwarf::RegisterLocations VerifyLocs; 1508f8122d35SGreg Clayton VerifyLocs.setRegisterLocation( 1509f8122d35SGreg Clayton Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1510f8122d35SGreg Clayton 1511f8122d35SGreg Clayton // Verify we catch state machine error. 1512f8122d35SGreg Clayton Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1513f8122d35SGreg Clayton EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1514f8122d35SGreg Clayton const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1515f8122d35SGreg Clayton EXPECT_EQ(Rows.size(), 5u); 1516f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1517f8122d35SGreg Clayton EXPECT_EQ( 1518f8122d35SGreg Clayton Rows[0].getCFAValue(), 1519f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1520f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1521f8122d35SGreg Clayton EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1522f8122d35SGreg Clayton 1523f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1524f8122d35SGreg Clayton EXPECT_EQ( 1525f8122d35SGreg Clayton Rows[1].getCFAValue(), 1526f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1527f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1528f8122d35SGreg Clayton EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1529f8122d35SGreg Clayton 1530f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1531f8122d35SGreg Clayton EXPECT_EQ( 1532f8122d35SGreg Clayton Rows[2].getCFAValue(), 1533f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1534f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1535f8122d35SGreg Clayton EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1536f8122d35SGreg Clayton 1537f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1538f8122d35SGreg Clayton EXPECT_EQ( 1539f8122d35SGreg Clayton Rows[3].getCFAValue(), 1540f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1541f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1542f8122d35SGreg Clayton EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1543f8122d35SGreg Clayton 1544f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1545f8122d35SGreg Clayton EXPECT_EQ( 1546f8122d35SGreg Clayton Rows[4].getCFAValue(), 1547f8122d35SGreg Clayton dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1548f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1549f8122d35SGreg Clayton EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1550f8122d35SGreg Clayton } 1551f8122d35SGreg Clayton 1552*167e7afcSRamNalamothu TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) { 1553*167e7afcSRamNalamothu // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf, 1554*167e7afcSRamNalamothu // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and 1555*167e7afcSRamNalamothu // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state 1556*167e7afcSRamNalamothu // machine. 1557*167e7afcSRamNalamothu dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1558*167e7afcSRamNalamothu /*Offset=*/0x0, 1559*167e7afcSRamNalamothu /*Length=*/0xff); 1560*167e7afcSRamNalamothu 1561*167e7afcSRamNalamothu dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1562*167e7afcSRamNalamothu /*Offset=*/0x3333abcdabcd, 1563*167e7afcSRamNalamothu /*Length=*/0x4444abcdabcd, 1564*167e7afcSRamNalamothu /*CIEPointer=*/0x1111abcdabcd, 1565*167e7afcSRamNalamothu /*InitialLocation=*/0x1000, 1566*167e7afcSRamNalamothu /*AddressRange=*/0x1000, 1567*167e7afcSRamNalamothu /*Cie=*/&TestCIE, 1568*167e7afcSRamNalamothu /*LSDAAddress=*/None, 1569*167e7afcSRamNalamothu /*Arch=*/Triple::x86_64); 1570*167e7afcSRamNalamothu 1571*167e7afcSRamNalamothu // Make a CIE that has a valid CFA definition and a single register unwind 1572*167e7afcSRamNalamothu // rule for register that we will verify is in all of the pushed rows. 1573*167e7afcSRamNalamothu constexpr uint8_t CFAReg1 = 12; 1574*167e7afcSRamNalamothu constexpr uint8_t CFAOff1 = 32; 1575*167e7afcSRamNalamothu constexpr uint8_t CFAReg2 = 13; 1576*167e7afcSRamNalamothu constexpr uint8_t CFAOff2 = 48; 1577*167e7afcSRamNalamothu constexpr uint8_t Reg = 13; 1578*167e7afcSRamNalamothu constexpr uint8_t InReg = 14; 1579*167e7afcSRamNalamothu constexpr uint8_t AddrSpace = 2; 1580*167e7afcSRamNalamothu 1581*167e7afcSRamNalamothu EXPECT_THAT_ERROR( 1582*167e7afcSRamNalamothu parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1, 1583*167e7afcSRamNalamothu AddrSpace, dwarf::DW_CFA_register, Reg, InReg}), 1584*167e7afcSRamNalamothu Succeeded()); 1585*167e7afcSRamNalamothu 1586*167e7afcSRamNalamothu // Make a FDE with DWARF call frame instruction opcodes that use all of the 1587*167e7afcSRamNalamothu // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1588*167e7afcSRamNalamothu // create a row are correctly working. 1589*167e7afcSRamNalamothu EXPECT_THAT_ERROR( 1590*167e7afcSRamNalamothu parseCFI( 1591*167e7afcSRamNalamothu TestFDE, 1592*167e7afcSRamNalamothu { 1593*167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1594*167e7afcSRamNalamothu CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1595*167e7afcSRamNalamothu dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1596*167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1597*167e7afcSRamNalamothu 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1598*167e7afcSRamNalamothu dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1599*167e7afcSRamNalamothu 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1600*167e7afcSRamNalamothu }), 1601*167e7afcSRamNalamothu Succeeded()); 1602*167e7afcSRamNalamothu 1603*167e7afcSRamNalamothu // Create locations that we expect the UnwindRow objects to contain after 1604*167e7afcSRamNalamothu // parsing the DWARF call frame instructions. 1605*167e7afcSRamNalamothu dwarf::RegisterLocations VerifyLocs; 1606*167e7afcSRamNalamothu VerifyLocs.setRegisterLocation( 1607*167e7afcSRamNalamothu Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1608*167e7afcSRamNalamothu 1609*167e7afcSRamNalamothu // Verify we catch state machine error. 1610*167e7afcSRamNalamothu Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1611*167e7afcSRamNalamothu EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1612*167e7afcSRamNalamothu const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1613*167e7afcSRamNalamothu EXPECT_EQ(Rows.size(), 5u); 1614*167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1615*167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getCFAValue(), 1616*167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1, 1617*167e7afcSRamNalamothu AddrSpace)); 1618*167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1619*167e7afcSRamNalamothu EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1620*167e7afcSRamNalamothu 1621*167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1622*167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getCFAValue(), 1623*167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1624*167e7afcSRamNalamothu AddrSpace)); 1625*167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1626*167e7afcSRamNalamothu EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1627*167e7afcSRamNalamothu 1628*167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1629*167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getCFAValue(), 1630*167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2, 1631*167e7afcSRamNalamothu AddrSpace)); 1632*167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1633*167e7afcSRamNalamothu EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1634*167e7afcSRamNalamothu 1635*167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1636*167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getCFAValue(), 1637*167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1638*167e7afcSRamNalamothu AddrSpace)); 1639*167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1640*167e7afcSRamNalamothu EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1641*167e7afcSRamNalamothu 1642*167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1643*167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getCFAValue(), 1644*167e7afcSRamNalamothu dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2, 1645*167e7afcSRamNalamothu AddrSpace)); 1646*167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1647*167e7afcSRamNalamothu EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1648*167e7afcSRamNalamothu } 1649*167e7afcSRamNalamothu 1650cada5b88SIgor Kudrin } // end anonymous namespace 1651