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