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