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