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 9cada5b88SIgor Kudrin #include "llvm/ADT/SmallVector.h" 10cada5b88SIgor Kudrin #include "llvm/ADT/StringRef.h" 11cada5b88SIgor Kudrin #include "llvm/BinaryFormat/Dwarf.h" 12cada5b88SIgor Kudrin #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 13*1e820e82SGeorgii Rymar #include "llvm/Testing/Support/Error.h" 14cada5b88SIgor Kudrin #include "gtest/gtest.h" 15cada5b88SIgor Kudrin 16cada5b88SIgor Kudrin using namespace llvm; 17cada5b88SIgor Kudrin 18cada5b88SIgor Kudrin namespace { 19cada5b88SIgor Kudrin 20cada5b88SIgor Kudrin dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) { 21cada5b88SIgor Kudrin return dwarf::CIE(IsDWARF64, Offset, Length, 22cada5b88SIgor Kudrin /*Version=*/3, 23cada5b88SIgor Kudrin /*Augmentation=*/StringRef(), 24cada5b88SIgor Kudrin /*AddressSize=*/8, 25cada5b88SIgor Kudrin /*SegmentDescriptorSize=*/0, 26cada5b88SIgor Kudrin /*CodeAlignmentFactor=*/1, 27cada5b88SIgor Kudrin /*DataAlignmentFactor=*/-8, 28cada5b88SIgor Kudrin /*ReturnAddressRegister=*/16, 29cada5b88SIgor Kudrin /*AugmentationData=*/StringRef(), 30cada5b88SIgor Kudrin /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr, 31cada5b88SIgor Kudrin /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit, 32cada5b88SIgor Kudrin /*Personality=*/None, 33cada5b88SIgor Kudrin /*PersonalityEnc=*/None, 34cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 35cada5b88SIgor Kudrin } 36cada5b88SIgor Kudrin 37cada5b88SIgor Kudrin void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH, 38cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 39cada5b88SIgor Kudrin std::string Output; 40cada5b88SIgor Kudrin raw_string_ostream OS(Output); 41cada5b88SIgor Kudrin TestCIE.dump(OS, /*MRI=*/nullptr, IsEH); 42cada5b88SIgor Kudrin OS.flush(); 43cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 44cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 45cada5b88SIgor Kudrin } 46cada5b88SIgor Kudrin 47cada5b88SIgor Kudrin void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH, 48cada5b88SIgor Kudrin StringRef ExpectedFirstLine) { 49cada5b88SIgor Kudrin std::string Output; 50cada5b88SIgor Kudrin raw_string_ostream OS(Output); 51cada5b88SIgor Kudrin TestFDE.dump(OS, /*MRI=*/nullptr, IsEH); 52cada5b88SIgor Kudrin OS.flush(); 53cada5b88SIgor Kudrin StringRef FirstLine = StringRef(Output).split('\n').first; 54cada5b88SIgor Kudrin EXPECT_EQ(FirstLine, ExpectedFirstLine); 55cada5b88SIgor Kudrin } 56cada5b88SIgor Kudrin 57cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF32CIE) { 58cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 59cada5b88SIgor Kudrin /*Offset=*/0x1111abcd, 60cada5b88SIgor Kudrin /*Length=*/0x2222abcd); 61cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE"); 62cada5b88SIgor Kudrin } 63cada5b88SIgor Kudrin 64cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64CIE) { 65cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 66cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 67cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 68cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/false, 69cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE"); 70cada5b88SIgor Kudrin } 71cada5b88SIgor Kudrin 72cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEHCIE) { 73cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 74cada5b88SIgor Kudrin /*Offset=*/0x1000, 75cada5b88SIgor Kudrin /*Length=*/0x20); 76cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE"); 77cada5b88SIgor Kudrin } 78cada5b88SIgor Kudrin 79cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64CIE) { 80cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 81cada5b88SIgor Kudrin /*Offset=*/0x1000, 82cada5b88SIgor Kudrin /*Length=*/0x20); 83cada5b88SIgor Kudrin expectDumpResult(TestCIE, /*IsEH=*/true, 84cada5b88SIgor Kudrin "00001000 0000000000000020 00000000 CIE"); 85cada5b88SIgor Kudrin } 86cada5b88SIgor Kudrin 87cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpDWARF64FDE) { 88cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 89cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 90cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd); 91cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 92cada5b88SIgor Kudrin /*Offset=*/0x3333abcdabcd, 93cada5b88SIgor Kudrin /*Length=*/0x4444abcdabcd, 94cada5b88SIgor Kudrin /*CIEPointer=*/0x1111abcdabcd, 95cada5b88SIgor Kudrin /*InitialLocation=*/0x5555abcdabcd, 96cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 97cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 98cada5b88SIgor Kudrin /*LSDAAddress=*/None, 99cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 100cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/false, 101cada5b88SIgor Kudrin "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE " 102cada5b88SIgor Kudrin "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde"); 103cada5b88SIgor Kudrin } 104cada5b88SIgor Kudrin 105cada5b88SIgor Kudrin TEST(DWARFDebugFrame, DumpEH64FDE) { 106cada5b88SIgor Kudrin dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 107cada5b88SIgor Kudrin /*Offset=*/0x1111ab9a000c, 108cada5b88SIgor Kudrin /*Length=*/0x20); 109cada5b88SIgor Kudrin dwarf::FDE TestFDE(/*IsDWARF64=*/true, 110cada5b88SIgor Kudrin /*Offset=*/0x1111abcdabcd, 111cada5b88SIgor Kudrin /*Length=*/0x2222abcdabcd, 112cada5b88SIgor Kudrin /*CIEPointer=*/0x33abcd, 113cada5b88SIgor Kudrin /*InitialLocation=*/0x4444abcdabcd, 114cada5b88SIgor Kudrin /*AddressRange=*/0x111111111111, 115cada5b88SIgor Kudrin /*Cie=*/&TestCIE, 116cada5b88SIgor Kudrin /*LSDAAddress=*/None, 117cada5b88SIgor Kudrin /*Arch=*/Triple::x86_64); 118cada5b88SIgor Kudrin expectDumpResult(TestFDE, /*IsEH=*/true, 119cada5b88SIgor Kudrin "1111abcdabcd 00002222abcdabcd 0033abcd FDE " 120cada5b88SIgor Kudrin "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde"); 121cada5b88SIgor Kudrin } 122cada5b88SIgor Kudrin 123*1e820e82SGeorgii Rymar // Here we test how truncated Call Frame Instructions are parsed. 124*1e820e82SGeorgii Rymar TEST(DWARFDebugFrame, ParseTruncatedCFITest) { 125*1e820e82SGeorgii Rymar auto ParseCFI = [](dwarf::CIE &C, ArrayRef<uint8_t> Instructions, 126*1e820e82SGeorgii Rymar Optional<uint64_t> Size = None) { 127*1e820e82SGeorgii Rymar DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 128*1e820e82SGeorgii Rymar /*AddressSize=*/8); 129*1e820e82SGeorgii Rymar uint64_t Offset = 0; 130*1e820e82SGeorgii Rymar const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size(); 131*1e820e82SGeorgii Rymar return C.cfis().parse(Data, &Offset, EndOffset); 132*1e820e82SGeorgii Rymar }; 133*1e820e82SGeorgii Rymar 134*1e820e82SGeorgii Rymar dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 135*1e820e82SGeorgii Rymar /*Offset=*/0x0, 136*1e820e82SGeorgii Rymar /*Length=*/0xff); 137*1e820e82SGeorgii Rymar 138*1e820e82SGeorgii Rymar // Having an empty instructions list is fine. 139*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR(ParseCFI(TestCIE, {}), Succeeded()); 140*1e820e82SGeorgii Rymar 141*1e820e82SGeorgii Rymar // Unable to read an opcode, because the instructions list is empty, but we 142*1e820e82SGeorgii Rymar // say to the parser that it is not. 143*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 144*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {}, /*Size=*/1), 145*1e820e82SGeorgii Rymar FailedWithMessage( 146*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x0 while reading [0x0, 0x1)")); 147*1e820e82SGeorgii Rymar 148*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_offset instruction. 149*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 150*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_offset}), 151*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 152*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 153*1e820e82SGeorgii Rymar 154*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_set_loc instruction. 155*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 156*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_set_loc}), 157*1e820e82SGeorgii Rymar FailedWithMessage( 158*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x9)")); 159*1e820e82SGeorgii Rymar 160*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc1 instruction. 161*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 162*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}), 163*1e820e82SGeorgii Rymar FailedWithMessage( 164*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x2)")); 165*1e820e82SGeorgii Rymar 166*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc2 instruction. 167*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 168*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}), 169*1e820e82SGeorgii Rymar FailedWithMessage( 170*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x3)")); 171*1e820e82SGeorgii Rymar 172*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_advance_loc4 instruction. 173*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 174*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}), 175*1e820e82SGeorgii Rymar FailedWithMessage( 176*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x1 while reading [0x1, 0x5)")); 177*1e820e82SGeorgii Rymar 178*1e820e82SGeorgii Rymar // A test for an instruction with a single ULEB128 operand. 179*1e820e82SGeorgii Rymar auto CheckOp_ULEB128 = [&](uint8_t Inst) { 180*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 181*1e820e82SGeorgii Rymar ParseCFI(TestCIE, Inst), 182*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 183*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 184*1e820e82SGeorgii Rymar }; 185*1e820e82SGeorgii Rymar 186*1e820e82SGeorgii Rymar for (uint8_t Inst : 187*1e820e82SGeorgii Rymar {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined, 188*1e820e82SGeorgii Rymar dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register, 189*1e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size}) 190*1e820e82SGeorgii Rymar CheckOp_ULEB128(Inst); 191*1e820e82SGeorgii Rymar 192*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction. 193*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 194*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}), 195*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 196*1e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 197*1e820e82SGeorgii Rymar 198*1e820e82SGeorgii Rymar // A test for an instruction with two ULEB128 operands. 199*1e820e82SGeorgii Rymar auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) { 200*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 201*1e820e82SGeorgii Rymar ParseCFI(TestCIE, Inst), 202*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 203*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 204*1e820e82SGeorgii Rymar 205*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 206*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {Inst, /*Op1=*/0}), 207*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 208*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 209*1e820e82SGeorgii Rymar }; 210*1e820e82SGeorgii Rymar 211*1e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register, 212*1e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_val_offset}) 213*1e820e82SGeorgii Rymar CheckOp_ULEB128_ULEB128(Inst); 214*1e820e82SGeorgii Rymar 215*1e820e82SGeorgii Rymar // A test for an instruction with two operands: ULEB128, SLEB128. 216*1e820e82SGeorgii Rymar auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) { 217*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 218*1e820e82SGeorgii Rymar ParseCFI(TestCIE, Inst), 219*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 220*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 221*1e820e82SGeorgii Rymar 222*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 223*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {Inst, /*Op1=*/0}), 224*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 225*1e820e82SGeorgii Rymar "malformed sleb128, extends past end")); 226*1e820e82SGeorgii Rymar }; 227*1e820e82SGeorgii Rymar 228*1e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_offset_extended_sf, 229*1e820e82SGeorgii Rymar dwarf::DW_CFA_def_cfa_sf, dwarf::DW_CFA_val_offset_sf}) 230*1e820e82SGeorgii Rymar CheckOp_ULEB128_SLEB128(Inst); 231*1e820e82SGeorgii Rymar 232*1e820e82SGeorgii Rymar // Unable to read a truncated DW_CFA_def_cfa_expression instruction. 233*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 234*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}), 235*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 236*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 237*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 238*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 239*1e820e82SGeorgii Rymar /*expression length=*/0x1}), 240*1e820e82SGeorgii Rymar FailedWithMessage( 241*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x2 while reading [0x2, 0x3)")); 242*1e820e82SGeorgii Rymar // The DW_CFA_def_cfa_expression can contain a zero length expression. 243*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR(ParseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 244*1e820e82SGeorgii Rymar /*ExprLen=*/0}), 245*1e820e82SGeorgii Rymar Succeeded()); 246*1e820e82SGeorgii Rymar 247*1e820e82SGeorgii Rymar // A test for an instruction with three operands: ULEB128, expression length 248*1e820e82SGeorgii Rymar // (ULEB128) and expression bytes. 249*1e820e82SGeorgii Rymar auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) { 250*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 251*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {Inst}), 252*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 253*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 254*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 255*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {Inst, /*Op1=*/0}), 256*1e820e82SGeorgii Rymar FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 257*1e820e82SGeorgii Rymar "malformed uleb128, extends past end")); 258*1e820e82SGeorgii Rymar // A zero length expression is fine 259*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR(ParseCFI(TestCIE, {Inst, 260*1e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/0}), 261*1e820e82SGeorgii Rymar Succeeded()); 262*1e820e82SGeorgii Rymar EXPECT_THAT_ERROR( 263*1e820e82SGeorgii Rymar ParseCFI(TestCIE, {Inst, 264*1e820e82SGeorgii Rymar /*Op1=*/0, /*ExprLen=*/1}), 265*1e820e82SGeorgii Rymar FailedWithMessage( 266*1e820e82SGeorgii Rymar "unexpected end of data at offset 0x3 while reading [0x3, 0x4)")); 267*1e820e82SGeorgii Rymar }; 268*1e820e82SGeorgii Rymar 269*1e820e82SGeorgii Rymar for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression}) 270*1e820e82SGeorgii Rymar CheckOp_ULEB128_Expr(Inst); 271*1e820e82SGeorgii Rymar } 272*1e820e82SGeorgii Rymar 273cada5b88SIgor Kudrin } // end anonymous namespace 274