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, GetOrParseLineTableValidTable) { 239 if (!setupGenerator(Version)) 240 return; 241 242 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 243 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 244 245 LineTable < = Gen->addLineTable(Format); 246 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 247 LT.addStandardOpcode(DW_LNS_copy, {}); 248 LT.addByte(0xaa); 249 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 250 251 LineTable <2 = Gen->addLineTable(Format); 252 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 253 LT2.addStandardOpcode(DW_LNS_copy, {}); 254 LT2.addByte(0xbb); 255 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 256 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 257 LT2.addStandardOpcode(DW_LNS_copy, {}); 258 LT2.addByte(0xcc); 259 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 260 261 generate(); 262 263 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 264 nullptr, RecordRecoverable); 265 ASSERT_TRUE(ExpectedLineTable.operator bool()); 266 EXPECT_FALSE(Recoverable); 267 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 268 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 269 EXPECT_EQ(Expected->Sequences.size(), 1u); 270 271 uint64_t SecondOffset = 272 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 273 Recoverable = Error::success(); 274 auto ExpectedLineTable2 = Line.getOrParseLineTable( 275 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 276 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 277 EXPECT_FALSE(Recoverable); 278 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 279 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 280 EXPECT_EQ(Expected2->Sequences.size(), 2u); 281 282 EXPECT_NE(Expected, Expected2); 283 284 // Check that if the same offset is requested, the exact same pointer is 285 // returned. 286 Recoverable = Error::success(); 287 auto ExpectedLineTable3 = Line.getOrParseLineTable( 288 LineData, 0, *Context, nullptr, RecordRecoverable); 289 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 290 EXPECT_FALSE(Recoverable); 291 EXPECT_EQ(Expected, *ExpectedLineTable3); 292 293 Recoverable = Error::success(); 294 auto ExpectedLineTable4 = Line.getOrParseLineTable( 295 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 296 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 297 EXPECT_FALSE(Recoverable); 298 EXPECT_EQ(Expected2, *ExpectedLineTable4); 299 300 // TODO: Add tests that show that the body of the programs have been read 301 // correctly. 302 } 303 304 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 305 if (!setupGenerator()) 306 return; 307 308 LineTable < = Gen->addLineTable(); 309 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 310 311 generate(); 312 313 checkGetOrParseLineTableEmitsFatalError( 314 "parsing line table prologue at offset 0x00000000 unsupported reserved " 315 "unit length found of value 0xfffffff0"); 316 } 317 318 TEST_F(DebugLineBasicFixture, ErrorForLowVersion) { 319 if (!setupGenerator()) 320 return; 321 322 LineTable < = Gen->addLineTable(); 323 LT.setCustomPrologue( 324 {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}}); 325 326 generate(); 327 328 checkGetOrParseLineTableEmitsFatalError( 329 "parsing line table prologue at offset " 330 "0x00000000 found unsupported version " 331 "0x01"); 332 } 333 334 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 335 if (!setupGenerator(5)) 336 return; 337 338 LineTable < = Gen->addLineTable(); 339 LT.setCustomPrologue({ 340 {19, LineTable::Long}, // unit length 341 {5, LineTable::Half}, // version 342 {8, LineTable::Byte}, // addr size 343 {0, LineTable::Byte}, // segment selector size 344 {11, LineTable::Long}, // prologue length 345 {1, LineTable::Byte}, // min instruction length 346 {1, LineTable::Byte}, // max ops per instruction 347 {1, LineTable::Byte}, // default is_stmt 348 {0, LineTable::Byte}, // line base 349 {14, LineTable::Byte}, // line range 350 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 351 // setup required). 352 {0, LineTable::Byte}, // standard opcode lengths 353 {0, LineTable::Byte}, // directory entry format count (should not be 354 // zero). 355 {0, LineTable::ULEB}, // directories count 356 {0, LineTable::Byte}, // file name entry format count 357 {0, LineTable::ULEB} // file name entry count 358 }); 359 360 generate(); 361 362 checkGetOrParseLineTableEmitsFatalError( 363 {"parsing line table prologue at 0x00000000 found an invalid directory " 364 "or file table description at 0x00000014", 365 "failed to parse entry content descriptions because no path was found"}); 366 } 367 368 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 369 if (!setupGenerator(Version)) 370 return; 371 372 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 373 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 374 375 LineTable < = Gen->addLineTable(Format); 376 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 377 ++Prologue.PrologueLength; 378 LT.setPrologue(Prologue); 379 380 generate(); 381 382 uint64_t ExpectedEnd = 383 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 384 checkGetOrParseLineTableEmitsFatalError( 385 (Twine("parsing line table prologue at 0x00000000 should have ended at " 386 "0x000000") + 387 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 388 Twine::utohexstr(ExpectedEnd - 1)) 389 .str()); 390 } 391 392 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 393 if (!setupGenerator(Version)) 394 return; 395 396 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 397 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 398 399 LineTable < = Gen->addLineTable(Format); 400 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 401 // FIXME: Ideally, we'd test for 1 less than expected, but the code does not 402 // currently fail if missing only the terminator of a v2-4 file table. 403 if (Version < 5) 404 Prologue.PrologueLength -= 2; 405 else 406 Prologue.PrologueLength -= 1; 407 LT.setPrologue(Prologue); 408 409 generate(); 410 411 uint64_t ExpectedEnd = 412 Prologue.TotalLength - 1 + Prologue.sizeofTotalLength(); 413 if (Version < 5) 414 --ExpectedEnd; 415 checkGetOrParseLineTableEmitsFatalError( 416 (Twine("parsing line table prologue at 0x00000000 should have ended at " 417 "0x000000") + 418 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 419 Twine::utohexstr(ExpectedEnd + 1)) 420 .str()); 421 } 422 423 INSTANTIATE_TEST_CASE_P( 424 LineTableTestParams, DebugLineParameterisedFixture, 425 Values(std::make_pair( 426 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 427 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 428 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 429 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 430 431 TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) { 432 if (!setupGenerator()) 433 return; 434 435 LineTable < = Gen->addLineTable(); 436 // The Length should be 1 for an end sequence opcode. 437 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 438 439 generate(); 440 441 checkGetOrParseLineTableEmitsFatalError( 442 "unexpected line op length at offset " 443 "0x00000030 expected 0x02 found 0x01"); 444 } 445 446 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 447 if (!setupGenerator()) 448 return; 449 450 LineTable &Padding = Gen->addLineTable(); 451 // Add some padding to show that a non-zero offset is handled correctly. 452 Padding.setCustomPrologue({{0, LineTable::Byte}}); 453 LineTable < = Gen->addLineTable(); 454 LT.addStandardOpcode(DW_LNS_copy, {}); 455 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 456 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 457 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 458 // Set the total length to 1 higher than the actual length. The program body 459 // has size 5. 460 Prologue.TotalLength += 6; 461 LT.setPrologue(Prologue); 462 463 generate(); 464 465 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 466 nullptr, RecordRecoverable); 467 checkError("line table program with offset 0x00000001 has length 0x00000034 " 468 "but only 0x00000033 bytes are available", 469 std::move(Recoverable)); 470 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 471 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 472 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 473 } 474 475 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 476 if (!setupGenerator(4, 8)) 477 return; 478 479 LineTable < = Gen->addLineTable(); 480 // The line data extractor expects size 8 (Quad) addresses. 481 uint64_t Addr1 = 0x11223344; 482 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 483 LT.addStandardOpcode(DW_LNS_copy, {}); 484 // Show that the expected address size is unchanged, so later valid lines 485 // don't cause a problem. 486 uint64_t Addr2 = 0x1122334455667788; 487 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 488 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 489 490 generate(); 491 492 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 493 nullptr, RecordRecoverable); 494 checkError( 495 "mismatching address size at offset 0x00000030 expected 0x08 found 0x04", 496 std::move(Recoverable)); 497 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 498 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 499 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 500 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 501 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 502 } 503 504 TEST_F(DebugLineBasicFixture, 505 ErrorForMismatchedAddressSizeUnsetInitialAddress) { 506 if (!setupGenerator(4, 0)) 507 return; 508 509 LineTable < = Gen->addLineTable(); 510 uint64_t Addr1 = 0x11223344; 511 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 512 LT.addStandardOpcode(DW_LNS_copy, {}); 513 uint64_t Addr2 = 0x1122334455667788; 514 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 515 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 516 517 generate(); 518 519 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 520 nullptr, RecordRecoverable); 521 checkError( 522 "mismatching address size at offset 0x00000038 expected 0x04 found 0x08", 523 std::move(Recoverable)); 524 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 525 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 526 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 527 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 528 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 529 } 530 531 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 532 if (!setupGenerator()) 533 return; 534 535 LineTable < = Gen->addLineTable(); 536 LT.addExtendedOpcode(9, DW_LNE_set_address, 537 {{0x1122334455667788, LineTable::Quad}}); 538 LT.addStandardOpcode(DW_LNS_copy, {}); 539 LT.addByte(0xaa); 540 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 541 LT.addExtendedOpcode(9, DW_LNE_set_address, 542 {{0x99aabbccddeeff00, LineTable::Quad}}); 543 LT.addStandardOpcode(DW_LNS_copy, {}); 544 LT.addByte(0xbb); 545 LT.addByte(0xcc); 546 547 generate(); 548 549 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 550 nullptr, RecordRecoverable); 551 checkError("last sequence in debug line table at offset 0x00000000 is not " 552 "terminated", 553 std::move(Recoverable)); 554 ASSERT_TRUE(ExpectedLineTable.operator bool()); 555 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 556 // The unterminated sequence is not added to the sequence list. 557 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 558 } 559 560 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 561 if (!setupGenerator()) 562 return; 563 564 DWARFDebugLine::SectionParser Parser = setupParser(); 565 566 EXPECT_EQ(Parser.getOffset(), 0u); 567 ASSERT_FALSE(Parser.done()); 568 569 DWARFDebugLine::LineTable Parsed = 570 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 571 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 572 EXPECT_EQ(Parsed.Sequences.size(), 1u); 573 EXPECT_EQ(Parser.getOffset(), 62u); 574 ASSERT_FALSE(Parser.done()); 575 576 DWARFDebugLine::LineTable Parsed2 = 577 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 578 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 579 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 580 EXPECT_EQ(Parser.getOffset(), 136u); 581 EXPECT_TRUE(Parser.done()); 582 583 EXPECT_FALSE(Recoverable); 584 EXPECT_FALSE(Unrecoverable); 585 } 586 587 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 588 if (!setupGenerator()) 589 return; 590 591 DWARFDebugLine::SectionParser Parser = setupParser(); 592 593 EXPECT_EQ(Parser.getOffset(), 0u); 594 ASSERT_FALSE(Parser.done()); 595 596 Parser.skip(RecordUnrecoverable); 597 EXPECT_EQ(Parser.getOffset(), 62u); 598 ASSERT_FALSE(Parser.done()); 599 600 Parser.skip(RecordUnrecoverable); 601 EXPECT_EQ(Parser.getOffset(), 136u); 602 EXPECT_TRUE(Parser.done()); 603 604 EXPECT_FALSE(Unrecoverable); 605 } 606 607 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 608 if (!setupGenerator()) 609 return; 610 611 generate(); 612 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 613 614 EXPECT_TRUE(Parser.done()); 615 } 616 617 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { 618 if (!setupGenerator()) 619 return; 620 621 LineTable < = Gen->addLineTable(); 622 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 623 Gen->addLineTable(); 624 generate(); 625 626 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 627 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 628 629 EXPECT_EQ(Parser.getOffset(), 4u); 630 EXPECT_TRUE(Parser.done()); 631 EXPECT_FALSE(Recoverable); 632 633 checkError("parsing line table prologue at offset 0x00000000 unsupported " 634 "reserved unit length found of value 0xfffffff0", 635 std::move(Unrecoverable)); 636 } 637 638 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { 639 if (!setupGenerator()) 640 return; 641 642 LineTable < = Gen->addLineTable(); 643 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 644 Gen->addLineTable(); 645 generate(); 646 647 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 648 Parser.skip(RecordUnrecoverable); 649 650 EXPECT_EQ(Parser.getOffset(), 4u); 651 EXPECT_TRUE(Parser.done()); 652 653 checkError("parsing line table prologue at offset 0x00000000 unsupported " 654 "reserved unit length found of value 0xfffffff0", 655 std::move(Unrecoverable)); 656 } 657 658 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 659 if (!setupGenerator()) 660 return; 661 662 LineTable < = Gen->addLineTable(DWARF32); 663 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 664 LineTable <2 = Gen->addLineTable(DWARF32); 665 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 666 generate(); 667 668 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 669 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 670 ASSERT_FALSE(Parser.done()); 671 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 672 673 EXPECT_TRUE(Parser.done()); 674 EXPECT_FALSE(Recoverable); 675 676 checkError({"parsing line table prologue at offset 0x00000000 found " 677 "unsupported version 0x00", 678 "parsing line table prologue at offset 0x00000006 found " 679 "unsupported version 0x01"}, 680 std::move(Unrecoverable)); 681 } 682 683 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 684 if (!setupGenerator()) 685 return; 686 687 LineTable < = Gen->addLineTable(DWARF32); 688 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 689 LineTable <2 = Gen->addLineTable(DWARF32); 690 LT2.addExtendedOpcode(9, DW_LNE_set_address, 691 {{0x1234567890abcdef, LineTable::Quad}}); 692 LT2.addStandardOpcode(DW_LNS_copy, {}); 693 LT2.addByte(0xbb); 694 generate(); 695 696 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 697 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 698 EXPECT_FALSE(Recoverable); 699 ASSERT_FALSE(Parser.done()); 700 checkError( 701 "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01", 702 std::move(Unrecoverable)); 703 704 // Reset the error state so that it does not confuse the next set of checks. 705 Unrecoverable = Error::success(); 706 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 707 708 EXPECT_TRUE(Parser.done()); 709 checkError("last sequence in debug line table at offset 0x00000031 is not " 710 "terminated", 711 std::move(Recoverable)); 712 EXPECT_FALSE(Unrecoverable); 713 } 714 715 TEST_F(DebugLineBasicFixture, 716 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 717 if (!setupGenerator()) 718 return; 719 720 LineTable < = Gen->addLineTable(DWARF32); 721 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 722 LineTable <2 = Gen->addLineTable(DWARF32); 723 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 724 generate(); 725 726 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 727 Parser.skip(RecordUnrecoverable); 728 ASSERT_FALSE(Parser.done()); 729 Parser.skip(RecordUnrecoverable); 730 731 EXPECT_TRUE(Parser.done()); 732 733 checkError({"parsing line table prologue at offset 0x00000000 found " 734 "unsupported version 0x00", 735 "parsing line table prologue at offset 0x00000006 found " 736 "unsupported version 0x01"}, 737 std::move(Unrecoverable)); 738 } 739 740 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 741 if (!setupGenerator()) 742 return; 743 744 LineTable < = Gen->addLineTable(DWARF32); 745 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 746 generate(); 747 748 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 749 Parser.skip(RecordUnrecoverable); 750 751 EXPECT_TRUE(Parser.done()); 752 EXPECT_FALSE(Unrecoverable); 753 } 754 755 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) { 756 if (!setupGenerator()) 757 return; 758 759 using ValLen = dwarfgen::LineTable::ValueAndLength; 760 LineTable < = Gen->addLineTable(DWARF32); 761 LT.addStandardOpcode(DW_LNS_copy, {}); 762 LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}}); 763 LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}}); 764 LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}}); 765 LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}}); 766 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 767 LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 768 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 769 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}}); 770 LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 771 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 772 LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}}); 773 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 774 generate(); 775 776 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 777 std::string Output; 778 raw_string_ostream OS(Output); 779 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS); 780 OS.flush(); 781 782 EXPECT_FALSE(Recoverable); 783 EXPECT_FALSE(Unrecoverable); 784 auto InOutput = [&Output](char const *Str) { 785 return Output.find(Str) != std::string::npos; 786 }; 787 EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output; 788 EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output; 789 // FIXME: The value printed after DW_LNS_advance_line is currently the result 790 // of the advance, but it should be the value being advanced by. See 791 // https://bugs.llvm.org/show_bug.cgi?id=44261 for details. 792 EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output; 793 EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output; 794 EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output; 795 EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output; 796 EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output; 797 EXPECT_TRUE( 798 InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n")) 799 << Output; 800 EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n")) 801 << Output; 802 EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output; 803 EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output; 804 EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; 805 } 806 807 } // end anonymous namespace 808