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