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