1 //===- DWARFDebugLineTest.cpp ---------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DwarfGenerator.h" 11 #include "DwarfUtils.h" 12 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 14 #include "llvm/Object/ObjectFile.h" 15 #include "llvm/Testing/Support/Error.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 using namespace dwarf; 20 using namespace dwarfgen; 21 using namespace object; 22 using namespace utils; 23 using namespace testing; 24 25 namespace { 26 struct CommonFixture { 27 CommonFixture() 28 : LineData("", true, 0), Recoverable(Error::success()), 29 RecordRecoverable(std::bind(&CommonFixture::recordRecoverable, this, 30 std::placeholders::_1)), 31 Unrecoverable(Error::success()), 32 RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this, 33 std::placeholders::_1)){}; 34 35 ~CommonFixture() { 36 EXPECT_FALSE(Recoverable); 37 EXPECT_FALSE(Unrecoverable); 38 } 39 40 bool setupGenerator(uint16_t Version = 4) { 41 Triple T = getHostTripleForAddrSize(8); 42 if (!isConfigurationSupported(T)) 43 return false; 44 auto ExpectedGenerator = Generator::create(T, Version); 45 if (ExpectedGenerator) 46 Gen.reset(ExpectedGenerator->release()); 47 return true; 48 } 49 50 void generate() { 51 Context = createContext(); 52 assert(Context != nullptr && "test state is not valid"); 53 const DWARFObject &Obj = Context->getDWARFObj(); 54 LineData = DWARFDataExtractor(Obj, Obj.getLineSection(), 55 sys::IsLittleEndianHost, 8); 56 } 57 58 std::unique_ptr<DWARFContext> createContext() { 59 if (!Gen) 60 return nullptr; 61 StringRef FileBytes = Gen->generate(); 62 MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 63 auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 64 if (Obj) 65 return DWARFContext::create(**Obj); 66 return nullptr; 67 } 68 69 DWARFDebugLine::SectionParser setupParser() { 70 LineTable < = Gen->addLineTable(DWARF32); 71 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 72 LT.addStandardOpcode(DW_LNS_copy, {}); 73 LT.addByte(0xaa); 74 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 75 76 LineTable <2 = Gen->addLineTable(DWARF64); 77 LT2.addExtendedOpcode(9, DW_LNE_set_address, 78 {{0x11223344, LineTable::Quad}}); 79 LT2.addStandardOpcode(DW_LNS_copy, {}); 80 LT2.addByte(0xbb); 81 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 82 83 generate(); 84 85 return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs); 86 } 87 88 void recordRecoverable(Error Err) { 89 Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); 90 } 91 void recordUnrecoverable(Error Err) { 92 Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); 93 } 94 95 void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) { 96 ASSERT_TRUE(Err.operator bool()); 97 size_t WhichMsg = 0; 98 Error Remaining = 99 handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) { 100 ASSERT_LT(WhichMsg, ExpectedMsgs.size()); 101 // Use .str(), because googletest doesn't visualise a StringRef 102 // properly. 103 EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str()); 104 }); 105 EXPECT_EQ(WhichMsg, ExpectedMsgs.size()); 106 EXPECT_FALSE(Remaining); 107 } 108 109 void checkError(StringRef ExpectedMsg, Error Err) { 110 checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err)); 111 } 112 113 void checkGetOrParseLineTableEmitsError(StringRef ExpectedMsg, 114 uint64_t Offset = 0) { 115 auto ExpectedLineTable = Line.getOrParseLineTable( 116 LineData, Offset, *Context, nullptr, RecordRecoverable); 117 EXPECT_FALSE(ExpectedLineTable); 118 EXPECT_FALSE(Recoverable); 119 120 checkError(ExpectedMsg, ExpectedLineTable.takeError()); 121 } 122 123 std::unique_ptr<Generator> Gen; 124 std::unique_ptr<DWARFContext> Context; 125 DWARFDataExtractor LineData; 126 DWARFDebugLine Line; 127 Error Recoverable; 128 std::function<void(Error)> RecordRecoverable; 129 Error Unrecoverable; 130 std::function<void(Error)> RecordUnrecoverable; 131 132 SmallVector<std::unique_ptr<DWARFCompileUnit>, 2> CUs; 133 std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs; 134 }; 135 136 // Fixtures must derive from "Test", but parameterised fixtures from 137 // "TestWithParam". It does not seem possible to inherit from both, so we share 138 // the common state in a separate class, inherited by the two fixture classes. 139 struct DebugLineBasicFixture : public Test, public CommonFixture {}; 140 141 struct DebugLineParameterisedFixture 142 : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 143 public CommonFixture { 144 void SetUp() { std::tie(Version, Format) = GetParam(); } 145 146 uint16_t Version; 147 DwarfFormat Format; 148 }; 149 150 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 151 DWARFDebugLine::Prologue Prologue, 152 uint64_t BodyLength) { 153 // Check version specific fields and values. 154 uint64_t UnitLength; 155 uint64_t PrologueLength; 156 switch (Version) { 157 case 4: 158 PrologueLength = 36; 159 UnitLength = PrologueLength + 2; 160 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 161 break; 162 case 2: 163 case 3: 164 PrologueLength = 35; 165 UnitLength = PrologueLength + 2; 166 break; 167 case 5: 168 PrologueLength = 39; 169 UnitLength = PrologueLength + 4; 170 EXPECT_EQ(Prologue.getAddressSize(), 8u); 171 EXPECT_EQ(Prologue.SegSelectorSize, 0u); 172 break; 173 default: 174 llvm_unreachable("unsupported DWARF version"); 175 } 176 UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 177 178 EXPECT_EQ(Prologue.TotalLength, UnitLength); 179 EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 180 EXPECT_EQ(Prologue.MinInstLength, 1u); 181 EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 182 EXPECT_EQ(Prologue.LineBase, -5); 183 EXPECT_EQ(Prologue.LineRange, 14u); 184 EXPECT_EQ(Prologue.OpcodeBase, 13u); 185 std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 186 EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 187 ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 188 ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 189 EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 190 ASSERT_EQ(Prologue.FileNames.size(), 1u); 191 ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 192 EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 193 } 194 195 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 196 if (!setupGenerator()) 197 return; 198 generate(); 199 200 checkGetOrParseLineTableEmitsError( 201 "offset 0x00000000 is not a valid debug line section offset", 0); 202 // Repeat to show that an error is reported each time. 203 checkGetOrParseLineTableEmitsError( 204 "offset 0x00000000 is not a valid debug line section offset", 0); 205 // Show that an error is reported for later offsets too. 206 checkGetOrParseLineTableEmitsError( 207 "offset 0x00000001 is not a valid debug line section offset", 1); 208 } 209 210 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 211 if (!setupGenerator()) 212 return; 213 214 LineTable < = Gen->addLineTable(); 215 LT.setCustomPrologue({{0, LineTable::Byte}}); 216 217 generate(); 218 219 checkGetOrParseLineTableEmitsError( 220 "offset 0x00000001 is not a valid debug line section offset", 1); 221 } 222 223 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 224 if (!setupGenerator(Version)) 225 return; 226 227 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 228 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 229 230 LineTable < = Gen->addLineTable(Format); 231 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 232 LT.addStandardOpcode(DW_LNS_copy, {}); 233 LT.addByte(0xaa); 234 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 235 236 LineTable <2 = Gen->addLineTable(Format); 237 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 238 LT2.addStandardOpcode(DW_LNS_copy, {}); 239 LT2.addByte(0xbb); 240 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 241 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 242 LT2.addStandardOpcode(DW_LNS_copy, {}); 243 LT2.addByte(0xcc); 244 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 245 246 generate(); 247 248 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 249 nullptr, RecordRecoverable); 250 ASSERT_TRUE(ExpectedLineTable.operator bool()); 251 EXPECT_FALSE(Recoverable); 252 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 253 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 254 EXPECT_EQ(Expected->Sequences.size(), 1u); 255 256 uint64_t SecondOffset = 257 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 258 Recoverable = Error::success(); 259 auto ExpectedLineTable2 = Line.getOrParseLineTable( 260 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 261 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 262 EXPECT_FALSE(Recoverable); 263 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 264 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 265 EXPECT_EQ(Expected2->Sequences.size(), 2u); 266 267 EXPECT_NE(Expected, Expected2); 268 269 // Check that if the same offset is requested, the exact same pointer is 270 // returned. 271 Recoverable = Error::success(); 272 auto ExpectedLineTable3 = Line.getOrParseLineTable( 273 LineData, 0, *Context, nullptr, RecordRecoverable); 274 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 275 EXPECT_FALSE(Recoverable); 276 EXPECT_EQ(Expected, *ExpectedLineTable3); 277 278 Recoverable = Error::success(); 279 auto ExpectedLineTable4 = Line.getOrParseLineTable( 280 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 281 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 282 EXPECT_FALSE(Recoverable); 283 EXPECT_EQ(Expected2, *ExpectedLineTable4); 284 285 // TODO: Add tests that show that the body of the programs have been read 286 // correctly. 287 } 288 289 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 290 if (!setupGenerator()) 291 return; 292 293 LineTable < = Gen->addLineTable(); 294 LT.setCustomPrologue({{0xffffff00, LineTable::Long}}); 295 296 generate(); 297 298 checkGetOrParseLineTableEmitsError( 299 "parsing line table prologue at offset 0x00000000 unsupported reserved " 300 "unit length found of value 0xffffff00"); 301 } 302 303 TEST_F(DebugLineBasicFixture, ErrorForLowVersion) { 304 if (!setupGenerator()) 305 return; 306 307 LineTable < = Gen->addLineTable(); 308 LT.setCustomPrologue( 309 {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}}); 310 311 generate(); 312 313 checkGetOrParseLineTableEmitsError("parsing line table prologue at offset " 314 "0x00000000 found unsupported version " 315 "0x01"); 316 } 317 318 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 319 if (!setupGenerator(5)) 320 return; 321 322 LineTable < = Gen->addLineTable(); 323 LT.setCustomPrologue({ 324 {19, LineTable::Long}, // unit length 325 {5, LineTable::Half}, // version 326 {8, LineTable::Byte}, // addr size 327 {0, LineTable::Byte}, // segment selector size 328 {11, LineTable::Long}, // prologue length 329 {1, LineTable::Byte}, // min instruction length 330 {1, LineTable::Byte}, // max ops per instruction 331 {1, LineTable::Byte}, // default is_stmt 332 {0, LineTable::Byte}, // line base 333 {14, LineTable::Byte}, // line range 334 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 335 // setup required). 336 {0, LineTable::Byte}, // standard opcode lengths 337 {0, LineTable::Byte}, // directory entry format count (should not be 338 // zero). 339 {0, LineTable::ULEB}, // directories count 340 {0, LineTable::Byte}, // file name entry format count 341 {0, LineTable::ULEB} // file name entry count 342 }); 343 344 generate(); 345 346 checkGetOrParseLineTableEmitsError( 347 "parsing line table prologue at 0x00000000 found an invalid directory or " 348 "file table description at 0x00000014"); 349 } 350 351 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 352 if (!setupGenerator(Version)) 353 return; 354 355 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 356 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 357 358 LineTable < = Gen->addLineTable(Format); 359 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 360 ++Prologue.PrologueLength; 361 LT.setPrologue(Prologue); 362 363 generate(); 364 365 uint64_t ExpectedEnd = 366 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 367 checkGetOrParseLineTableEmitsError( 368 (Twine("parsing line table prologue at 0x00000000 should have ended at " 369 "0x000000") + 370 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 371 Twine::utohexstr(ExpectedEnd - 1)) 372 .str()); 373 } 374 375 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 376 if (!setupGenerator(Version)) 377 return; 378 379 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 380 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 381 382 LineTable < = Gen->addLineTable(Format); 383 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 384 // FIXME: Ideally, we'd test for 1 less than expected, but the code does not 385 // currently fail if missing only the terminator of a v2-4 file table. 386 if (Version < 5) 387 Prologue.PrologueLength -= 2; 388 else 389 Prologue.PrologueLength -= 1; 390 LT.setPrologue(Prologue); 391 392 generate(); 393 394 uint64_t ExpectedEnd = 395 Prologue.TotalLength - 1 + Prologue.sizeofTotalLength(); 396 if (Version < 5) 397 --ExpectedEnd; 398 checkGetOrParseLineTableEmitsError( 399 (Twine("parsing line table prologue at 0x00000000 should have ended at " 400 "0x000000") + 401 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 402 Twine::utohexstr(ExpectedEnd + 1)) 403 .str()); 404 } 405 406 INSTANTIATE_TEST_CASE_P( 407 LineTableTestParams, DebugLineParameterisedFixture, 408 Values(std::make_pair( 409 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 410 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 411 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 412 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 413 414 TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) { 415 if (!setupGenerator()) 416 return; 417 418 LineTable < = Gen->addLineTable(); 419 // The Length should be 1 for an end sequence opcode. 420 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 421 422 generate(); 423 424 checkGetOrParseLineTableEmitsError("unexpected line op length at offset " 425 "0x00000030 expected 0x02 found 0x01"); 426 } 427 428 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 429 if (!setupGenerator()) 430 return; 431 432 LineTable < = Gen->addLineTable(); 433 // The line data extractor expects size 8 (Quad) addresses. 434 LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x11223344, LineTable::Long}}); 435 LT.addStandardOpcode(DW_LNS_copy, {}); 436 LT.addByte(0xaa); 437 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 438 439 generate(); 440 441 checkGetOrParseLineTableEmitsError( 442 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04"); 443 } 444 445 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 446 if (!setupGenerator()) 447 return; 448 449 LineTable < = Gen->addLineTable(); 450 LT.addExtendedOpcode(9, DW_LNE_set_address, 451 {{0x1122334455667788, LineTable::Quad}}); 452 LT.addStandardOpcode(DW_LNS_copy, {}); 453 LT.addByte(0xaa); 454 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 455 LT.addExtendedOpcode(9, DW_LNE_set_address, 456 {{0x99aabbccddeeff00, LineTable::Quad}}); 457 LT.addStandardOpcode(DW_LNS_copy, {}); 458 LT.addByte(0xbb); 459 LT.addByte(0xcc); 460 461 generate(); 462 463 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 464 nullptr, RecordRecoverable); 465 checkError("last sequence in debug line table is not terminated!", 466 std::move(Recoverable)); 467 ASSERT_TRUE(ExpectedLineTable.operator bool()); 468 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 469 // The unterminated sequence is not added to the sequence list. 470 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 471 } 472 473 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 474 if (!setupGenerator()) 475 return; 476 477 DWARFDebugLine::SectionParser Parser = setupParser(); 478 479 EXPECT_EQ(Parser.getOffset(), 0u); 480 ASSERT_FALSE(Parser.done()); 481 482 DWARFDebugLine::LineTable Parsed = 483 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 484 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 485 EXPECT_EQ(Parsed.Sequences.size(), 1u); 486 EXPECT_EQ(Parser.getOffset(), 62u); 487 ASSERT_FALSE(Parser.done()); 488 489 DWARFDebugLine::LineTable Parsed2 = 490 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 491 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 492 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 493 EXPECT_EQ(Parser.getOffset(), 136u); 494 EXPECT_TRUE(Parser.done()); 495 496 EXPECT_FALSE(Recoverable); 497 EXPECT_FALSE(Unrecoverable); 498 } 499 500 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 501 if (!setupGenerator()) 502 return; 503 504 DWARFDebugLine::SectionParser Parser = setupParser(); 505 506 EXPECT_EQ(Parser.getOffset(), 0u); 507 ASSERT_FALSE(Parser.done()); 508 509 Parser.skip(RecordUnrecoverable); 510 EXPECT_EQ(Parser.getOffset(), 62u); 511 ASSERT_FALSE(Parser.done()); 512 513 Parser.skip(RecordUnrecoverable); 514 EXPECT_EQ(Parser.getOffset(), 136u); 515 EXPECT_TRUE(Parser.done()); 516 517 EXPECT_FALSE(Unrecoverable); 518 } 519 520 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 521 if (!setupGenerator()) 522 return; 523 524 generate(); 525 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 526 527 EXPECT_TRUE(Parser.done()); 528 } 529 530 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { 531 if (!setupGenerator()) 532 return; 533 534 LineTable < = Gen->addLineTable(); 535 LT.setCustomPrologue({{0xffffff00, LineTable::Long}}); 536 Gen->addLineTable(); 537 generate(); 538 539 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 540 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 541 542 EXPECT_EQ(Parser.getOffset(), 4u); 543 EXPECT_TRUE(Parser.done()); 544 EXPECT_FALSE(Recoverable); 545 546 checkError("parsing line table prologue at offset 0x00000000 unsupported " 547 "reserved unit length found of value 0xffffff00", 548 std::move(Unrecoverable)); 549 } 550 551 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { 552 if (!setupGenerator()) 553 return; 554 555 LineTable < = Gen->addLineTable(); 556 LT.setCustomPrologue({{0xffffff00, LineTable::Long}}); 557 Gen->addLineTable(); 558 generate(); 559 560 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 561 Parser.skip(RecordUnrecoverable); 562 563 EXPECT_EQ(Parser.getOffset(), 4u); 564 EXPECT_TRUE(Parser.done()); 565 566 checkError("parsing line table prologue at offset 0x00000000 unsupported " 567 "reserved unit length found of value 0xffffff00", 568 std::move(Unrecoverable)); 569 } 570 571 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 572 if (!setupGenerator()) 573 return; 574 575 LineTable < = Gen->addLineTable(DWARF32); 576 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 577 LineTable <2 = Gen->addLineTable(DWARF32); 578 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 579 generate(); 580 581 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 582 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 583 ASSERT_FALSE(Parser.done()); 584 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 585 586 EXPECT_TRUE(Parser.done()); 587 EXPECT_FALSE(Recoverable); 588 589 checkError({"parsing line table prologue at offset 0x00000000 found " 590 "unsupported version 0x00", 591 "parsing line table prologue at offset 0x00000006 found " 592 "unsupported version 0x01"}, 593 std::move(Unrecoverable)); 594 } 595 596 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 597 if (!setupGenerator()) 598 return; 599 600 LineTable < = Gen->addLineTable(DWARF32); 601 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 602 LineTable <2 = Gen->addLineTable(DWARF32); 603 LT2.addExtendedOpcode(9, DW_LNE_set_address, 604 {{0x1234567890abcdef, LineTable::Quad}}); 605 LT2.addStandardOpcode(DW_LNS_copy, {}); 606 LT2.addByte(0xbb); 607 generate(); 608 609 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 610 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 611 EXPECT_FALSE(Recoverable); 612 ASSERT_FALSE(Parser.done()); 613 checkError( 614 "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01", 615 std::move(Unrecoverable)); 616 617 // Reset the error state so that it does not confuse the next set of checks. 618 Unrecoverable = Error::success(); 619 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 620 621 EXPECT_TRUE(Parser.done()); 622 checkError("last sequence in debug line table is not terminated!", 623 std::move(Recoverable)); 624 EXPECT_FALSE(Unrecoverable); 625 } 626 627 TEST_F(DebugLineBasicFixture, 628 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 629 if (!setupGenerator()) 630 return; 631 632 LineTable < = Gen->addLineTable(DWARF32); 633 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 634 LineTable <2 = Gen->addLineTable(DWARF32); 635 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 636 generate(); 637 638 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 639 Parser.skip(RecordUnrecoverable); 640 ASSERT_FALSE(Parser.done()); 641 Parser.skip(RecordUnrecoverable); 642 643 EXPECT_TRUE(Parser.done()); 644 645 checkError({"parsing line table prologue at offset 0x00000000 found " 646 "unsupported version 0x00", 647 "parsing line table prologue at offset 0x00000006 found " 648 "unsupported version 0x01"}, 649 std::move(Unrecoverable)); 650 } 651 652 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 653 if (!setupGenerator()) 654 return; 655 656 LineTable < = Gen->addLineTable(DWARF32); 657 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 658 generate(); 659 660 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 661 Parser.skip(RecordUnrecoverable); 662 663 EXPECT_TRUE(Parser.done()); 664 EXPECT_FALSE(Unrecoverable); 665 } 666 667 } // end anonymous namespace 668