1 //===- llvm/unittest/DebugInfo/DWARFDebugFrameTest.cpp --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 10 #include "llvm/ADT/DenseSet.h" 11 #include "llvm/ADT/SmallVector.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/BinaryFormat/Dwarf.h" 14 #include "llvm/DebugInfo/DIContext.h" 15 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 16 #include "llvm/Testing/Support/Error.h" 17 #include "gtest/gtest.h" 18 19 using namespace llvm; 20 21 namespace { 22 23 dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) { 24 return dwarf::CIE(IsDWARF64, Offset, Length, 25 /*Version=*/3, 26 /*Augmentation=*/StringRef(), 27 /*AddressSize=*/8, 28 /*SegmentDescriptorSize=*/0, 29 /*CodeAlignmentFactor=*/1, 30 /*DataAlignmentFactor=*/-8, 31 /*ReturnAddressRegister=*/16, 32 /*AugmentationData=*/StringRef(), 33 /*FDEPointerEncoding=*/dwarf::DW_EH_PE_absptr, 34 /*LSDAPointerEncoding=*/dwarf::DW_EH_PE_omit, 35 /*Personality=*/std::nullopt, 36 /*PersonalityEnc=*/std::nullopt, 37 /*Arch=*/Triple::x86_64); 38 } 39 40 void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH, 41 StringRef ExpectedFirstLine) { 42 std::string Output; 43 raw_string_ostream OS(Output); 44 auto DumpOpts = DIDumpOptions(); 45 DumpOpts.IsEH = IsEH; 46 TestCIE.dump(OS, DumpOpts); 47 StringRef FirstLine = StringRef(Output).split('\n').first; 48 EXPECT_EQ(FirstLine, ExpectedFirstLine); 49 } 50 51 void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH, 52 StringRef ExpectedFirstLine) { 53 std::string Output; 54 raw_string_ostream OS(Output); 55 auto DumpOpts = DIDumpOptions(); 56 DumpOpts.IsEH = IsEH; 57 TestFDE.dump(OS, DumpOpts); 58 StringRef FirstLine = StringRef(Output).split('\n').first; 59 EXPECT_EQ(FirstLine, ExpectedFirstLine); 60 } 61 62 TEST(DWARFDebugFrame, DumpDWARF32CIE) { 63 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 64 /*Offset=*/0x1111abcd, 65 /*Length=*/0x2222abcd); 66 expectDumpResult(TestCIE, /*IsEH=*/false, "1111abcd 2222abcd ffffffff CIE"); 67 } 68 69 TEST(DWARFDebugFrame, DumpDWARF64CIE) { 70 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 71 /*Offset=*/0x1111abcdabcd, 72 /*Length=*/0x2222abcdabcd); 73 expectDumpResult(TestCIE, /*IsEH=*/false, 74 "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE"); 75 } 76 77 TEST(DWARFDebugFrame, DumpEHCIE) { 78 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 79 /*Offset=*/0x1000, 80 /*Length=*/0x20); 81 expectDumpResult(TestCIE, /*IsEH=*/true, "00001000 00000020 00000000 CIE"); 82 } 83 84 TEST(DWARFDebugFrame, DumpEH64CIE) { 85 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 86 /*Offset=*/0x1000, 87 /*Length=*/0x20); 88 expectDumpResult(TestCIE, /*IsEH=*/true, 89 "00001000 0000000000000020 00000000 CIE"); 90 } 91 92 TEST(DWARFDebugFrame, DumpDWARF64FDE) { 93 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 94 /*Offset=*/0x1111abcdabcd, 95 /*Length=*/0x2222abcdabcd); 96 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 97 /*Offset=*/0x3333abcdabcd, 98 /*Length=*/0x4444abcdabcd, 99 /*CIEPointer=*/0x1111abcdabcd, 100 /*InitialLocation=*/0x5555abcdabcd, 101 /*AddressRange=*/0x111111111111, 102 /*Cie=*/&TestCIE, 103 /*LSDAAddress=*/std::nullopt, 104 /*Arch=*/Triple::x86_64); 105 expectDumpResult(TestFDE, /*IsEH=*/false, 106 "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE " 107 "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde"); 108 } 109 110 TEST(DWARFDebugFrame, DumpEH64FDE) { 111 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/true, 112 /*Offset=*/0x1111ab9a000c, 113 /*Length=*/0x20); 114 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 115 /*Offset=*/0x1111abcdabcd, 116 /*Length=*/0x2222abcdabcd, 117 /*CIEPointer=*/0x33abcd, 118 /*InitialLocation=*/0x4444abcdabcd, 119 /*AddressRange=*/0x111111111111, 120 /*Cie=*/&TestCIE, 121 /*LSDAAddress=*/std::nullopt, 122 /*Arch=*/Triple::x86_64); 123 expectDumpResult(TestFDE, /*IsEH=*/true, 124 "1111abcdabcd 00002222abcdabcd 0033abcd FDE " 125 "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde"); 126 } 127 128 static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions, 129 std::optional<uint64_t> Size = std::nullopt) { 130 DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 131 /*AddressSize=*/8); 132 uint64_t Offset = 0; 133 const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size(); 134 return C.cfis().parse(Data, &Offset, EndOffset); 135 } 136 137 static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) { 138 DWARFDataExtractor Data(Instructions, /*IsLittleEndian=*/true, 139 /*AddressSize=*/8); 140 uint64_t Offset = 0; 141 return FDE.cfis().parse(Data, &Offset, Instructions.size()); 142 } 143 144 TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) { 145 llvm::DenseSet<uint8_t> ValidExtendedOpcodes = { 146 dwarf::DW_CFA_nop, 147 dwarf::DW_CFA_advance_loc, 148 dwarf::DW_CFA_offset, 149 dwarf::DW_CFA_restore, 150 dwarf::DW_CFA_set_loc, 151 dwarf::DW_CFA_advance_loc1, 152 dwarf::DW_CFA_advance_loc2, 153 dwarf::DW_CFA_advance_loc4, 154 dwarf::DW_CFA_offset_extended, 155 dwarf::DW_CFA_restore_extended, 156 dwarf::DW_CFA_undefined, 157 dwarf::DW_CFA_same_value, 158 dwarf::DW_CFA_register, 159 dwarf::DW_CFA_remember_state, 160 dwarf::DW_CFA_restore_state, 161 dwarf::DW_CFA_def_cfa, 162 dwarf::DW_CFA_def_cfa_register, 163 dwarf::DW_CFA_def_cfa_offset, 164 dwarf::DW_CFA_def_cfa_expression, 165 dwarf::DW_CFA_expression, 166 dwarf::DW_CFA_offset_extended_sf, 167 dwarf::DW_CFA_def_cfa_sf, 168 dwarf::DW_CFA_def_cfa_offset_sf, 169 dwarf::DW_CFA_LLVM_def_aspace_cfa, 170 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, 171 dwarf::DW_CFA_val_offset, 172 dwarf::DW_CFA_val_offset_sf, 173 dwarf::DW_CFA_val_expression, 174 dwarf::DW_CFA_MIPS_advance_loc8, 175 dwarf::DW_CFA_GNU_window_save, 176 dwarf::DW_CFA_AARCH64_negate_ra_state, 177 dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc, 178 dwarf::DW_CFA_GNU_args_size}; 179 180 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 181 /*Offset=*/0x0, 182 /*Length=*/0xff); 183 184 // See DWARF standard v3, section 7.23: low 6 bits are used to encode an 185 // extended opcode. 186 for (uint8_t Code = 0; Code <= 63; ++Code) { 187 if (ValidExtendedOpcodes.count(Code)) 188 continue; 189 190 EXPECT_THAT_ERROR(parseCFI(TestCIE, Code), 191 FailedWithMessage(("invalid extended CFI opcode 0x" + 192 Twine::utohexstr(Code)) 193 .str() 194 .c_str())); 195 } 196 } 197 198 // Here we test how truncated Call Frame Instructions are parsed. 199 TEST(DWARFDebugFrame, ParseTruncatedCFITest) { 200 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 201 /*Offset=*/0x0, 202 /*Length=*/0xff); 203 204 // Having an empty instructions list is fine. 205 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 206 207 // Unable to read an opcode, because the instructions list is empty, but we 208 // say to the parser that it is not. 209 EXPECT_THAT_ERROR( 210 parseCFI(TestCIE, {}, /*Size=*/1), 211 FailedWithMessage( 212 "unexpected end of data at offset 0x0 while reading [0x0, 0x1)")); 213 214 // Unable to read a truncated DW_CFA_offset instruction. 215 EXPECT_THAT_ERROR( 216 parseCFI(TestCIE, {dwarf::DW_CFA_offset}), 217 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 218 "malformed uleb128, extends past end")); 219 220 // Unable to read a truncated DW_CFA_set_loc instruction. 221 EXPECT_THAT_ERROR( 222 parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}), 223 FailedWithMessage( 224 "unexpected end of data at offset 0x1 while reading [0x1, 0x9)")); 225 226 // Unable to read a truncated DW_CFA_advance_loc1 instruction. 227 EXPECT_THAT_ERROR( 228 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}), 229 FailedWithMessage( 230 "unexpected end of data at offset 0x1 while reading [0x1, 0x2)")); 231 232 // Unable to read a truncated DW_CFA_advance_loc2 instruction. 233 EXPECT_THAT_ERROR( 234 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}), 235 FailedWithMessage( 236 "unexpected end of data at offset 0x1 while reading [0x1, 0x3)")); 237 238 // Unable to read a truncated DW_CFA_advance_loc4 instruction. 239 EXPECT_THAT_ERROR( 240 parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}), 241 FailedWithMessage( 242 "unexpected end of data at offset 0x1 while reading [0x1, 0x5)")); 243 244 // A test for an instruction with a single ULEB128 operand. 245 auto CheckOp_ULEB128 = [&](uint8_t Inst) { 246 EXPECT_THAT_ERROR( 247 parseCFI(TestCIE, Inst), 248 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 249 "malformed uleb128, extends past end")); 250 }; 251 252 for (uint8_t Inst : 253 {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined, 254 dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register, 255 dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size}) 256 CheckOp_ULEB128(Inst); 257 258 // Unable to read a truncated DW_CFA_def_cfa_offset_sf instruction. 259 EXPECT_THAT_ERROR( 260 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}), 261 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 262 "malformed sleb128, extends past end")); 263 264 // A test for an instruction with two ULEB128 operands. 265 auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) { 266 EXPECT_THAT_ERROR( 267 parseCFI(TestCIE, Inst), 268 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 269 "malformed uleb128, extends past end")); 270 271 EXPECT_THAT_ERROR( 272 parseCFI(TestCIE, {Inst, /*Op1=*/0}), 273 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 274 "malformed uleb128, extends past end")); 275 }; 276 277 for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register, 278 dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa, 279 dwarf::DW_CFA_val_offset}) 280 CheckOp_ULEB128_ULEB128(Inst); 281 282 // A test for an instruction with two operands: ULEB128, SLEB128. 283 auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) { 284 EXPECT_THAT_ERROR( 285 parseCFI(TestCIE, Inst), 286 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 287 "malformed uleb128, extends past end")); 288 289 EXPECT_THAT_ERROR( 290 parseCFI(TestCIE, {Inst, /*Op1=*/0}), 291 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 292 "malformed sleb128, extends past end")); 293 }; 294 295 for (uint8_t Inst : 296 {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf, 297 dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf}) 298 CheckOp_ULEB128_SLEB128(Inst); 299 300 // Unable to read a truncated DW_CFA_def_cfa_expression instruction. 301 EXPECT_THAT_ERROR( 302 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}), 303 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 304 "malformed uleb128, extends past end")); 305 EXPECT_THAT_ERROR( 306 parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 307 /*expression length=*/0x1}), 308 FailedWithMessage( 309 "unexpected end of data at offset 0x2 while reading [0x2, 0x3)")); 310 // The DW_CFA_def_cfa_expression can contain a zero length expression. 311 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression, 312 /*ExprLen=*/0}), 313 Succeeded()); 314 315 // A test for an instruction with three operands: ULEB128, expression length 316 // (ULEB128) and expression bytes. 317 auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) { 318 EXPECT_THAT_ERROR( 319 parseCFI(TestCIE, {Inst}), 320 FailedWithMessage("unable to decode LEB128 at offset 0x00000001: " 321 "malformed uleb128, extends past end")); 322 EXPECT_THAT_ERROR( 323 parseCFI(TestCIE, {Inst, /*Op1=*/0}), 324 FailedWithMessage("unable to decode LEB128 at offset 0x00000002: " 325 "malformed uleb128, extends past end")); 326 // A zero length expression is fine 327 EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst, 328 /*Op1=*/0, /*ExprLen=*/0}), 329 Succeeded()); 330 EXPECT_THAT_ERROR( 331 parseCFI(TestCIE, {Inst, 332 /*Op1=*/0, /*ExprLen=*/1}), 333 FailedWithMessage( 334 "unexpected end of data at offset 0x3 while reading [0x3, 0x4)")); 335 }; 336 337 for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression}) 338 CheckOp_ULEB128_Expr(Inst); 339 } 340 341 void expectDumpResult(const dwarf::UnwindLocation &Loc, 342 StringRef ExpectedFirstLine) { 343 std::string Output; 344 raw_string_ostream OS(Output); 345 OS << Loc; 346 StringRef FirstLine = StringRef(Output).split('\n').first; 347 EXPECT_EQ(FirstLine, ExpectedFirstLine); 348 } 349 350 TEST(DWARFDebugFrame, DumpUnwindLocations) { 351 // Test constructing unwind locations and dumping each kind. 352 constexpr int32_t PlusOff = 8; 353 constexpr int32_t MinusOff = -8; 354 constexpr uint8_t RegNum = 12; 355 expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified"); 356 expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined"); 357 expectDumpResult(dwarf::UnwindLocation::createSame(), "same"); 358 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff), 359 "CFA+8"); 360 expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff), 361 "CFA-8"); 362 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff), 363 "[CFA+8]"); 364 expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff), 365 "[CFA-8]"); 366 367 expectDumpResult( 368 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff), 369 "reg12+8"); 370 expectDumpResult( 371 dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff), 372 "reg12-8"); 373 expectDumpResult( 374 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff), 375 "[reg12+8]"); 376 expectDumpResult( 377 dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff), 378 "[reg12-8]"); 379 expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12"); 380 expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32"); 381 } 382 383 void expectDumpResult(const dwarf::RegisterLocations &Locs, 384 StringRef ExpectedFirstLine) { 385 std::string Output; 386 raw_string_ostream OS(Output); 387 OS << Locs; 388 StringRef FirstLine = StringRef(Output).split('\n').first; 389 EXPECT_EQ(FirstLine, ExpectedFirstLine); 390 } 391 392 TEST(DWARFDebugFrame, RegisterLocations) { 393 // Test the functionality of the RegisterLocations class. 394 dwarf::RegisterLocations Locs; 395 expectDumpResult(Locs, ""); 396 EXPECT_FALSE(Locs.hasLocations()); 397 // Set a register location for reg12 to unspecified and verify it dumps 398 // correctly. 399 Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified()); 400 EXPECT_TRUE(Locs.hasLocations()); 401 expectDumpResult(Locs, "reg12=unspecified"); 402 403 // Replace the register location for reg12 to "same" and verify it dumps 404 // correctly after it is modified 405 Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame()); 406 EXPECT_TRUE(Locs.hasLocations()); 407 expectDumpResult(Locs, "reg12=same"); 408 409 // Remove the register location for reg12 verify it dumps correctly after it 410 // is removed. 411 Locs.removeRegisterLocation(12); 412 EXPECT_FALSE(Locs.hasLocations()); 413 expectDumpResult(Locs, ""); 414 415 // Verify multiple registers added to the list dump correctly. 416 auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4); 417 auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8); 418 auto Reg14Loc = dwarf::UnwindLocation::createSame(); 419 Locs.setRegisterLocation(12, Reg12Loc); 420 Locs.setRegisterLocation(13, Reg13Loc); 421 Locs.setRegisterLocation(14, Reg14Loc); 422 EXPECT_TRUE(Locs.hasLocations()); 423 expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same"); 424 425 // Verify RegisterLocations::getRegisterLocation() works as expected. 426 std::optional<dwarf::UnwindLocation> OptionalLoc; 427 OptionalLoc = Locs.getRegisterLocation(0); 428 EXPECT_FALSE(OptionalLoc.has_value()); 429 430 OptionalLoc = Locs.getRegisterLocation(12); 431 EXPECT_TRUE(OptionalLoc.has_value()); 432 EXPECT_EQ(*OptionalLoc, Reg12Loc); 433 434 OptionalLoc = Locs.getRegisterLocation(13); 435 EXPECT_TRUE(OptionalLoc.has_value()); 436 EXPECT_EQ(*OptionalLoc, Reg13Loc); 437 438 OptionalLoc = Locs.getRegisterLocation(14); 439 EXPECT_TRUE(OptionalLoc.has_value()); 440 EXPECT_EQ(*OptionalLoc, Reg14Loc); 441 442 // Verify registers are correctly removed when multiple exist in the list. 443 Locs.removeRegisterLocation(13); 444 EXPECT_FALSE(Locs.getRegisterLocation(13).has_value()); 445 EXPECT_TRUE(Locs.hasLocations()); 446 expectDumpResult(Locs, "reg12=[CFA+4], reg14=same"); 447 Locs.removeRegisterLocation(14); 448 EXPECT_FALSE(Locs.getRegisterLocation(14).has_value()); 449 EXPECT_TRUE(Locs.hasLocations()); 450 expectDumpResult(Locs, "reg12=[CFA+4]"); 451 Locs.removeRegisterLocation(12); 452 EXPECT_FALSE(Locs.getRegisterLocation(12).has_value()); 453 EXPECT_FALSE(Locs.hasLocations()); 454 expectDumpResult(Locs, ""); 455 } 456 457 // Test that empty rows are not added to UnwindTable when 458 // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty. 459 TEST(DWARFDebugFrame, UnwindTableEmptyRows) { 460 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 461 /*Offset=*/0x0, 462 /*Length=*/0xff); 463 464 // Having an empty instructions list is fine. 465 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 466 EXPECT_TRUE(TestCIE.cfis().empty()); 467 468 // Verify dwarf::UnwindTable::create() won't result in errors and 469 // and empty rows are not added to CIE UnwindTable. 470 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 471 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 472 const size_t ExpectedNumOfRows = 0; 473 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 474 475 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 476 /*Offset=*/0x3333abcdabcd, 477 /*Length=*/0x4444abcdabcd, 478 /*CIEPointer=*/0x1111abcdabcd, 479 /*InitialLocation=*/0x1000, 480 /*AddressRange=*/0x1000, 481 /*Cie=*/&TestCIE, 482 /*LSDAAddress=*/std::nullopt, 483 /*Arch=*/Triple::x86_64); 484 485 // Having an empty instructions list is fine. 486 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 487 EXPECT_TRUE(TestFDE.cfis().empty()); 488 489 // Verify dwarf::UnwindTable::create() won't result in errors and 490 // and empty rows are not added to FDE UnwindTable. 491 RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 492 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 493 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 494 } 495 496 // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs 497 // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions. 498 TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) { 499 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 500 /*Offset=*/0x0, 501 /*Length=*/0xff); 502 503 // Make a CIE that has only DW_CFA_nop instructions. 504 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded()); 505 EXPECT_TRUE(!TestCIE.cfis().empty()); 506 507 // Verify dwarf::UnwindTable::create() won't result in errors and 508 // and empty rows are not added to CIE UnwindTable. 509 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 510 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 511 const size_t ExpectedNumOfRows = 0; 512 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 513 514 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 515 /*Offset=*/0x3333abcdabcd, 516 /*Length=*/0x4444abcdabcd, 517 /*CIEPointer=*/0x1111abcdabcd, 518 /*InitialLocation=*/0x1000, 519 /*AddressRange=*/0x1000, 520 /*Cie=*/&TestCIE, 521 /*LSDAAddress=*/std::nullopt, 522 /*Arch=*/Triple::x86_64); 523 524 // Make an FDE that has only DW_CFA_nop instructions. 525 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded()); 526 EXPECT_TRUE(!TestFDE.cfis().empty()); 527 528 // Verify dwarf::UnwindTable::create() won't result in errors and 529 // and empty rows are not added to FDE UnwindTable. 530 RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 531 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 532 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 533 } 534 535 TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 536 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 537 /*Offset=*/0x0, 538 /*Length=*/0xff); 539 540 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 541 /*Offset=*/0x3333abcdabcd, 542 /*Length=*/0x4444abcdabcd, 543 /*CIEPointer=*/0x1111abcdabcd, 544 /*InitialLocation=*/0x1000, 545 /*AddressRange=*/0x1000, 546 /*Cie=*/&TestCIE, 547 /*LSDAAddress=*/std::nullopt, 548 /*Arch=*/Triple::x86_64); 549 550 // Make a CIE that has a valid CFA definition. 551 constexpr uint8_t Reg = 12; 552 constexpr uint8_t Offset = 32; 553 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 554 Succeeded()); 555 556 // Make a FDE with DWARF call frame instruction opcodes that have valid 557 // syntax, but will cause an error when we parse them into a UnwindTable. 558 // Here we encode two DW_CFA_set_loc opcodes: 559 // DW_CFA_set_loc(0x1100) 560 // DW_CFA_set_loc(0x1000) 561 // These opcodes cause a new row to be appended to the rows in a UnwindTable 562 // and the resulting rows are not in ascending address order and should cause 563 // a state machine error. 564 EXPECT_THAT_ERROR( 565 parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 566 dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 567 Succeeded()); 568 569 // Verify we catch state machine error. 570 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 571 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 572 FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 573 " must be greater than the current row " 574 "address 0x1100")); 575 } 576 577 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 578 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 579 /*Offset=*/0x0, 580 /*Length=*/0xff); 581 582 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 583 /*Offset=*/0x3333abcdabcd, 584 /*Length=*/0x4444abcdabcd, 585 /*CIEPointer=*/0x1111abcdabcd, 586 /*InitialLocation=*/0x1000, 587 /*AddressRange=*/0x1000, 588 /*Cie=*/&TestCIE, 589 /*LSDAAddress=*/std::nullopt, 590 /*Arch=*/Triple::x86_64); 591 592 // Make a CIE that has a valid CFA definition. 593 constexpr uint8_t Reg = 12; 594 constexpr uint8_t Offset = 32; 595 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 596 Succeeded()); 597 598 // Make a FDE with DWARF call frame instruction opcodes that have valid 599 // syntax, but will cause an error when we parse them into a UnwindTable. 600 // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 601 // DW_CFA_remember_state, and an error should be returned. 602 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 603 Succeeded()); 604 605 // Verify we catch state machine error. 606 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 607 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 608 FailedWithMessage("DW_CFA_restore_state without a matching " 609 "previous DW_CFA_remember_state")); 610 } 611 612 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 613 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 614 /*Offset=*/0x0, 615 /*Length=*/0xff); 616 617 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 618 /*Offset=*/0x3333abcdabcd, 619 /*Length=*/0x4444abcdabcd, 620 /*CIEPointer=*/0x1111abcdabcd, 621 /*InitialLocation=*/0x1000, 622 /*AddressRange=*/0x1000, 623 /*Cie=*/&TestCIE, 624 /*LSDAAddress=*/std::nullopt, 625 /*Arch=*/Triple::x86_64); 626 627 // Make a CIE that has a valid CFA definition. 628 constexpr uint8_t Reg = 12; 629 constexpr uint8_t Offset = 32; 630 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 631 Succeeded()); 632 633 // Make a FDE with DWARF call frame instruction opcodes that have valid 634 // syntax, but will cause an error when we parse them into a UnwindTable. 635 // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 636 // found any documentation that describes what this does after some brief 637 // searching. 638 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 639 Succeeded()); 640 641 // Verify we catch state machine error. 642 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 643 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 644 FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 645 "architecture x86_64")); 646 } 647 648 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 649 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 650 /*Offset=*/0x0, 651 /*Length=*/0xff); 652 653 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 654 /*Offset=*/0x3333abcdabcd, 655 /*Length=*/0x4444abcdabcd, 656 /*CIEPointer=*/0x1111abcdabcd, 657 /*InitialLocation=*/0x1000, 658 /*AddressRange=*/0x1000, 659 /*Cie=*/&TestCIE, 660 /*LSDAAddress=*/std::nullopt, 661 /*Arch=*/Triple::x86_64); 662 663 // Make a CIE that has an invalid CFA definition. We do this so we can try 664 // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 665 // error back. 666 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 667 668 // Make a FDE with DWARF call frame instruction opcodes that have valid 669 // syntax, but will cause an error when we parse them into a UnwindTable. 670 // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 671 // didn't define the CFA in terms of a register plus offset, so this should 672 // cause an error. 673 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 674 Succeeded()); 675 676 // Verify we catch state machine error. 677 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 678 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 679 FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 680 "rule was not RegPlusOffset")); 681 } 682 683 TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 684 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 685 /*Offset=*/0x0, 686 /*Length=*/0xff); 687 688 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 689 /*Offset=*/0x3333abcdabcd, 690 /*Length=*/0x4444abcdabcd, 691 /*CIEPointer=*/0x1111abcdabcd, 692 /*InitialLocation=*/0x1000, 693 /*AddressRange=*/0x1000, 694 /*Cie=*/&TestCIE, 695 /*LSDAAddress=*/std::nullopt, 696 /*Arch=*/Triple::x86_64); 697 698 // Make a CIE that has an invalid CFA definition. We do this so we can try 699 // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 700 // appropriate error back. 701 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 702 703 // Make a FDE with DWARF call frame instruction opcodes that have valid 704 // syntax, but will cause an error when we parse them into a UnwindTable. 705 // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 706 // didn't define the CFA in terms of a register plus offset, so this should 707 // cause an error. 708 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 709 Succeeded()); 710 711 // Verify we catch state machine error. 712 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 713 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 714 FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 715 "rule was not RegPlusOffset")); 716 } 717 718 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 719 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 720 /*Offset=*/0x0, 721 /*Length=*/0xff); 722 723 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 724 /*Offset=*/0x3333abcdabcd, 725 /*Length=*/0x4444abcdabcd, 726 /*CIEPointer=*/0x1111abcdabcd, 727 /*InitialLocation=*/0x1000, 728 /*AddressRange=*/0x1000, 729 /*Cie=*/&TestCIE, 730 /*LSDAAddress=*/std::nullopt, 731 /*Arch=*/Triple::x86_64); 732 733 // Make a CIE that has only defines the CFA register with no offset. Some 734 // architectures do this and we must ensure that we set the CFA value to be 735 // equal to that register with no offset. 736 constexpr uint8_t CFAReg = 12; 737 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 738 Succeeded()); 739 740 // Make a FDE with DWARF call frame instruction opcodes that have valid 741 // syntax, but will cause an error when we parse them into a UnwindTable. 742 // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 743 // our CIE didn't define the CFA in terms of a register plus offset, so this 744 // should cause an error. 745 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 746 747 // Verify we catch state machine error. 748 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 749 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 750 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 751 EXPECT_EQ(Rows.size(), 1u); 752 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 753 EXPECT_EQ(Rows[0].getCFAValue(), 754 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 755 } 756 757 TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 758 // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 759 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 760 /*Offset=*/0x0, 761 /*Length=*/0xff); 762 763 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 764 /*Offset=*/0x3333abcdabcd, 765 /*Length=*/0x4444abcdabcd, 766 /*CIEPointer=*/0x1111abcdabcd, 767 /*InitialLocation=*/0x1000, 768 /*AddressRange=*/0x1000, 769 /*Cie=*/&TestCIE, 770 /*LSDAAddress=*/std::nullopt, 771 /*Arch=*/Triple::x86_64); 772 773 // Make a CIE that has a valid CFA definition and a single register unwind 774 // rule for register that we will verify is in all of the pushed rows. 775 constexpr uint8_t CFAReg = 12; 776 constexpr uint8_t CFAOffset = 32; 777 constexpr uint8_t Reg = 13; 778 constexpr uint8_t InReg = 14; 779 780 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 781 dwarf::DW_CFA_register, Reg, InReg}), 782 Succeeded()); 783 784 // Make a FDE with DWARF call frame instruction opcodes that use all of the 785 // row pushing opcodes. This will verify that all opcodes that should create 786 // a row are correctly working. Each opcode will push a row prior to 787 // advancing the address, and then a row will be automatically pushed at the 788 // end of the parsing, so we should end up with 6 rows starting at address 789 // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 790 // from the CIE. 791 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 792 dwarf::DW_CFA_advance_loc1, 793 4, 794 dwarf::DW_CFA_advance_loc2, 795 4, 796 0, 797 dwarf::DW_CFA_advance_loc4, 798 4, 799 0, 800 0, 801 0, 802 dwarf::DW_CFA_set_loc, 803 0x14, 804 0x10, 805 0, 806 0, 807 0, 808 0, 809 0, 810 0}), 811 Succeeded()); 812 813 // Create locations that we expect the UnwindRow objects to contain after 814 // parsing the DWARF call frame instructions. 815 dwarf::RegisterLocations VerifyLocs; 816 VerifyLocs.setRegisterLocation( 817 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 818 819 // Verify we catch state machine error. 820 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 821 ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 822 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 823 EXPECT_EQ(Rows.size(), 6u); 824 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 825 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 826 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 827 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 828 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 829 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 830 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 831 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 832 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 833 EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 834 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 835 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 836 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 837 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 838 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 839 EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 840 EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 841 EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 842 } 843 844 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 845 // Test that DW_CFA_restore works as expected when parsed in the state 846 // machine. 847 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 848 /*Offset=*/0x0, 849 /*Length=*/0xff); 850 851 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 852 /*Offset=*/0x3333abcdabcd, 853 /*Length=*/0x4444abcdabcd, 854 /*CIEPointer=*/0x1111abcdabcd, 855 /*InitialLocation=*/0x1000, 856 /*AddressRange=*/0x1000, 857 /*Cie=*/&TestCIE, 858 /*LSDAAddress=*/std::nullopt, 859 /*Arch=*/Triple::x86_64); 860 861 // Make a CIE that has a valid CFA definition and a single register unwind 862 // rule for register that we will verify is in all of the pushed rows. 863 constexpr uint8_t CFAReg = 12; 864 constexpr uint8_t CFAOffset = 32; 865 constexpr uint8_t Reg = 13; 866 constexpr uint8_t InReg = 14; 867 constexpr int32_t RegCFAOffset = -8; 868 869 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 870 dwarf::DW_CFA_register, Reg, InReg}), 871 Succeeded()); 872 873 // Make a FDE with DWARF call frame instruction opcodes that changes the rule 874 // for register "Reg" to be [CFA-8], then push a row, and then restore the 875 // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 876 // two rows: 877 // - one with Reg = [CFA-8] 878 // - one with Reg = InReg 879 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 880 dwarf::DW_CFA_advance_loc | 4, 881 dwarf::DW_CFA_restore | Reg}), 882 Succeeded()); 883 884 // Create locations that we expect the UnwindRow objects to contain after 885 // parsing the DWARF call frame instructions. 886 dwarf::RegisterLocations VerifyLocs1; 887 VerifyLocs1.setRegisterLocation( 888 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 889 890 dwarf::RegisterLocations VerifyLocs2; 891 VerifyLocs2.setRegisterLocation( 892 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 893 894 // Verify we catch state machine error. 895 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 896 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 897 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 898 EXPECT_EQ(Rows.size(), 2u); 899 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 900 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 901 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 902 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 903 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 904 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 905 } 906 907 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 908 // Test that DW_CFA_restore works as expected when parsed in the state 909 // machine. 910 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 911 /*Offset=*/0x0, 912 /*Length=*/0xff); 913 914 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 915 /*Offset=*/0x3333abcdabcd, 916 /*Length=*/0x4444abcdabcd, 917 /*CIEPointer=*/0x1111abcdabcd, 918 /*InitialLocation=*/0x1000, 919 /*AddressRange=*/0x1000, 920 /*Cie=*/&TestCIE, 921 /*LSDAAddress=*/std::nullopt, 922 /*Arch=*/Triple::x86_64); 923 924 // Make a CIE that has a valid CFA definition and a single register unwind 925 // rule for register that we will verify is in all of the pushed rows. 926 constexpr uint8_t CFAReg = 12; 927 constexpr uint8_t CFAOffset = 32; 928 constexpr uint8_t Reg = 13; 929 constexpr uint8_t InReg = 14; 930 constexpr int32_t RegCFAOffset = -8; 931 932 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 933 dwarf::DW_CFA_register, Reg, InReg}), 934 Succeeded()); 935 936 // Make a FDE with DWARF call frame instruction opcodes that changes the rule 937 // for register "Reg" to be [CFA-8], then push a row, and then restore the 938 // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 939 // end up with two rows: 940 // - one with Reg = [CFA-8] 941 // - one with Reg = InReg 942 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 943 dwarf::DW_CFA_advance_loc | 4, 944 dwarf::DW_CFA_restore_extended, Reg}), 945 Succeeded()); 946 947 // Create locations that we expect the UnwindRow objects to contain after 948 // parsing the DWARF call frame instructions. 949 dwarf::RegisterLocations VerifyLocs1; 950 VerifyLocs1.setRegisterLocation( 951 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 952 953 dwarf::RegisterLocations VerifyLocs2; 954 VerifyLocs2.setRegisterLocation( 955 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 956 957 // Verify we catch state machine error. 958 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 959 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 960 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 961 EXPECT_EQ(Rows.size(), 2u); 962 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 963 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 964 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 965 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 966 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 967 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 968 } 969 970 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 971 // Test that DW_CFA_offset, DW_CFA_offset_extended and 972 // DW_CFA_offset_extended_sf work as expected when parsed in the state 973 // machine. 974 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 975 /*Offset=*/0x0, 976 /*Length=*/0xff); 977 978 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 979 /*Offset=*/0x3333abcdabcd, 980 /*Length=*/0x4444abcdabcd, 981 /*CIEPointer=*/0x1111abcdabcd, 982 /*InitialLocation=*/0x1000, 983 /*AddressRange=*/0x1000, 984 /*Cie=*/&TestCIE, 985 /*LSDAAddress=*/std::nullopt, 986 /*Arch=*/Triple::x86_64); 987 988 // Make a CIE that has a valid CFA definition and a single register unwind 989 // rule for register that we will verify is in all of the pushed rows. 990 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 991 Succeeded()); 992 993 // Make a FDE with DWARF call frame instruction opcodes that changes the 994 // unwind rules for the follwing registers: 995 // Reg1 = [CFA-8] 996 // Reg2 = [CFA-16] 997 // Reg3 = [CFA+8] 998 constexpr uint8_t Reg1 = 14; 999 constexpr uint8_t Reg2 = 15; 1000 constexpr uint8_t Reg3 = 16; 1001 constexpr uint8_t Neg1SLEB = 0x7f; 1002 EXPECT_THAT_ERROR( 1003 parseCFI(TestFDE, 1004 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 1005 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 1006 Succeeded()); 1007 1008 // Create locations that we expect the UnwindRow objects to contain after 1009 // parsing the DWARF call frame instructions. 1010 dwarf::RegisterLocations VerifyLocs; 1011 VerifyLocs.setRegisterLocation( 1012 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1013 VerifyLocs.setRegisterLocation( 1014 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1015 VerifyLocs.setRegisterLocation( 1016 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 1017 1018 // Verify we catch state machine error. 1019 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1020 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1021 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1022 EXPECT_EQ(Rows.size(), 1u); 1023 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1024 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1025 } 1026 1027 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 1028 // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 1029 // parsed in the state machine. 1030 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1031 /*Offset=*/0x0, 1032 /*Length=*/0xff); 1033 1034 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1035 /*Offset=*/0x3333abcdabcd, 1036 /*Length=*/0x4444abcdabcd, 1037 /*CIEPointer=*/0x1111abcdabcd, 1038 /*InitialLocation=*/0x1000, 1039 /*AddressRange=*/0x1000, 1040 /*Cie=*/&TestCIE, 1041 /*LSDAAddress=*/std::nullopt, 1042 /*Arch=*/Triple::x86_64); 1043 1044 // Make a CIE that has a valid CFA definition and a single register unwind 1045 // rule for register that we will verify is in all of the pushed rows. 1046 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1047 Succeeded()); 1048 1049 // Make a FDE with DWARF call frame instruction opcodes that changes the 1050 // unwind rules for the follwing registers: 1051 // Reg1 = [CFA-8] 1052 // Reg2 = [CFA-16] 1053 // Reg3 = [CFA+8] 1054 constexpr uint8_t Reg1 = 14; 1055 constexpr uint8_t Reg2 = 15; 1056 constexpr uint8_t Neg1SLEB = 0x7f; 1057 EXPECT_THAT_ERROR( 1058 parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 1059 dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 1060 Succeeded()); 1061 1062 // Create locations that we expect the UnwindRow objects to contain after 1063 // parsing the DWARF call frame instructions. 1064 dwarf::RegisterLocations VerifyLocs; 1065 VerifyLocs.setRegisterLocation( 1066 Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 1067 VerifyLocs.setRegisterLocation( 1068 Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 1069 1070 // Verify we catch state machine error. 1071 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1072 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1073 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1074 EXPECT_EQ(Rows.size(), 1u); 1075 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1076 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1077 } 1078 1079 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 1080 // Test that DW_CFA_nop works as expected when parsed in the state machine. 1081 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1082 /*Offset=*/0x0, 1083 /*Length=*/0xff); 1084 1085 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1086 /*Offset=*/0x3333abcdabcd, 1087 /*Length=*/0x4444abcdabcd, 1088 /*CIEPointer=*/0x1111abcdabcd, 1089 /*InitialLocation=*/0x1000, 1090 /*AddressRange=*/0x1000, 1091 /*Cie=*/&TestCIE, 1092 /*LSDAAddress=*/std::nullopt, 1093 /*Arch=*/Triple::x86_64); 1094 1095 // Make a CIE that has a valid CFA definition and a single register unwind 1096 // rule for register that we will verify is in all of the pushed rows. 1097 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1098 Succeeded()); 1099 1100 // Make a FDE with DWARF call frame instruction opcodes that changes the 1101 // unwind rules for the follwing registers: 1102 // Reg1 = [CFA-8] 1103 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1104 constexpr uint8_t Reg1 = 14; 1105 EXPECT_THAT_ERROR( 1106 parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1107 Succeeded()); 1108 1109 // Create locations that we expect the UnwindRow objects to contain after 1110 // parsing the DWARF call frame instructions. 1111 dwarf::RegisterLocations VerifyLocs; 1112 VerifyLocs.setRegisterLocation( 1113 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1114 1115 // Verify we catch state machine error. 1116 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1117 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1118 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1119 EXPECT_EQ(Rows.size(), 1u); 1120 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1121 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1122 } 1123 1124 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1125 // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1126 // when parsed in the state machine. 1127 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1128 /*Offset=*/0x0, 1129 /*Length=*/0xff); 1130 1131 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1132 /*Offset=*/0x3333abcdabcd, 1133 /*Length=*/0x4444abcdabcd, 1134 /*CIEPointer=*/0x1111abcdabcd, 1135 /*InitialLocation=*/0x1000, 1136 /*AddressRange=*/0x1000, 1137 /*Cie=*/&TestCIE, 1138 /*LSDAAddress=*/std::nullopt, 1139 /*Arch=*/Triple::x86_64); 1140 1141 // Make a CIE that has a valid CFA definition and a single register unwind 1142 // rule for register that we will verify is in all of the pushed rows. 1143 constexpr uint8_t CFAOff1 = 32; 1144 constexpr uint8_t CFAOff2 = 16; 1145 constexpr uint8_t Reg1 = 14; 1146 constexpr uint8_t Reg2 = 15; 1147 constexpr uint8_t Reg3 = 16; 1148 1149 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, CFAOff1}), 1150 Succeeded()); 1151 1152 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1153 // follwing rows: 1154 // 0x1000: CFA=reg12+CFAOff1: Reg1=[CFA-8] 1155 // 0x1004: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16] 1156 // 0x1008: CFA=reg12+CFAOff2: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1157 // 0x100C: CFA=reg12+CFAOff1: Reg1=[CFA-8] Reg2=[CFA-16] 1158 // 0x1010: CFA=reg12+CFAOff1: Reg1=[CFA-8] 1159 // This state machine will: 1160 // - set Reg1 location 1161 // - push a row (from DW_CFA_advance_loc) 1162 // - remember the state 1163 // - set Reg2 location 1164 // - push a row (from DW_CFA_advance_loc) 1165 // - remember the state 1166 // - set CFA offset to CFAOff2 1167 // - set Reg3 location 1168 // - push a row (from DW_CFA_advance_loc) 1169 // - remember the state where Reg1 and Reg2 were set 1170 // - push a row (from DW_CFA_advance_loc) 1171 // - remember the state where only Reg1 was set 1172 // - push a row (automatically at the end of instruction parsing) 1173 // Then we verify that all registers are correct in all generated rows. 1174 EXPECT_THAT_ERROR( 1175 parseCFI(TestFDE, 1176 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1177 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1178 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1179 dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1180 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1181 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1182 dwarf::DW_CFA_restore_state}), 1183 Succeeded()); 1184 1185 // Create locations that we expect the UnwindRow objects to contain after 1186 // parsing the DWARF call frame instructions. 1187 dwarf::RegisterLocations VerifyLocs1; 1188 VerifyLocs1.setRegisterLocation( 1189 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1190 1191 dwarf::RegisterLocations VerifyLocs2; 1192 VerifyLocs2.setRegisterLocation( 1193 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1194 VerifyLocs2.setRegisterLocation( 1195 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1196 1197 dwarf::RegisterLocations VerifyLocs3; 1198 VerifyLocs3.setRegisterLocation( 1199 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1200 VerifyLocs3.setRegisterLocation( 1201 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1202 VerifyLocs3.setRegisterLocation( 1203 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 1204 1205 // Verify we catch state machine error. 1206 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1207 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1208 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1209 EXPECT_EQ(Rows.size(), 5u); 1210 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1211 EXPECT_EQ(Rows[0].getCFAValue(), 1212 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1)); 1213 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1214 1215 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1216 EXPECT_EQ(Rows[1].getCFAValue(), 1217 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1)); 1218 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1219 1220 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1221 EXPECT_EQ(Rows[2].getCFAValue(), 1222 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff2)); 1223 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1224 1225 EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1226 EXPECT_EQ(Rows[3].getCFAValue(), 1227 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1)); 1228 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1229 1230 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1231 EXPECT_EQ(Rows[4].getCFAValue(), 1232 dwarf::UnwindLocation::createIsRegisterPlusOffset(12, CFAOff1)); 1233 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1234 } 1235 1236 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1237 // Test that DW_CFA_undefined works as expected when parsed in the state 1238 // machine. 1239 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1240 /*Offset=*/0x0, 1241 /*Length=*/0xff); 1242 1243 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1244 /*Offset=*/0x3333abcdabcd, 1245 /*Length=*/0x4444abcdabcd, 1246 /*CIEPointer=*/0x1111abcdabcd, 1247 /*InitialLocation=*/0x1000, 1248 /*AddressRange=*/0x1000, 1249 /*Cie=*/&TestCIE, 1250 /*LSDAAddress=*/std::nullopt, 1251 /*Arch=*/Triple::x86_64); 1252 1253 // Make a CIE that has a valid CFA definition and a single register unwind 1254 // rule for register that we will verify is in all of the pushed rows. 1255 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1256 Succeeded()); 1257 1258 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1259 // follwing rows: 1260 // 0x1000: CFA=reg12+32: Reg1=undefined 1261 // Then we verify that all registers are correct in all generated rows. 1262 constexpr uint8_t Reg1 = 14; 1263 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1264 Succeeded()); 1265 1266 // Create locations that we expect the UnwindRow objects to contain after 1267 // parsing the DWARF call frame instructions. 1268 dwarf::RegisterLocations VerifyLocs; 1269 VerifyLocs.setRegisterLocation(Reg1, 1270 dwarf::UnwindLocation::createUndefined()); 1271 1272 // Verify we catch state machine error. 1273 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1274 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1275 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1276 EXPECT_EQ(Rows.size(), 1u); 1277 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1278 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1279 } 1280 1281 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1282 // Test that DW_CFA_same_value works as expected when parsed in the state 1283 // machine. 1284 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1285 /*Offset=*/0x0, 1286 /*Length=*/0xff); 1287 1288 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1289 /*Offset=*/0x3333abcdabcd, 1290 /*Length=*/0x4444abcdabcd, 1291 /*CIEPointer=*/0x1111abcdabcd, 1292 /*InitialLocation=*/0x1000, 1293 /*AddressRange=*/0x1000, 1294 /*Cie=*/&TestCIE, 1295 /*LSDAAddress=*/std::nullopt, 1296 /*Arch=*/Triple::x86_64); 1297 1298 // Make a CIE that has a valid CFA definition and a single register unwind 1299 // rule for register that we will verify is in all of the pushed rows. 1300 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1301 Succeeded()); 1302 1303 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1304 // follwing rows: 1305 // 0x1000: CFA=reg12+32: Reg1=same 1306 // Then we verify that all registers are correct in all generated rows. 1307 constexpr uint8_t Reg1 = 14; 1308 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1309 Succeeded()); 1310 1311 // Create locations that we expect the UnwindRow objects to contain after 1312 // parsing the DWARF call frame instructions. 1313 dwarf::RegisterLocations VerifyLocs; 1314 VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1315 1316 // Verify we catch state machine error. 1317 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1318 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1319 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1320 EXPECT_EQ(Rows.size(), 1u); 1321 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1322 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1323 } 1324 1325 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1326 // Test that DW_CFA_register works as expected when parsed in the state 1327 // machine. 1328 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1329 /*Offset=*/0x0, 1330 /*Length=*/0xff); 1331 1332 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1333 /*Offset=*/0x3333abcdabcd, 1334 /*Length=*/0x4444abcdabcd, 1335 /*CIEPointer=*/0x1111abcdabcd, 1336 /*InitialLocation=*/0x1000, 1337 /*AddressRange=*/0x1000, 1338 /*Cie=*/&TestCIE, 1339 /*LSDAAddress=*/std::nullopt, 1340 /*Arch=*/Triple::x86_64); 1341 1342 // Make a CIE that has a valid CFA definition and a single register unwind 1343 // rule for register that we will verify is in all of the pushed rows. 1344 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1345 Succeeded()); 1346 1347 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1348 // follwing rows: 1349 // 0x1000: CFA=reg12+32: Reg1=same 1350 // Then we verify that all registers are correct in all generated rows. 1351 constexpr uint8_t Reg = 13; 1352 constexpr uint8_t InReg = 14; 1353 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1354 Succeeded()); 1355 1356 // Create locations that we expect the UnwindRow objects to contain after 1357 // parsing the DWARF call frame instructions. 1358 dwarf::RegisterLocations VerifyLocs; 1359 VerifyLocs.setRegisterLocation( 1360 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1361 1362 // Verify we catch state machine error. 1363 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1364 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1365 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1366 EXPECT_EQ(Rows.size(), 1u); 1367 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1368 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1369 } 1370 1371 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1372 // Test that DW_CFA_expression works as expected when parsed in the state 1373 // machine. 1374 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1375 /*Offset=*/0x0, 1376 /*Length=*/0xff); 1377 1378 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1379 /*Offset=*/0x3333abcdabcd, 1380 /*Length=*/0x4444abcdabcd, 1381 /*CIEPointer=*/0x1111abcdabcd, 1382 /*InitialLocation=*/0x1000, 1383 /*AddressRange=*/0x1000, 1384 /*Cie=*/&TestCIE, 1385 /*LSDAAddress=*/std::nullopt, 1386 /*Arch=*/Triple::x86_64); 1387 1388 // Make a CIE that has a valid CFA definition and a single register unwind 1389 // rule for register that we will verify is in all of the pushed rows. 1390 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1391 Succeeded()); 1392 1393 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1394 // follwing rows: 1395 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1396 // Then we verify that all registers are correct in all generated rows. 1397 constexpr uint8_t Reg = 13; 1398 constexpr uint8_t AddrSize = 8; 1399 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1400 dwarf::DW_OP_reg12}; 1401 1402 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1403 1404 // Create locations that we expect the UnwindRow objects to contain after 1405 // parsing the DWARF call frame instructions. 1406 dwarf::RegisterLocations VerifyLocs; 1407 1408 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1409 DataExtractor ExprData(ExprBytes, true, AddrSize); 1410 DWARFExpression Expr(ExprData, AddrSize); 1411 VerifyLocs.setRegisterLocation( 1412 Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1413 1414 // Verify we catch state machine error. 1415 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1416 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1417 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1418 EXPECT_EQ(Rows.size(), 1u); 1419 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1420 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1421 } 1422 1423 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1424 // Test that DW_CFA_val_expression works as expected when parsed in the state 1425 // machine. 1426 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1427 /*Offset=*/0x0, 1428 /*Length=*/0xff); 1429 1430 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1431 /*Offset=*/0x3333abcdabcd, 1432 /*Length=*/0x4444abcdabcd, 1433 /*CIEPointer=*/0x1111abcdabcd, 1434 /*InitialLocation=*/0x1000, 1435 /*AddressRange=*/0x1000, 1436 /*Cie=*/&TestCIE, 1437 /*LSDAAddress=*/std::nullopt, 1438 /*Arch=*/Triple::x86_64); 1439 1440 // Make a CIE that has a valid CFA definition and a single register unwind 1441 // rule for register that we will verify is in all of the pushed rows. 1442 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1443 Succeeded()); 1444 1445 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1446 // follwing rows: 1447 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1448 // Then we verify that all registers are correct in all generated rows. 1449 constexpr uint8_t Reg = 13; 1450 constexpr uint8_t AddrSize = 8; 1451 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1452 dwarf::DW_OP_reg12}; 1453 1454 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1455 1456 // Create locations that we expect the UnwindRow objects to contain after 1457 // parsing the DWARF call frame instructions. 1458 dwarf::RegisterLocations VerifyLocs; 1459 1460 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1461 DataExtractor ExprData(ExprBytes, true, AddrSize); 1462 DWARFExpression Expr(ExprData, AddrSize); 1463 VerifyLocs.setRegisterLocation( 1464 Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1465 1466 // Verify we catch state machine error. 1467 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1468 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1469 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1470 EXPECT_EQ(Rows.size(), 1u); 1471 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1472 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1473 } 1474 1475 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1476 // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1477 // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1478 // parsed in the state machine. 1479 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1480 /*Offset=*/0x0, 1481 /*Length=*/0xff); 1482 1483 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1484 /*Offset=*/0x3333abcdabcd, 1485 /*Length=*/0x4444abcdabcd, 1486 /*CIEPointer=*/0x1111abcdabcd, 1487 /*InitialLocation=*/0x1000, 1488 /*AddressRange=*/0x1000, 1489 /*Cie=*/&TestCIE, 1490 /*LSDAAddress=*/std::nullopt, 1491 /*Arch=*/Triple::x86_64); 1492 1493 // Make a CIE that has a valid CFA definition and a single register unwind 1494 // rule for register that we will verify is in all of the pushed rows. 1495 constexpr uint8_t CFAReg1 = 12; 1496 constexpr uint8_t CFAOff1 = 32; 1497 constexpr uint8_t CFAReg2 = 13; 1498 constexpr uint8_t CFAOff2 = 48; 1499 constexpr uint8_t Reg = 13; 1500 constexpr uint8_t InReg = 14; 1501 1502 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1503 dwarf::DW_CFA_register, Reg, InReg}), 1504 Succeeded()); 1505 1506 // Make a FDE with DWARF call frame instruction opcodes that use all of the 1507 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1508 // create a row are correctly working. 1509 EXPECT_THAT_ERROR( 1510 parseCFI( 1511 TestFDE, 1512 { 1513 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1514 CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1515 dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1516 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1517 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1518 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1519 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1520 }), 1521 Succeeded()); 1522 1523 // Create locations that we expect the UnwindRow objects to contain after 1524 // parsing the DWARF call frame instructions. 1525 dwarf::RegisterLocations VerifyLocs; 1526 VerifyLocs.setRegisterLocation( 1527 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1528 1529 // Verify we catch state machine error. 1530 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1531 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1532 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1533 EXPECT_EQ(Rows.size(), 5u); 1534 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1535 EXPECT_EQ( 1536 Rows[0].getCFAValue(), 1537 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1538 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1539 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1540 1541 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1542 EXPECT_EQ( 1543 Rows[1].getCFAValue(), 1544 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1545 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1546 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1547 1548 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1549 EXPECT_EQ( 1550 Rows[2].getCFAValue(), 1551 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1552 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1553 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1554 1555 EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1556 EXPECT_EQ( 1557 Rows[3].getCFAValue(), 1558 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1559 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1560 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1561 1562 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1563 EXPECT_EQ( 1564 Rows[4].getCFAValue(), 1565 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1566 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1567 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1568 } 1569 1570 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) { 1571 // Test that DW_CFA_LLVM_def_aspace_cfa, DW_CFA_LLVM_def_aspace_cfa_sf, 1572 // DW_CFA_def_cfa_register, DW_CFA_def_cfa_offset, and 1573 // DW_CFA_def_cfa_offset_sf works as expected when parsed in the state 1574 // machine. 1575 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1576 /*Offset=*/0x0, 1577 /*Length=*/0xff); 1578 1579 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1580 /*Offset=*/0x3333abcdabcd, 1581 /*Length=*/0x4444abcdabcd, 1582 /*CIEPointer=*/0x1111abcdabcd, 1583 /*InitialLocation=*/0x1000, 1584 /*AddressRange=*/0x1000, 1585 /*Cie=*/&TestCIE, 1586 /*LSDAAddress=*/std::nullopt, 1587 /*Arch=*/Triple::x86_64); 1588 1589 // Make a CIE that has a valid CFA definition and a single register unwind 1590 // rule for register that we will verify is in all of the pushed rows. 1591 constexpr uint8_t CFAReg1 = 12; 1592 constexpr uint8_t CFAOff1 = 32; 1593 constexpr uint8_t CFAReg2 = 13; 1594 constexpr uint8_t CFAOff2 = 48; 1595 constexpr uint8_t Reg = 13; 1596 constexpr uint8_t InReg = 14; 1597 constexpr uint8_t AddrSpace = 2; 1598 1599 EXPECT_THAT_ERROR( 1600 parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1, 1601 AddrSpace, dwarf::DW_CFA_register, Reg, InReg}), 1602 Succeeded()); 1603 1604 // Make a FDE with DWARF call frame instruction opcodes that use all of the 1605 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1606 // create a row are correctly working. 1607 EXPECT_THAT_ERROR( 1608 parseCFI( 1609 TestFDE, 1610 { 1611 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1612 CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1613 dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1614 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1615 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1616 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1617 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1618 }), 1619 Succeeded()); 1620 1621 // Create locations that we expect the UnwindRow objects to contain after 1622 // parsing the DWARF call frame instructions. 1623 dwarf::RegisterLocations VerifyLocs; 1624 VerifyLocs.setRegisterLocation( 1625 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1626 1627 // Verify we catch state machine error. 1628 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1629 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1630 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1631 EXPECT_EQ(Rows.size(), 5u); 1632 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1633 EXPECT_EQ(Rows[0].getCFAValue(), 1634 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1, 1635 AddrSpace)); 1636 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1637 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1638 1639 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1640 EXPECT_EQ(Rows[1].getCFAValue(), 1641 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1642 AddrSpace)); 1643 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1644 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1645 1646 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1647 EXPECT_EQ(Rows[2].getCFAValue(), 1648 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2, 1649 AddrSpace)); 1650 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1651 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1652 1653 EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1654 EXPECT_EQ(Rows[3].getCFAValue(), 1655 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1, 1656 AddrSpace)); 1657 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1658 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1659 1660 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1661 EXPECT_EQ(Rows[4].getCFAValue(), 1662 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2, 1663 AddrSpace)); 1664 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1665 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1666 } 1667 1668 } // end anonymous namespace 1669