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 that empty rows are not added to UnwindTable when 451 // dwarf::CIE::CFIs or dwarf::FDE::CFIs is empty. 452 TEST(DWARFDebugFrame, UnwindTableEmptyRows) { 453 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 454 /*Offset=*/0x0, 455 /*Length=*/0xff); 456 457 // Having an empty instructions list is fine. 458 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 459 EXPECT_TRUE(TestCIE.cfis().empty()); 460 461 // Verify dwarf::UnwindTable::create() won't result in errors and 462 // and empty rows are not added to CIE UnwindTable. 463 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 464 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 465 const size_t ExpectedNumOfRows = 0; 466 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 467 468 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 469 /*Offset=*/0x3333abcdabcd, 470 /*Length=*/0x4444abcdabcd, 471 /*CIEPointer=*/0x1111abcdabcd, 472 /*InitialLocation=*/0x1000, 473 /*AddressRange=*/0x1000, 474 /*Cie=*/&TestCIE, 475 /*LSDAAddress=*/None, 476 /*Arch=*/Triple::x86_64); 477 478 // Having an empty instructions list is fine. 479 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 480 EXPECT_TRUE(TestFDE.cfis().empty()); 481 482 // Verify dwarf::UnwindTable::create() won't result in errors and 483 // and empty rows are not added to FDE UnwindTable. 484 RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 485 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 486 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 487 } 488 489 // Test that empty rows are not added to UnwindTable when dwarf::CIE::CFIs 490 // or dwarf::FDE::CFIs is not empty but has only DW_CFA_nop instructions. 491 TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) { 492 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 493 /*Offset=*/0x0, 494 /*Length=*/0xff); 495 496 // Make a CIE that has only DW_CFA_nop instructions. 497 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded()); 498 EXPECT_TRUE(!TestCIE.cfis().empty()); 499 500 // Verify dwarf::UnwindTable::create() won't result in errors and 501 // and empty rows are not added to CIE UnwindTable. 502 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE); 503 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 504 const size_t ExpectedNumOfRows = 0; 505 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 506 507 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 508 /*Offset=*/0x3333abcdabcd, 509 /*Length=*/0x4444abcdabcd, 510 /*CIEPointer=*/0x1111abcdabcd, 511 /*InitialLocation=*/0x1000, 512 /*AddressRange=*/0x1000, 513 /*Cie=*/&TestCIE, 514 /*LSDAAddress=*/None, 515 /*Arch=*/Triple::x86_64); 516 517 // Make an FDE that has only DW_CFA_nop instructions. 518 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded()); 519 EXPECT_TRUE(!TestFDE.cfis().empty()); 520 521 // Verify dwarf::UnwindTable::create() won't result in errors and 522 // and empty rows are not added to FDE UnwindTable. 523 RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 524 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 525 EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows); 526 } 527 528 TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) { 529 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 530 /*Offset=*/0x0, 531 /*Length=*/0xff); 532 533 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 534 /*Offset=*/0x3333abcdabcd, 535 /*Length=*/0x4444abcdabcd, 536 /*CIEPointer=*/0x1111abcdabcd, 537 /*InitialLocation=*/0x1000, 538 /*AddressRange=*/0x1000, 539 /*Cie=*/&TestCIE, 540 /*LSDAAddress=*/None, 541 /*Arch=*/Triple::x86_64); 542 543 // Make a CIE that has a valid CFA definition. 544 constexpr uint8_t Reg = 12; 545 constexpr uint8_t Offset = 32; 546 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 547 Succeeded()); 548 549 // Make a FDE with DWARF call frame instruction opcodes that have valid 550 // syntax, but will cause an error when we parse them into a UnwindTable. 551 // Here we encode two DW_CFA_set_loc opcodes: 552 // DW_CFA_set_loc(0x1100) 553 // DW_CFA_set_loc(0x1000) 554 // These opcodes cause a new row to be appended to the rows in a UnwindTable 555 // and the resulting rows are not in ascending address order and should cause 556 // a state machine error. 557 EXPECT_THAT_ERROR( 558 parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0, 559 dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}), 560 Succeeded()); 561 562 // Verify we catch state machine error. 563 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 564 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 565 FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which" 566 " must be greater than the current row " 567 "address 0x1100")); 568 } 569 570 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) { 571 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 572 /*Offset=*/0x0, 573 /*Length=*/0xff); 574 575 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 576 /*Offset=*/0x3333abcdabcd, 577 /*Length=*/0x4444abcdabcd, 578 /*CIEPointer=*/0x1111abcdabcd, 579 /*InitialLocation=*/0x1000, 580 /*AddressRange=*/0x1000, 581 /*Cie=*/&TestCIE, 582 /*LSDAAddress=*/None, 583 /*Arch=*/Triple::x86_64); 584 585 // Make a CIE that has a valid CFA definition. 586 constexpr uint8_t Reg = 12; 587 constexpr uint8_t Offset = 32; 588 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 589 Succeeded()); 590 591 // Make a FDE with DWARF call frame instruction opcodes that have valid 592 // syntax, but will cause an error when we parse them into a UnwindTable. 593 // Here we encode a DW_CFA_restore_state opcode that was not preceded by a 594 // DW_CFA_remember_state, and an error should be returned. 595 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}), 596 Succeeded()); 597 598 // Verify we catch state machine error. 599 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 600 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 601 FailedWithMessage("DW_CFA_restore_state without a matching " 602 "previous DW_CFA_remember_state")); 603 } 604 605 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) { 606 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 607 /*Offset=*/0x0, 608 /*Length=*/0xff); 609 610 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 611 /*Offset=*/0x3333abcdabcd, 612 /*Length=*/0x4444abcdabcd, 613 /*CIEPointer=*/0x1111abcdabcd, 614 /*InitialLocation=*/0x1000, 615 /*AddressRange=*/0x1000, 616 /*Cie=*/&TestCIE, 617 /*LSDAAddress=*/None, 618 /*Arch=*/Triple::x86_64); 619 620 // Make a CIE that has a valid CFA definition. 621 constexpr uint8_t Reg = 12; 622 constexpr uint8_t Offset = 32; 623 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}), 624 Succeeded()); 625 626 // Make a FDE with DWARF call frame instruction opcodes that have valid 627 // syntax, but will cause an error when we parse them into a UnwindTable. 628 // Here we encode a DW_CFA_GNU_window_save that is not supported. I have not 629 // found any documentation that describes what this does after some brief 630 // searching. 631 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}), 632 Succeeded()); 633 634 // Verify we catch state machine error. 635 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 636 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 637 FailedWithMessage("DW_CFA opcode 0x2d is not supported for " 638 "architecture x86_64")); 639 } 640 641 TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) { 642 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 643 /*Offset=*/0x0, 644 /*Length=*/0xff); 645 646 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 647 /*Offset=*/0x3333abcdabcd, 648 /*Length=*/0x4444abcdabcd, 649 /*CIEPointer=*/0x1111abcdabcd, 650 /*InitialLocation=*/0x1000, 651 /*AddressRange=*/0x1000, 652 /*Cie=*/&TestCIE, 653 /*LSDAAddress=*/None, 654 /*Arch=*/Triple::x86_64); 655 656 // Make a CIE that has an invalid CFA definition. We do this so we can try 657 // and use a DW_CFA_def_cfa_register opcode in the FDE and get an appropriate 658 // error back. 659 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 660 661 // Make a FDE with DWARF call frame instruction opcodes that have valid 662 // syntax, but will cause an error when we parse them into a UnwindTable. 663 // Here we encode a DW_CFA_def_cfa_offset with a offset of 16, but our CIE 664 // didn't define the CFA in terms of a register plus offset, so this should 665 // cause an error. 666 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}), 667 Succeeded()); 668 669 // Verify we catch state machine error. 670 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 671 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 672 FailedWithMessage("DW_CFA_def_cfa_offset found when CFA " 673 "rule was not RegPlusOffset")); 674 } 675 676 TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) { 677 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 678 /*Offset=*/0x0, 679 /*Length=*/0xff); 680 681 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 682 /*Offset=*/0x3333abcdabcd, 683 /*Length=*/0x4444abcdabcd, 684 /*CIEPointer=*/0x1111abcdabcd, 685 /*InitialLocation=*/0x1000, 686 /*AddressRange=*/0x1000, 687 /*Cie=*/&TestCIE, 688 /*LSDAAddress=*/None, 689 /*Arch=*/Triple::x86_64); 690 691 // Make a CIE that has an invalid CFA definition. We do this so we can try 692 // and use a DW_CFA_def_cfa_offset_sf opcode in the FDE and get an 693 // appropriate error back. 694 EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded()); 695 696 // Make a FDE with DWARF call frame instruction opcodes that have valid 697 // syntax, but will cause an error when we parse them into a UnwindTable. 698 // Here we encode a DW_CFA_def_cfa_offset_sf with a offset of 4, but our CIE 699 // didn't define the CFA in terms of a register plus offset, so this should 700 // cause an error. 701 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}), 702 Succeeded()); 703 704 // Verify we catch state machine error. 705 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 706 EXPECT_THAT_ERROR(RowsOrErr.takeError(), 707 FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA " 708 "rule was not RegPlusOffset")); 709 } 710 711 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) { 712 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 713 /*Offset=*/0x0, 714 /*Length=*/0xff); 715 716 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 717 /*Offset=*/0x3333abcdabcd, 718 /*Length=*/0x4444abcdabcd, 719 /*CIEPointer=*/0x1111abcdabcd, 720 /*InitialLocation=*/0x1000, 721 /*AddressRange=*/0x1000, 722 /*Cie=*/&TestCIE, 723 /*LSDAAddress=*/None, 724 /*Arch=*/Triple::x86_64); 725 726 // Make a CIE that has only defines the CFA register with no offset. Some 727 // architectures do this and we must ensure that we set the CFA value to be 728 // equal to that register with no offset. 729 constexpr uint8_t CFAReg = 12; 730 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}), 731 Succeeded()); 732 733 // Make a FDE with DWARF call frame instruction opcodes that have valid 734 // syntax, but will cause an error when we parse them into a UnwindTable. 735 // Here we encode a DW_CFA_def_cfa_register with a register number of 12, but 736 // our CIE didn't define the CFA in terms of a register plus offset, so this 737 // should cause an error. 738 EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded()); 739 740 // Verify we catch state machine error. 741 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 742 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 743 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 744 EXPECT_EQ(Rows.size(), 1u); 745 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 746 EXPECT_EQ(Rows[0].getCFAValue(), 747 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0)); 748 } 749 750 TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) { 751 // Test all opcodes that should end up pushing a UnwindRow into a UnwindTable. 752 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 753 /*Offset=*/0x0, 754 /*Length=*/0xff); 755 756 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 757 /*Offset=*/0x3333abcdabcd, 758 /*Length=*/0x4444abcdabcd, 759 /*CIEPointer=*/0x1111abcdabcd, 760 /*InitialLocation=*/0x1000, 761 /*AddressRange=*/0x1000, 762 /*Cie=*/&TestCIE, 763 /*LSDAAddress=*/None, 764 /*Arch=*/Triple::x86_64); 765 766 // Make a CIE that has a valid CFA definition and a single register unwind 767 // rule for register that we will verify is in all of the pushed rows. 768 constexpr uint8_t CFAReg = 12; 769 constexpr uint8_t CFAOffset = 32; 770 constexpr uint8_t Reg = 13; 771 constexpr uint8_t InReg = 14; 772 773 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 774 dwarf::DW_CFA_register, Reg, InReg}), 775 Succeeded()); 776 777 // Make a FDE with DWARF call frame instruction opcodes that use all of the 778 // row pushing opcodes. This will verify that all opcodes that should create 779 // a row are correctly working. Each opcode will push a row prior to 780 // advancing the address, and then a row will be automatically pushed at the 781 // end of the parsing, so we should end up with 6 rows starting at address 782 // 0x1000 (from the FDE) and incrementing each one by 4 * CodeAlignmentFactor 783 // from the CIE. 784 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4, 785 dwarf::DW_CFA_advance_loc1, 786 4, 787 dwarf::DW_CFA_advance_loc2, 788 4, 789 0, 790 dwarf::DW_CFA_advance_loc4, 791 4, 792 0, 793 0, 794 0, 795 dwarf::DW_CFA_set_loc, 796 0x14, 797 0x10, 798 0, 799 0, 800 0, 801 0, 802 0, 803 0}), 804 Succeeded()); 805 806 // Create locations that we expect the UnwindRow objects to contain after 807 // parsing the DWARF call frame instructions. 808 dwarf::RegisterLocations VerifyLocs; 809 VerifyLocs.setRegisterLocation( 810 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 811 812 // Verify we catch state machine error. 813 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 814 ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 815 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 816 EXPECT_EQ(Rows.size(), 6u); 817 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 818 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 819 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 820 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 821 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 822 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 823 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 824 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 825 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 826 EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 827 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 828 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 829 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 830 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 831 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 832 EXPECT_EQ(Rows[5].getAddress(), 0x1014u); 833 EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u); 834 EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs); 835 } 836 837 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) { 838 // Test that DW_CFA_restore works as expected when parsed in the state 839 // machine. 840 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 841 /*Offset=*/0x0, 842 /*Length=*/0xff); 843 844 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 845 /*Offset=*/0x3333abcdabcd, 846 /*Length=*/0x4444abcdabcd, 847 /*CIEPointer=*/0x1111abcdabcd, 848 /*InitialLocation=*/0x1000, 849 /*AddressRange=*/0x1000, 850 /*Cie=*/&TestCIE, 851 /*LSDAAddress=*/None, 852 /*Arch=*/Triple::x86_64); 853 854 // Make a CIE that has a valid CFA definition and a single register unwind 855 // rule for register that we will verify is in all of the pushed rows. 856 constexpr uint8_t CFAReg = 12; 857 constexpr uint8_t CFAOffset = 32; 858 constexpr uint8_t Reg = 13; 859 constexpr uint8_t InReg = 14; 860 constexpr int32_t RegCFAOffset = -8; 861 862 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 863 dwarf::DW_CFA_register, Reg, InReg}), 864 Succeeded()); 865 866 // Make a FDE with DWARF call frame instruction opcodes that changes the rule 867 // for register "Reg" to be [CFA-8], then push a row, and then restore the 868 // register unwind rule for "Reg" using DW_CFA_restore. We should end up with 869 // two rows: 870 // - one with Reg = [CFA-8] 871 // - one with Reg = InReg 872 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 873 dwarf::DW_CFA_advance_loc | 4, 874 dwarf::DW_CFA_restore | Reg}), 875 Succeeded()); 876 877 // Create locations that we expect the UnwindRow objects to contain after 878 // parsing the DWARF call frame instructions. 879 dwarf::RegisterLocations VerifyLocs1; 880 VerifyLocs1.setRegisterLocation( 881 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 882 883 dwarf::RegisterLocations VerifyLocs2; 884 VerifyLocs2.setRegisterLocation( 885 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 886 887 // Verify we catch state machine error. 888 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 889 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 890 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 891 EXPECT_EQ(Rows.size(), 2u); 892 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 893 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 894 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 895 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 896 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 897 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 898 } 899 900 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) { 901 // Test that DW_CFA_restore works as expected when parsed in the state 902 // machine. 903 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 904 /*Offset=*/0x0, 905 /*Length=*/0xff); 906 907 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 908 /*Offset=*/0x3333abcdabcd, 909 /*Length=*/0x4444abcdabcd, 910 /*CIEPointer=*/0x1111abcdabcd, 911 /*InitialLocation=*/0x1000, 912 /*AddressRange=*/0x1000, 913 /*Cie=*/&TestCIE, 914 /*LSDAAddress=*/None, 915 /*Arch=*/Triple::x86_64); 916 917 // Make a CIE that has a valid CFA definition and a single register unwind 918 // rule for register that we will verify is in all of the pushed rows. 919 constexpr uint8_t CFAReg = 12; 920 constexpr uint8_t CFAOffset = 32; 921 constexpr uint8_t Reg = 13; 922 constexpr uint8_t InReg = 14; 923 constexpr int32_t RegCFAOffset = -8; 924 925 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset, 926 dwarf::DW_CFA_register, Reg, InReg}), 927 Succeeded()); 928 929 // Make a FDE with DWARF call frame instruction opcodes that changes the rule 930 // for register "Reg" to be [CFA-8], then push a row, and then restore the 931 // register unwind rule for "Reg" using DW_CFA_restore_extended. We should 932 // end up with two rows: 933 // - one with Reg = [CFA-8] 934 // - one with Reg = InReg 935 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1, 936 dwarf::DW_CFA_advance_loc | 4, 937 dwarf::DW_CFA_restore_extended, Reg}), 938 Succeeded()); 939 940 // Create locations that we expect the UnwindRow objects to contain after 941 // parsing the DWARF call frame instructions. 942 dwarf::RegisterLocations VerifyLocs1; 943 VerifyLocs1.setRegisterLocation( 944 Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset)); 945 946 dwarf::RegisterLocations VerifyLocs2; 947 VerifyLocs2.setRegisterLocation( 948 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 949 950 // Verify we catch state machine error. 951 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 952 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 953 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 954 EXPECT_EQ(Rows.size(), 2u); 955 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 956 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 957 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 958 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 959 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 960 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 961 } 962 963 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) { 964 // Test that DW_CFA_offset, DW_CFA_offset_extended and 965 // DW_CFA_offset_extended_sf work as expected when parsed in the state 966 // machine. 967 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 968 /*Offset=*/0x0, 969 /*Length=*/0xff); 970 971 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 972 /*Offset=*/0x3333abcdabcd, 973 /*Length=*/0x4444abcdabcd, 974 /*CIEPointer=*/0x1111abcdabcd, 975 /*InitialLocation=*/0x1000, 976 /*AddressRange=*/0x1000, 977 /*Cie=*/&TestCIE, 978 /*LSDAAddress=*/None, 979 /*Arch=*/Triple::x86_64); 980 981 // Make a CIE that has a valid CFA definition and a single register unwind 982 // rule for register that we will verify is in all of the pushed rows. 983 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 984 Succeeded()); 985 986 // Make a FDE with DWARF call frame instruction opcodes that changes the 987 // unwind rules for the follwing registers: 988 // Reg1 = [CFA-8] 989 // Reg2 = [CFA-16] 990 // Reg3 = [CFA+8] 991 constexpr uint8_t Reg1 = 14; 992 constexpr uint8_t Reg2 = 15; 993 constexpr uint8_t Reg3 = 16; 994 constexpr uint8_t Neg1SLEB = 0x7f; 995 EXPECT_THAT_ERROR( 996 parseCFI(TestFDE, 997 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended, 998 Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}), 999 Succeeded()); 1000 1001 // Create locations that we expect the UnwindRow objects to contain after 1002 // parsing the DWARF call frame instructions. 1003 dwarf::RegisterLocations VerifyLocs; 1004 VerifyLocs.setRegisterLocation( 1005 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1006 VerifyLocs.setRegisterLocation( 1007 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1008 VerifyLocs.setRegisterLocation( 1009 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8)); 1010 1011 // Verify we catch state machine error. 1012 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1013 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1014 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1015 EXPECT_EQ(Rows.size(), 1u); 1016 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1017 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1018 } 1019 1020 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) { 1021 // Test that DW_CFA_val_offset and DW_CFA_val_offset_sf work as expected when 1022 // parsed in the state machine. 1023 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1024 /*Offset=*/0x0, 1025 /*Length=*/0xff); 1026 1027 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1028 /*Offset=*/0x3333abcdabcd, 1029 /*Length=*/0x4444abcdabcd, 1030 /*CIEPointer=*/0x1111abcdabcd, 1031 /*InitialLocation=*/0x1000, 1032 /*AddressRange=*/0x1000, 1033 /*Cie=*/&TestCIE, 1034 /*LSDAAddress=*/None, 1035 /*Arch=*/Triple::x86_64); 1036 1037 // Make a CIE that has a valid CFA definition and a single register unwind 1038 // rule for register that we will verify is in all of the pushed rows. 1039 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1040 Succeeded()); 1041 1042 // Make a FDE with DWARF call frame instruction opcodes that changes the 1043 // unwind rules for the follwing registers: 1044 // Reg1 = [CFA-8] 1045 // Reg2 = [CFA-16] 1046 // Reg3 = [CFA+8] 1047 constexpr uint8_t Reg1 = 14; 1048 constexpr uint8_t Reg2 = 15; 1049 constexpr uint8_t Neg1SLEB = 0x7f; 1050 EXPECT_THAT_ERROR( 1051 parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1, 1052 dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}), 1053 Succeeded()); 1054 1055 // Create locations that we expect the UnwindRow objects to contain after 1056 // parsing the DWARF call frame instructions. 1057 dwarf::RegisterLocations VerifyLocs; 1058 VerifyLocs.setRegisterLocation( 1059 Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8)); 1060 VerifyLocs.setRegisterLocation( 1061 Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8)); 1062 1063 // Verify we catch state machine error. 1064 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1065 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1066 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1067 EXPECT_EQ(Rows.size(), 1u); 1068 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1069 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1070 } 1071 1072 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) { 1073 // Test that DW_CFA_nop works as expected when parsed in the state machine. 1074 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1075 /*Offset=*/0x0, 1076 /*Length=*/0xff); 1077 1078 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1079 /*Offset=*/0x3333abcdabcd, 1080 /*Length=*/0x4444abcdabcd, 1081 /*CIEPointer=*/0x1111abcdabcd, 1082 /*InitialLocation=*/0x1000, 1083 /*AddressRange=*/0x1000, 1084 /*Cie=*/&TestCIE, 1085 /*LSDAAddress=*/None, 1086 /*Arch=*/Triple::x86_64); 1087 1088 // Make a CIE that has a valid CFA definition and a single register unwind 1089 // rule for register that we will verify is in all of the pushed rows. 1090 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1091 Succeeded()); 1092 1093 // Make a FDE with DWARF call frame instruction opcodes that changes the 1094 // unwind rules for the follwing registers: 1095 // Reg1 = [CFA-8] 1096 // The opcodes for setting Reg1 are preceded by a DW_CFA_nop. 1097 constexpr uint8_t Reg1 = 14; 1098 EXPECT_THAT_ERROR( 1099 parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}), 1100 Succeeded()); 1101 1102 // Create locations that we expect the UnwindRow objects to contain after 1103 // parsing the DWARF call frame instructions. 1104 dwarf::RegisterLocations VerifyLocs; 1105 VerifyLocs.setRegisterLocation( 1106 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1107 1108 // Verify we catch state machine error. 1109 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1110 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1111 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1112 EXPECT_EQ(Rows.size(), 1u); 1113 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1114 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1115 } 1116 1117 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) { 1118 // Test that DW_CFA_remember_state and DW_CFA_restore_state work as expected 1119 // when parsed in the state machine. 1120 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1121 /*Offset=*/0x0, 1122 /*Length=*/0xff); 1123 1124 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1125 /*Offset=*/0x3333abcdabcd, 1126 /*Length=*/0x4444abcdabcd, 1127 /*CIEPointer=*/0x1111abcdabcd, 1128 /*InitialLocation=*/0x1000, 1129 /*AddressRange=*/0x1000, 1130 /*Cie=*/&TestCIE, 1131 /*LSDAAddress=*/None, 1132 /*Arch=*/Triple::x86_64); 1133 1134 // Make a CIE that has a valid CFA definition and a single register unwind 1135 // rule for register that we will verify is in all of the pushed rows. 1136 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1137 Succeeded()); 1138 1139 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1140 // follwing rows: 1141 // 0x1000: CFA=reg12+32: Reg1=[CFA-8] 1142 // 0x1004: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1143 // 0x1008: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] Reg3=[CFA-24] 1144 // 0x100C: CFA=reg12+32: Reg1=[CFA-8] Reg2=[CFA-16] 1145 // 0x1010: CFA=reg12+32: Reg1=[CFA-8] 1146 // This state machine will: 1147 // - set Reg1 location 1148 // - push a row (from DW_CFA_advance_loc) 1149 // - remember the state 1150 // - set Reg2 location 1151 // - push a row (from DW_CFA_advance_loc) 1152 // - remember the state 1153 // - set Reg3 location 1154 // - push a row (from DW_CFA_advance_loc) 1155 // - remember the state where Reg1 and Reg2 were set 1156 // - push a row (from DW_CFA_advance_loc) 1157 // - remember the state where only Reg1 was set 1158 // - push a row (automatically at the end of instruction parsing) 1159 // Then we verify that all registers are correct in all generated rows. 1160 constexpr uint8_t Reg1 = 14; 1161 constexpr uint8_t Reg2 = 15; 1162 constexpr uint8_t Reg3 = 16; 1163 EXPECT_THAT_ERROR( 1164 parseCFI(TestFDE, 1165 {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4, 1166 dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2, 1167 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state, 1168 dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4, 1169 dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4, 1170 dwarf::DW_CFA_restore_state}), 1171 Succeeded()); 1172 1173 // Create locations that we expect the UnwindRow objects to contain after 1174 // parsing the DWARF call frame instructions. 1175 dwarf::RegisterLocations VerifyLocs1; 1176 VerifyLocs1.setRegisterLocation( 1177 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1178 1179 dwarf::RegisterLocations VerifyLocs2; 1180 VerifyLocs2.setRegisterLocation( 1181 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1182 VerifyLocs2.setRegisterLocation( 1183 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1184 1185 dwarf::RegisterLocations VerifyLocs3; 1186 VerifyLocs3.setRegisterLocation( 1187 Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8)); 1188 VerifyLocs3.setRegisterLocation( 1189 Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16)); 1190 VerifyLocs3.setRegisterLocation( 1191 Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24)); 1192 1193 // Verify we catch state machine error. 1194 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1195 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1196 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1197 EXPECT_EQ(Rows.size(), 5u); 1198 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1199 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1); 1200 1201 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1202 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2); 1203 1204 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1205 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3); 1206 1207 EXPECT_EQ(Rows[3].getAddress(), 0x100Cu); 1208 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2); 1209 1210 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1211 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1); 1212 } 1213 1214 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) { 1215 // Test that DW_CFA_undefined works as expected when parsed in the state 1216 // machine. 1217 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1218 /*Offset=*/0x0, 1219 /*Length=*/0xff); 1220 1221 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1222 /*Offset=*/0x3333abcdabcd, 1223 /*Length=*/0x4444abcdabcd, 1224 /*CIEPointer=*/0x1111abcdabcd, 1225 /*InitialLocation=*/0x1000, 1226 /*AddressRange=*/0x1000, 1227 /*Cie=*/&TestCIE, 1228 /*LSDAAddress=*/None, 1229 /*Arch=*/Triple::x86_64); 1230 1231 // Make a CIE that has a valid CFA definition and a single register unwind 1232 // rule for register that we will verify is in all of the pushed rows. 1233 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1234 Succeeded()); 1235 1236 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1237 // follwing rows: 1238 // 0x1000: CFA=reg12+32: Reg1=undefined 1239 // Then we verify that all registers are correct in all generated rows. 1240 constexpr uint8_t Reg1 = 14; 1241 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}), 1242 Succeeded()); 1243 1244 // Create locations that we expect the UnwindRow objects to contain after 1245 // parsing the DWARF call frame instructions. 1246 dwarf::RegisterLocations VerifyLocs; 1247 VerifyLocs.setRegisterLocation(Reg1, 1248 dwarf::UnwindLocation::createUndefined()); 1249 1250 // Verify we catch state machine error. 1251 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1252 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1253 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1254 EXPECT_EQ(Rows.size(), 1u); 1255 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1256 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1257 } 1258 1259 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) { 1260 // Test that DW_CFA_same_value works as expected when parsed in the state 1261 // machine. 1262 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1263 /*Offset=*/0x0, 1264 /*Length=*/0xff); 1265 1266 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1267 /*Offset=*/0x3333abcdabcd, 1268 /*Length=*/0x4444abcdabcd, 1269 /*CIEPointer=*/0x1111abcdabcd, 1270 /*InitialLocation=*/0x1000, 1271 /*AddressRange=*/0x1000, 1272 /*Cie=*/&TestCIE, 1273 /*LSDAAddress=*/None, 1274 /*Arch=*/Triple::x86_64); 1275 1276 // Make a CIE that has a valid CFA definition and a single register unwind 1277 // rule for register that we will verify is in all of the pushed rows. 1278 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1279 Succeeded()); 1280 1281 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1282 // follwing rows: 1283 // 0x1000: CFA=reg12+32: Reg1=same 1284 // Then we verify that all registers are correct in all generated rows. 1285 constexpr uint8_t Reg1 = 14; 1286 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}), 1287 Succeeded()); 1288 1289 // Create locations that we expect the UnwindRow objects to contain after 1290 // parsing the DWARF call frame instructions. 1291 dwarf::RegisterLocations VerifyLocs; 1292 VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame()); 1293 1294 // Verify we catch state machine error. 1295 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1296 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1297 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1298 EXPECT_EQ(Rows.size(), 1u); 1299 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1300 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1301 } 1302 1303 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) { 1304 // Test that DW_CFA_register works as expected when parsed in the state 1305 // machine. 1306 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1307 /*Offset=*/0x0, 1308 /*Length=*/0xff); 1309 1310 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1311 /*Offset=*/0x3333abcdabcd, 1312 /*Length=*/0x4444abcdabcd, 1313 /*CIEPointer=*/0x1111abcdabcd, 1314 /*InitialLocation=*/0x1000, 1315 /*AddressRange=*/0x1000, 1316 /*Cie=*/&TestCIE, 1317 /*LSDAAddress=*/None, 1318 /*Arch=*/Triple::x86_64); 1319 1320 // Make a CIE that has a valid CFA definition and a single register unwind 1321 // rule for register that we will verify is in all of the pushed rows. 1322 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1323 Succeeded()); 1324 1325 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1326 // follwing rows: 1327 // 0x1000: CFA=reg12+32: Reg1=same 1328 // Then we verify that all registers are correct in all generated rows. 1329 constexpr uint8_t Reg = 13; 1330 constexpr uint8_t InReg = 14; 1331 EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}), 1332 Succeeded()); 1333 1334 // Create locations that we expect the UnwindRow objects to contain after 1335 // parsing the DWARF call frame instructions. 1336 dwarf::RegisterLocations VerifyLocs; 1337 VerifyLocs.setRegisterLocation( 1338 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1339 1340 // Verify we catch state machine error. 1341 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1342 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1343 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1344 EXPECT_EQ(Rows.size(), 1u); 1345 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1346 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1347 } 1348 1349 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) { 1350 // Test that DW_CFA_expression works as expected when parsed in the state 1351 // machine. 1352 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1353 /*Offset=*/0x0, 1354 /*Length=*/0xff); 1355 1356 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1357 /*Offset=*/0x3333abcdabcd, 1358 /*Length=*/0x4444abcdabcd, 1359 /*CIEPointer=*/0x1111abcdabcd, 1360 /*InitialLocation=*/0x1000, 1361 /*AddressRange=*/0x1000, 1362 /*Cie=*/&TestCIE, 1363 /*LSDAAddress=*/None, 1364 /*Arch=*/Triple::x86_64); 1365 1366 // Make a CIE that has a valid CFA definition and a single register unwind 1367 // rule for register that we will verify is in all of the pushed rows. 1368 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1369 Succeeded()); 1370 1371 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1372 // follwing rows: 1373 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1374 // Then we verify that all registers are correct in all generated rows. 1375 constexpr uint8_t Reg = 13; 1376 constexpr uint8_t AddrSize = 8; 1377 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1, 1378 dwarf::DW_OP_reg12}; 1379 1380 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1381 1382 // Create locations that we expect the UnwindRow objects to contain after 1383 // parsing the DWARF call frame instructions. 1384 dwarf::RegisterLocations VerifyLocs; 1385 1386 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1387 DataExtractor ExprData(ExprBytes, true, AddrSize); 1388 DWARFExpression Expr(ExprData, AddrSize); 1389 VerifyLocs.setRegisterLocation( 1390 Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr)); 1391 1392 // Verify we catch state machine error. 1393 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1394 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1395 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1396 EXPECT_EQ(Rows.size(), 1u); 1397 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1398 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1399 } 1400 1401 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) { 1402 // Test that DW_CFA_val_expression works as expected when parsed in the state 1403 // machine. 1404 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1405 /*Offset=*/0x0, 1406 /*Length=*/0xff); 1407 1408 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1409 /*Offset=*/0x3333abcdabcd, 1410 /*Length=*/0x4444abcdabcd, 1411 /*CIEPointer=*/0x1111abcdabcd, 1412 /*InitialLocation=*/0x1000, 1413 /*AddressRange=*/0x1000, 1414 /*Cie=*/&TestCIE, 1415 /*LSDAAddress=*/None, 1416 /*Arch=*/Triple::x86_64); 1417 1418 // Make a CIE that has a valid CFA definition and a single register unwind 1419 // rule for register that we will verify is in all of the pushed rows. 1420 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}), 1421 Succeeded()); 1422 1423 // Make a FDE with DWARF call frame instruction opcodes that encodes the 1424 // follwing rows: 1425 // 0x1000: CFA=reg12+32: Reg1=DWARFExpr(DW_OP_reg12) 1426 // Then we verify that all registers are correct in all generated rows. 1427 constexpr uint8_t Reg = 13; 1428 constexpr uint8_t AddrSize = 8; 1429 std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1, 1430 dwarf::DW_OP_reg12}; 1431 1432 EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded()); 1433 1434 // Create locations that we expect the UnwindRow objects to contain after 1435 // parsing the DWARF call frame instructions. 1436 dwarf::RegisterLocations VerifyLocs; 1437 1438 std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12}; 1439 DataExtractor ExprData(ExprBytes, true, AddrSize); 1440 DWARFExpression Expr(ExprData, AddrSize); 1441 VerifyLocs.setRegisterLocation( 1442 Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr)); 1443 1444 // Verify we catch state machine error. 1445 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1446 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1447 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1448 EXPECT_EQ(Rows.size(), 1u); 1449 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1450 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1451 } 1452 1453 TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) { 1454 // Test that DW_CFA_def_cfa, DW_CFA_def_cfa_sf, DW_CFA_def_cfa_register, 1455 // DW_CFA_def_cfa_offset, and DW_CFA_def_cfa_offset_sf works as expected when 1456 // parsed in the state machine. 1457 dwarf::CIE TestCIE = createCIE(/*IsDWARF64=*/false, 1458 /*Offset=*/0x0, 1459 /*Length=*/0xff); 1460 1461 dwarf::FDE TestFDE(/*IsDWARF64=*/true, 1462 /*Offset=*/0x3333abcdabcd, 1463 /*Length=*/0x4444abcdabcd, 1464 /*CIEPointer=*/0x1111abcdabcd, 1465 /*InitialLocation=*/0x1000, 1466 /*AddressRange=*/0x1000, 1467 /*Cie=*/&TestCIE, 1468 /*LSDAAddress=*/None, 1469 /*Arch=*/Triple::x86_64); 1470 1471 // Make a CIE that has a valid CFA definition and a single register unwind 1472 // rule for register that we will verify is in all of the pushed rows. 1473 constexpr uint8_t CFAReg1 = 12; 1474 constexpr uint8_t CFAOff1 = 32; 1475 constexpr uint8_t CFAReg2 = 13; 1476 constexpr uint8_t CFAOff2 = 48; 1477 constexpr uint8_t Reg = 13; 1478 constexpr uint8_t InReg = 14; 1479 1480 EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1, 1481 dwarf::DW_CFA_register, Reg, InReg}), 1482 Succeeded()); 1483 1484 // Make a FDE with DWARF call frame instruction opcodes that use all of the 1485 // DW_CFA_def_cfa* opcodes. This will verify that all opcodes that should 1486 // create a row are correctly working. 1487 EXPECT_THAT_ERROR( 1488 parseCFI( 1489 TestFDE, 1490 { 1491 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register, 1492 CFAReg2, dwarf::DW_CFA_advance_loc | 4, 1493 dwarf::DW_CFA_def_cfa_offset, CFAOff2, 1494 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf, 1495 0x7c, // -4 SLEB to make offset = 32 (CFAOff1) 1496 dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1, 1497 0x7a, // -6 SLEB to make CFA offset 48 (CFAOff2) 1498 }), 1499 Succeeded()); 1500 1501 // Create locations that we expect the UnwindRow objects to contain after 1502 // parsing the DWARF call frame instructions. 1503 dwarf::RegisterLocations VerifyLocs; 1504 VerifyLocs.setRegisterLocation( 1505 Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0)); 1506 1507 // Verify we catch state machine error. 1508 Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE); 1509 EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded()); 1510 const dwarf::UnwindTable &Rows = RowsOrErr.get(); 1511 EXPECT_EQ(Rows.size(), 5u); 1512 EXPECT_EQ(Rows[0].getAddress(), 0x1000u); 1513 EXPECT_EQ( 1514 Rows[0].getCFAValue(), 1515 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1)); 1516 EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u); 1517 EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs); 1518 1519 EXPECT_EQ(Rows[1].getAddress(), 0x1004u); 1520 EXPECT_EQ( 1521 Rows[1].getCFAValue(), 1522 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1523 EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u); 1524 EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs); 1525 1526 EXPECT_EQ(Rows[2].getAddress(), 0x1008u); 1527 EXPECT_EQ( 1528 Rows[2].getCFAValue(), 1529 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2)); 1530 EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u); 1531 EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs); 1532 1533 EXPECT_EQ(Rows[3].getAddress(), 0x100cu); 1534 EXPECT_EQ( 1535 Rows[3].getCFAValue(), 1536 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1)); 1537 EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u); 1538 EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs); 1539 1540 EXPECT_EQ(Rows[4].getAddress(), 0x1010u); 1541 EXPECT_EQ( 1542 Rows[4].getCFAValue(), 1543 dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2)); 1544 EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u); 1545 EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs); 1546 } 1547 1548 } // end anonymous namespace 1549