1 //===- DWARFDebugLineTest.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 "DwarfGenerator.h" 10 #include "DwarfUtils.h" 11 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 13 #include "llvm/Object/ObjectFile.h" 14 #include "llvm/Testing/Support/Error.h" 15 #include "gtest/gtest.h" 16 17 using namespace llvm; 18 using namespace dwarf; 19 using namespace dwarfgen; 20 using namespace object; 21 using namespace utils; 22 using namespace testing; 23 24 namespace { 25 struct CommonFixture { 26 CommonFixture() 27 : LineData("", true, 0), Recoverable(Error::success()), 28 RecordRecoverable(std::bind(&CommonFixture::recordRecoverable, this, 29 std::placeholders::_1)), 30 Unrecoverable(Error::success()), 31 RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this, 32 std::placeholders::_1)){}; 33 34 ~CommonFixture() { 35 EXPECT_FALSE(Recoverable); 36 EXPECT_FALSE(Unrecoverable); 37 } 38 39 bool setupGenerator(uint16_t Version = 4, uint8_t AddrSize = 8) { 40 AddressSize = AddrSize; 41 Triple T = 42 getDefaultTargetTripleForAddrSize(AddressSize == 0 ? 8 : AddressSize); 43 if (!isConfigurationSupported(T)) 44 return false; 45 auto ExpectedGenerator = Generator::create(T, Version); 46 if (ExpectedGenerator) 47 Gen.reset(ExpectedGenerator->release()); 48 return true; 49 } 50 51 void generate() { 52 Context = createContext(); 53 assert(Context != nullptr && "test state is not valid"); 54 const DWARFObject &Obj = Context->getDWARFObj(); 55 uint8_t TargetAddrSize = AddressSize == 0 ? 8 : AddressSize; 56 LineData = DWARFDataExtractor( 57 Obj, Obj.getLineSection(), 58 getDefaultTargetTripleForAddrSize(TargetAddrSize).isLittleEndian(), 59 AddressSize); 60 } 61 62 std::unique_ptr<DWARFContext> createContext() { 63 if (!Gen) 64 return nullptr; 65 StringRef FileBytes = Gen->generate(); 66 MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 67 auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 68 if (Obj) 69 return DWARFContext::create(**Obj); 70 return nullptr; 71 } 72 73 DWARFDebugLine::SectionParser setupParser() { 74 LineTable < = Gen->addLineTable(DWARF32); 75 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 76 LT.addStandardOpcode(DW_LNS_copy, {}); 77 LT.addByte(0xaa); 78 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 79 80 LineTable <2 = Gen->addLineTable(DWARF64); 81 LT2.addExtendedOpcode(9, DW_LNE_set_address, 82 {{0x11223344, LineTable::Quad}}); 83 LT2.addStandardOpcode(DW_LNS_copy, {}); 84 LT2.addByte(0xbb); 85 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 86 87 generate(); 88 89 return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs); 90 } 91 92 void recordRecoverable(Error Err) { 93 Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); 94 } 95 void recordUnrecoverable(Error Err) { 96 Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); 97 } 98 99 void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) { 100 ASSERT_TRUE(Err.operator bool()); 101 size_t WhichMsg = 0; 102 Error Remaining = 103 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) { 104 ASSERT_LT(WhichMsg, ExpectedMsgs.size()); 105 // Use .str(), because googletest doesn't visualise a StringRef 106 // properly. 107 EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str()); 108 }); 109 EXPECT_EQ(WhichMsg, ExpectedMsgs.size()); 110 EXPECT_FALSE(Remaining); 111 } 112 113 void checkError(StringRef ExpectedMsg, Error Err) { 114 checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err)); 115 } 116 117 void checkGetOrParseLineTableEmitsFatalError(StringRef ExpectedMsg, 118 uint64_t Offset = 0) { 119 auto ExpectedLineTable = Line.getOrParseLineTable( 120 LineData, Offset, *Context, nullptr, RecordRecoverable); 121 EXPECT_FALSE(ExpectedLineTable); 122 EXPECT_FALSE(Recoverable); 123 124 checkError(ExpectedMsg, ExpectedLineTable.takeError()); 125 } 126 127 void checkGetOrParseLineTableEmitsFatalError(ArrayRef<StringRef> ExpectedMsgs, 128 uint64_t Offset = 0) { 129 auto ExpectedLineTable = Line.getOrParseLineTable( 130 LineData, Offset, *Context, nullptr, RecordRecoverable); 131 EXPECT_FALSE(ExpectedLineTable); 132 EXPECT_FALSE(Recoverable); 133 134 checkError(ExpectedMsgs, ExpectedLineTable.takeError()); 135 } 136 137 uint8_t AddressSize; 138 std::unique_ptr<Generator> Gen; 139 std::unique_ptr<DWARFContext> Context; 140 DWARFDataExtractor LineData; 141 DWARFDebugLine Line; 142 Error Recoverable; 143 std::function<void(Error)> RecordRecoverable; 144 Error Unrecoverable; 145 std::function<void(Error)> RecordUnrecoverable; 146 147 SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs; 148 SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs; 149 }; 150 151 // Fixtures must derive from "Test", but parameterised fixtures from 152 // "TestWithParam". It does not seem possible to inherit from both, so we share 153 // the common state in a separate class, inherited by the two fixture classes. 154 struct DebugLineBasicFixture : public Test, public CommonFixture {}; 155 156 struct DebugLineParameterisedFixture 157 : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 158 public CommonFixture { 159 void SetUp() { std::tie(Version, Format) = GetParam(); } 160 161 uint16_t Version; 162 DwarfFormat Format; 163 }; 164 165 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 166 DWARFDebugLine::Prologue Prologue, 167 uint64_t BodyLength) { 168 // Check version specific fields and values. 169 uint64_t UnitLength; 170 uint64_t PrologueLength; 171 switch (Version) { 172 case 4: 173 PrologueLength = 36; 174 UnitLength = PrologueLength + 2; 175 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 176 break; 177 case 2: 178 case 3: 179 PrologueLength = 35; 180 UnitLength = PrologueLength + 2; 181 break; 182 case 5: 183 PrologueLength = 39; 184 UnitLength = PrologueLength + 4; 185 EXPECT_EQ(Prologue.getAddressSize(), 8u); 186 EXPECT_EQ(Prologue.SegSelectorSize, 0u); 187 break; 188 default: 189 llvm_unreachable("unsupported DWARF version"); 190 } 191 UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 192 193 EXPECT_EQ(Prologue.TotalLength, UnitLength); 194 EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 195 EXPECT_EQ(Prologue.MinInstLength, 1u); 196 EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 197 EXPECT_EQ(Prologue.LineBase, -5); 198 EXPECT_EQ(Prologue.LineRange, 14u); 199 EXPECT_EQ(Prologue.OpcodeBase, 13u); 200 std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 201 EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 202 ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 203 ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 204 EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 205 ASSERT_EQ(Prologue.FileNames.size(), 1u); 206 ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 207 EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 208 } 209 210 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 211 if (!setupGenerator()) 212 return; 213 generate(); 214 215 checkGetOrParseLineTableEmitsFatalError( 216 "offset 0x00000000 is not a valid debug line section offset", 0); 217 // Repeat to show that an error is reported each time. 218 checkGetOrParseLineTableEmitsFatalError( 219 "offset 0x00000000 is not a valid debug line section offset", 0); 220 // Show that an error is reported for later offsets too. 221 checkGetOrParseLineTableEmitsFatalError( 222 "offset 0x00000001 is not a valid debug line section offset", 1); 223 } 224 225 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 226 if (!setupGenerator()) 227 return; 228 229 LineTable < = Gen->addLineTable(); 230 LT.setCustomPrologue({{0, LineTable::Byte}}); 231 232 generate(); 233 234 checkGetOrParseLineTableEmitsFatalError( 235 "offset 0x00000001 is not a valid debug line section offset", 1); 236 } 237 238 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 239 if (!setupGenerator(Version)) 240 return; 241 LineTable < = Gen->addLineTable(Format); 242 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 243 LT.setPrologue(Prologue); 244 generate(); 245 246 // + 10 for sizes of DWARF-32 unit length, version, prologue length. 247 uint64_t ExpectedLength = Prologue.PrologueLength + 10; 248 if (Version == 5) 249 // Add address and segment selector size fields. 250 ExpectedLength += 2; 251 if (Format == DWARF64) 252 // Unit length grows by 8, prologue length by 4. 253 ExpectedLength += 12; 254 255 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 256 nullptr, RecordRecoverable); 257 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 258 EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 259 } 260 261 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 262 if (!setupGenerator(Version)) 263 return; 264 265 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 266 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 267 268 LineTable < = Gen->addLineTable(Format); 269 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 270 LT.addStandardOpcode(DW_LNS_copy, {}); 271 LT.addByte(0xaa); 272 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 273 274 LineTable <2 = Gen->addLineTable(Format); 275 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 276 LT2.addStandardOpcode(DW_LNS_copy, {}); 277 LT2.addByte(0xbb); 278 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 279 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 280 LT2.addStandardOpcode(DW_LNS_copy, {}); 281 LT2.addByte(0xcc); 282 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 283 284 generate(); 285 286 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 287 nullptr, RecordRecoverable); 288 ASSERT_TRUE(ExpectedLineTable.operator bool()); 289 EXPECT_FALSE(Recoverable); 290 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 291 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 292 EXPECT_EQ(Expected->Sequences.size(), 1u); 293 294 uint64_t SecondOffset = 295 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 296 Recoverable = Error::success(); 297 auto ExpectedLineTable2 = Line.getOrParseLineTable( 298 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 299 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 300 EXPECT_FALSE(Recoverable); 301 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 302 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 303 EXPECT_EQ(Expected2->Sequences.size(), 2u); 304 305 EXPECT_NE(Expected, Expected2); 306 307 // Check that if the same offset is requested, the exact same pointer is 308 // returned. 309 Recoverable = Error::success(); 310 auto ExpectedLineTable3 = Line.getOrParseLineTable( 311 LineData, 0, *Context, nullptr, RecordRecoverable); 312 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 313 EXPECT_FALSE(Recoverable); 314 EXPECT_EQ(Expected, *ExpectedLineTable3); 315 316 Recoverable = Error::success(); 317 auto ExpectedLineTable4 = Line.getOrParseLineTable( 318 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 319 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 320 EXPECT_FALSE(Recoverable); 321 EXPECT_EQ(Expected2, *ExpectedLineTable4); 322 323 // TODO: Add tests that show that the body of the programs have been read 324 // correctly. 325 } 326 327 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 328 if (!setupGenerator()) 329 return; 330 331 LineTable < = Gen->addLineTable(); 332 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 333 334 generate(); 335 336 checkGetOrParseLineTableEmitsFatalError( 337 "parsing line table prologue at offset 0x00000000 unsupported reserved " 338 "unit length found of value 0xfffffff0"); 339 } 340 341 TEST_F(DebugLineBasicFixture, ErrorForLowVersion) { 342 if (!setupGenerator()) 343 return; 344 345 LineTable < = Gen->addLineTable(); 346 LT.setCustomPrologue( 347 {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}}); 348 349 generate(); 350 351 checkGetOrParseLineTableEmitsFatalError( 352 "parsing line table prologue at offset " 353 "0x00000000 found unsupported version " 354 "0x01"); 355 } 356 357 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 358 if (!setupGenerator(5)) 359 return; 360 361 LineTable < = Gen->addLineTable(); 362 LT.setCustomPrologue({ 363 {19, LineTable::Long}, // unit length 364 {5, LineTable::Half}, // version 365 {8, LineTable::Byte}, // addr size 366 {0, LineTable::Byte}, // segment selector size 367 {11, LineTable::Long}, // prologue length 368 {1, LineTable::Byte}, // min instruction length 369 {1, LineTable::Byte}, // max ops per instruction 370 {1, LineTable::Byte}, // default is_stmt 371 {0, LineTable::Byte}, // line base 372 {14, LineTable::Byte}, // line range 373 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 374 // setup required). 375 {0, LineTable::Byte}, // standard opcode lengths 376 {0, LineTable::Byte}, // directory entry format count (should not be 377 // zero). 378 {0, LineTable::ULEB}, // directories count 379 {0, LineTable::Byte}, // file name entry format count 380 {0, LineTable::ULEB} // file name entry count 381 }); 382 383 generate(); 384 385 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 386 nullptr, RecordRecoverable); 387 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 388 389 checkError( 390 {"parsing line table prologue at 0x00000000 found an invalid directory " 391 "or file table description at 0x00000014", 392 "failed to parse entry content descriptions because no path was found"}, 393 std::move(Recoverable)); 394 } 395 396 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 397 if (!setupGenerator(Version)) 398 return; 399 400 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 401 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 402 403 LineTable < = Gen->addLineTable(Format); 404 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 405 ++Prologue.PrologueLength; 406 LT.setPrologue(Prologue); 407 408 generate(); 409 410 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 411 nullptr, RecordRecoverable); 412 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 413 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 414 // Undo the earlier modification so that it can be compared against a 415 // "default" prologue. 416 --Result.Prologue.PrologueLength; 417 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 418 419 uint64_t ExpectedEnd = 420 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 421 checkError( 422 (Twine("parsing line table prologue at 0x00000000 should have ended at " 423 "0x000000") + 424 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 425 Twine::utohexstr(ExpectedEnd - 1)) 426 .str(), 427 std::move(Recoverable)); 428 } 429 430 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 431 if (!setupGenerator(Version)) 432 return; 433 434 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 435 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 436 437 LineTable < = Gen->addLineTable(Format); 438 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 439 // FIXME: Ideally, we'd test for 1 less than expected, but the code does not 440 // currently fail if missing only the terminator of a v2-4 file table. 441 if (Version < 5) 442 Prologue.PrologueLength -= 2; 443 else 444 Prologue.PrologueLength -= 1; 445 LT.setPrologue(Prologue); 446 447 generate(); 448 449 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 450 nullptr, RecordRecoverable); 451 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 452 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 453 // Undo the earlier modification so that it can be compared against a 454 // "default" prologue. 455 if (Version < 5) 456 Result.Prologue.PrologueLength += 2; 457 else 458 Result.Prologue.PrologueLength += 1; 459 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 460 461 uint64_t ExpectedEnd = 462 Prologue.TotalLength - 1 + Prologue.sizeofTotalLength(); 463 if (Version < 5) 464 --ExpectedEnd; 465 checkError( 466 (Twine("parsing line table prologue at 0x00000000 should have ended at " 467 "0x000000") + 468 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 469 Twine::utohexstr(ExpectedEnd + 1)) 470 .str(), 471 std::move(Recoverable)); 472 } 473 474 INSTANTIATE_TEST_CASE_P( 475 LineTableTestParams, DebugLineParameterisedFixture, 476 Values(std::make_pair( 477 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 478 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 479 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 480 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 481 482 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 483 if (!setupGenerator()) 484 return; 485 486 LineTable < = Gen->addLineTable(); 487 LT.addByte(0xaa); 488 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 489 // The operand will be read for both the discriminator opcode and then parsed 490 // again as DW_LNS_negate_stmt, to respect the claimed length. 491 LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 492 {{DW_LNS_negate_stmt, LineTable::ULEB}}); 493 LT.addByte(0xbb); 494 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 495 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 496 497 generate(); 498 499 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 500 nullptr, RecordRecoverable); 501 checkError( 502 "unexpected line op length at offset 0x00000031 expected 0x01 found 0x02", 503 std::move(Recoverable)); 504 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 505 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 506 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 507 EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 508 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 509 } 510 511 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 512 if (!setupGenerator()) 513 return; 514 515 LineTable < = Gen->addLineTable(); 516 LT.addByte(0xaa); 517 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 518 // The Length should be 1 for an end sequence opcode. 519 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 520 // The negate statement opcode will be skipped. 521 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 522 LT.addByte(0xbb); 523 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 524 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 525 526 generate(); 527 528 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 529 nullptr, RecordRecoverable); 530 checkError( 531 "unexpected line op length at offset 0x00000032 expected 0x02 found 0x01", 532 std::move(Recoverable)); 533 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 534 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 535 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 536 ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 537 EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 538 } 539 540 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 541 if (!setupGenerator()) 542 return; 543 544 LineTable &Padding = Gen->addLineTable(); 545 // Add some padding to show that a non-zero offset is handled correctly. 546 Padding.setCustomPrologue({{0, LineTable::Byte}}); 547 LineTable < = Gen->addLineTable(); 548 LT.addStandardOpcode(DW_LNS_copy, {}); 549 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 550 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 551 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 552 // Set the total length to 1 higher than the actual length. 553 ++Prologue.TotalLength; 554 LT.setPrologue(Prologue); 555 556 generate(); 557 558 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 559 nullptr, RecordRecoverable); 560 checkError("line table program with offset 0x00000001 has length 0x00000034 " 561 "but only 0x00000033 bytes are available", 562 std::move(Recoverable)); 563 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 564 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 565 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 566 } 567 568 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 569 if (!setupGenerator(4, 8)) 570 return; 571 572 LineTable < = Gen->addLineTable(); 573 // The line data extractor expects size 8 (Quad) addresses. 574 uint64_t Addr1 = 0x11223344; 575 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 576 LT.addStandardOpcode(DW_LNS_copy, {}); 577 // Show that the expected address size is unchanged, so later valid lines 578 // don't cause a problem. 579 uint64_t Addr2 = 0x1122334455667788; 580 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 581 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 582 583 generate(); 584 585 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 586 nullptr, RecordRecoverable); 587 checkError( 588 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04", 589 std::move(Recoverable)); 590 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 591 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 592 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 593 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 594 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 595 } 596 597 TEST_F(DebugLineBasicFixture, 598 ErrorForMismatchedAddressSizeUnsetInitialAddress) { 599 if (!setupGenerator(4, 0)) 600 return; 601 602 LineTable < = Gen->addLineTable(); 603 uint64_t Addr1 = 0x11223344; 604 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 605 LT.addStandardOpcode(DW_LNS_copy, {}); 606 uint64_t Addr2 = 0x1122334455667788; 607 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 608 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 609 610 generate(); 611 612 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 613 nullptr, RecordRecoverable); 614 checkError( 615 "mismatching address size at offset 0x00000038 expected 0x04 found 0x08", 616 std::move(Recoverable)); 617 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 618 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 619 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 620 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 621 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 622 } 623 624 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 625 if (!setupGenerator()) 626 return; 627 628 LineTable < = Gen->addLineTable(); 629 LT.addExtendedOpcode(9, DW_LNE_set_address, 630 {{0x1122334455667788, LineTable::Quad}}); 631 LT.addStandardOpcode(DW_LNS_copy, {}); 632 LT.addByte(0xaa); 633 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 634 LT.addExtendedOpcode(9, DW_LNE_set_address, 635 {{0x99aabbccddeeff00, LineTable::Quad}}); 636 LT.addStandardOpcode(DW_LNS_copy, {}); 637 LT.addByte(0xbb); 638 LT.addByte(0xcc); 639 640 generate(); 641 642 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 643 nullptr, RecordRecoverable); 644 checkError("last sequence in debug line table at offset 0x00000000 is not " 645 "terminated", 646 std::move(Recoverable)); 647 ASSERT_TRUE(ExpectedLineTable.operator bool()); 648 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 649 // The unterminated sequence is not added to the sequence list. 650 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 651 } 652 653 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 654 if (!setupGenerator()) 655 return; 656 657 DWARFDebugLine::SectionParser Parser = setupParser(); 658 659 EXPECT_EQ(Parser.getOffset(), 0u); 660 ASSERT_FALSE(Parser.done()); 661 662 DWARFDebugLine::LineTable Parsed = 663 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 664 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 665 EXPECT_EQ(Parsed.Sequences.size(), 1u); 666 EXPECT_EQ(Parser.getOffset(), 62u); 667 ASSERT_FALSE(Parser.done()); 668 669 DWARFDebugLine::LineTable Parsed2 = 670 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 671 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 672 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 673 EXPECT_EQ(Parser.getOffset(), 136u); 674 EXPECT_TRUE(Parser.done()); 675 676 EXPECT_FALSE(Recoverable); 677 EXPECT_FALSE(Unrecoverable); 678 } 679 680 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 681 if (!setupGenerator()) 682 return; 683 684 DWARFDebugLine::SectionParser Parser = setupParser(); 685 686 EXPECT_EQ(Parser.getOffset(), 0u); 687 ASSERT_FALSE(Parser.done()); 688 689 Parser.skip(RecordRecoverable, RecordUnrecoverable); 690 EXPECT_EQ(Parser.getOffset(), 62u); 691 ASSERT_FALSE(Parser.done()); 692 693 Parser.skip(RecordRecoverable, RecordUnrecoverable); 694 EXPECT_EQ(Parser.getOffset(), 136u); 695 EXPECT_TRUE(Parser.done()); 696 697 EXPECT_FALSE(Recoverable); 698 EXPECT_FALSE(Unrecoverable); 699 } 700 701 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 702 if (!setupGenerator()) 703 return; 704 705 generate(); 706 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 707 708 EXPECT_TRUE(Parser.done()); 709 } 710 711 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { 712 if (!setupGenerator()) 713 return; 714 715 LineTable < = Gen->addLineTable(); 716 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 717 Gen->addLineTable(); 718 generate(); 719 720 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 721 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 722 723 EXPECT_EQ(Parser.getOffset(), 4u); 724 EXPECT_TRUE(Parser.done()); 725 EXPECT_FALSE(Recoverable); 726 727 checkError("parsing line table prologue at offset 0x00000000 unsupported " 728 "reserved unit length found of value 0xfffffff0", 729 std::move(Unrecoverable)); 730 } 731 732 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { 733 if (!setupGenerator()) 734 return; 735 736 LineTable < = Gen->addLineTable(); 737 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 738 Gen->addLineTable(); 739 generate(); 740 741 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 742 Parser.skip(RecordRecoverable, RecordUnrecoverable); 743 744 EXPECT_EQ(Parser.getOffset(), 4u); 745 EXPECT_TRUE(Parser.done()); 746 EXPECT_FALSE(Recoverable); 747 748 checkError("parsing line table prologue at offset 0x00000000 unsupported " 749 "reserved unit length found of value 0xfffffff0", 750 std::move(Unrecoverable)); 751 } 752 753 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 754 if (!setupGenerator()) 755 return; 756 757 LineTable < = Gen->addLineTable(DWARF32); 758 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 759 LineTable <2 = Gen->addLineTable(DWARF32); 760 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 761 generate(); 762 763 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 764 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 765 ASSERT_FALSE(Parser.done()); 766 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 767 768 EXPECT_TRUE(Parser.done()); 769 EXPECT_FALSE(Recoverable); 770 771 checkError({"parsing line table prologue at offset 0x00000000 found " 772 "unsupported version 0x00", 773 "parsing line table prologue at offset 0x00000006 found " 774 "unsupported version 0x01"}, 775 std::move(Unrecoverable)); 776 } 777 778 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 779 if (!setupGenerator()) 780 return; 781 782 LineTable < = Gen->addLineTable(DWARF32); 783 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 784 LineTable <2 = Gen->addLineTable(DWARF32); 785 LT2.addExtendedOpcode(9, DW_LNE_set_address, 786 {{0x1234567890abcdef, LineTable::Quad}}); 787 LT2.addStandardOpcode(DW_LNS_copy, {}); 788 LT2.addByte(0xbb); 789 generate(); 790 791 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 792 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 793 EXPECT_FALSE(Unrecoverable); 794 ASSERT_FALSE(Parser.done()); 795 checkError( 796 "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01", 797 std::move(Recoverable)); 798 799 // Reset the error state so that it does not confuse the next set of checks. 800 Unrecoverable = Error::success(); 801 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 802 803 EXPECT_TRUE(Parser.done()); 804 checkError("last sequence in debug line table at offset 0x00000031 is not " 805 "terminated", 806 std::move(Recoverable)); 807 EXPECT_FALSE(Unrecoverable); 808 } 809 810 TEST_F(DebugLineBasicFixture, 811 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 812 if (!setupGenerator()) 813 return; 814 815 LineTable < = Gen->addLineTable(DWARF32); 816 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 817 LineTable <2 = Gen->addLineTable(DWARF32); 818 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 819 generate(); 820 821 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 822 Parser.skip(RecordRecoverable, RecordUnrecoverable); 823 ASSERT_FALSE(Parser.done()); 824 Parser.skip(RecordRecoverable, RecordUnrecoverable); 825 826 EXPECT_TRUE(Parser.done()); 827 EXPECT_FALSE(Recoverable); 828 829 checkError({"parsing line table prologue at offset 0x00000000 found " 830 "unsupported version 0x00", 831 "parsing line table prologue at offset 0x00000006 found " 832 "unsupported version 0x01"}, 833 std::move(Unrecoverable)); 834 } 835 836 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 837 if (!setupGenerator()) 838 return; 839 840 LineTable < = Gen->addLineTable(DWARF32); 841 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 842 generate(); 843 844 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 845 Parser.skip(RecordRecoverable, RecordUnrecoverable); 846 847 EXPECT_TRUE(Parser.done()); 848 EXPECT_FALSE(Recoverable); 849 EXPECT_FALSE(Unrecoverable); 850 } 851 852 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) { 853 if (!setupGenerator()) 854 return; 855 856 using ValLen = dwarfgen::LineTable::ValueAndLength; 857 LineTable < = Gen->addLineTable(DWARF32); 858 LT.addStandardOpcode(DW_LNS_copy, {}); 859 LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}}); 860 LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}}); 861 LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}}); 862 LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}}); 863 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 864 LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 865 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 866 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}}); 867 LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 868 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 869 LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}}); 870 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 871 generate(); 872 873 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 874 std::string Output; 875 raw_string_ostream OS(Output); 876 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS); 877 OS.flush(); 878 879 EXPECT_FALSE(Recoverable); 880 EXPECT_FALSE(Unrecoverable); 881 auto InOutput = [&Output](char const *Str) { 882 return Output.find(Str) != std::string::npos; 883 }; 884 EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output; 885 EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output; 886 // FIXME: The value printed after DW_LNS_advance_line is currently the result 887 // of the advance, but it should be the value being advanced by. See 888 // https://bugs.llvm.org/show_bug.cgi?id=44261 for details. 889 EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output; 890 EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output; 891 EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output; 892 EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output; 893 EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output; 894 EXPECT_TRUE( 895 InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n")) 896 << Output; 897 EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n")) 898 << Output; 899 EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output; 900 EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output; 901 EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; 902 } 903 904 } // end anonymous namespace 905