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 Expected<const DWARFDebugLine::LineTable *> 100 getOrParseLineTableFatalErrors(uint64_t Offset = 0) { 101 auto ExpectedLineTable = Line.getOrParseLineTable( 102 LineData, Offset, *Context, nullptr, RecordRecoverable); 103 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 104 return ExpectedLineTable; 105 } 106 107 uint8_t AddressSize; 108 std::unique_ptr<Generator> Gen; 109 std::unique_ptr<DWARFContext> Context; 110 DWARFDataExtractor LineData; 111 DWARFDebugLine Line; 112 Error Recoverable; 113 std::function<void(Error)> RecordRecoverable; 114 Error Unrecoverable; 115 std::function<void(Error)> RecordUnrecoverable; 116 117 SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs; 118 SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs; 119 }; 120 121 // Fixtures must derive from "Test", but parameterised fixtures from 122 // "TestWithParam". It does not seem possible to inherit from both, so we share 123 // the common state in a separate class, inherited by the two fixture classes. 124 struct DebugLineBasicFixture : public Test, public CommonFixture {}; 125 126 struct DebugLineParameterisedFixture 127 : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 128 public CommonFixture { 129 void SetUp() { std::tie(Version, Format) = GetParam(); } 130 131 uint16_t Version; 132 DwarfFormat Format; 133 }; 134 135 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 136 DWARFDebugLine::Prologue Prologue, 137 uint64_t BodyLength) { 138 // Check version specific fields and values. 139 uint64_t UnitLength; 140 uint64_t PrologueLength; 141 switch (Version) { 142 case 4: 143 PrologueLength = 36; 144 UnitLength = PrologueLength + 2; 145 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 146 break; 147 case 2: 148 case 3: 149 PrologueLength = 35; 150 UnitLength = PrologueLength + 2; 151 break; 152 case 5: 153 PrologueLength = 42; 154 UnitLength = PrologueLength + 4; 155 EXPECT_EQ(Prologue.getAddressSize(), 8u); 156 EXPECT_EQ(Prologue.SegSelectorSize, 0u); 157 break; 158 default: 159 llvm_unreachable("unsupported DWARF version"); 160 } 161 UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 162 163 EXPECT_EQ(Prologue.TotalLength, UnitLength); 164 EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 165 EXPECT_EQ(Prologue.MinInstLength, 1u); 166 EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 167 EXPECT_EQ(Prologue.LineBase, -5); 168 EXPECT_EQ(Prologue.LineRange, 14u); 169 EXPECT_EQ(Prologue.OpcodeBase, 13u); 170 std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 171 EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 172 ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 173 ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 174 EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 175 ASSERT_EQ(Prologue.FileNames.size(), 1u); 176 ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 177 ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u); 178 EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 179 } 180 181 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 182 if (!setupGenerator()) 183 return; 184 generate(); 185 186 EXPECT_THAT_EXPECTED( 187 getOrParseLineTableFatalErrors(0), 188 FailedWithMessage( 189 "offset 0x00000000 is not a valid debug line section offset")); 190 // Repeat to show that an error is reported each time. 191 EXPECT_THAT_EXPECTED( 192 getOrParseLineTableFatalErrors(0), 193 FailedWithMessage( 194 "offset 0x00000000 is not a valid debug line section offset")); 195 196 // Show that an error is reported for later offsets too. 197 EXPECT_THAT_EXPECTED( 198 getOrParseLineTableFatalErrors(1), 199 FailedWithMessage( 200 "offset 0x00000001 is not a valid debug line section offset")); 201 } 202 203 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 204 if (!setupGenerator()) 205 return; 206 207 LineTable < = Gen->addLineTable(); 208 LT.setCustomPrologue({{0, LineTable::Byte}}); 209 210 generate(); 211 212 EXPECT_THAT_EXPECTED( 213 getOrParseLineTableFatalErrors(0), 214 FailedWithMessage( 215 "parsing line table prologue at offset 0x00000000: " 216 "unexpected end of data at offset 0x1 while reading [0x0, 0x4)")); 217 218 EXPECT_THAT_EXPECTED( 219 getOrParseLineTableFatalErrors(1), 220 FailedWithMessage( 221 "offset 0x00000001 is not a valid debug line section offset")); 222 } 223 224 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 225 if (!setupGenerator(Version)) 226 return; 227 LineTable < = Gen->addLineTable(Format); 228 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 229 LT.setPrologue(Prologue); 230 generate(); 231 232 // + 10 for sizes of DWARF-32 unit length, version, prologue length. 233 uint64_t ExpectedLength = Prologue.PrologueLength + 10; 234 if (Version == 5) 235 // Add address and segment selector size fields. 236 ExpectedLength += 2; 237 if (Format == DWARF64) 238 // Unit length grows by 8, prologue length by 4. 239 ExpectedLength += 12; 240 241 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 242 nullptr, RecordRecoverable); 243 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 244 EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 245 } 246 247 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 248 if (!setupGenerator(Version)) 249 return; 250 251 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 252 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 253 254 LineTable < = Gen->addLineTable(Format); 255 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 256 LT.addStandardOpcode(DW_LNS_copy, {}); 257 LT.addByte(0xaa); 258 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 259 260 LineTable <2 = Gen->addLineTable(Format); 261 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 262 LT2.addStandardOpcode(DW_LNS_copy, {}); 263 LT2.addByte(0xbb); 264 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 265 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 266 LT2.addStandardOpcode(DW_LNS_copy, {}); 267 LT2.addByte(0xcc); 268 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 269 270 generate(); 271 272 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 273 nullptr, RecordRecoverable); 274 ASSERT_TRUE(ExpectedLineTable.operator bool()); 275 EXPECT_FALSE(Recoverable); 276 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 277 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 278 EXPECT_EQ(Expected->Sequences.size(), 1u); 279 280 uint64_t SecondOffset = 281 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 282 Recoverable = Error::success(); 283 auto ExpectedLineTable2 = Line.getOrParseLineTable( 284 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 285 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 286 EXPECT_FALSE(Recoverable); 287 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 288 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 289 EXPECT_EQ(Expected2->Sequences.size(), 2u); 290 291 EXPECT_NE(Expected, Expected2); 292 293 // Check that if the same offset is requested, the exact same pointer is 294 // returned. 295 Recoverable = Error::success(); 296 auto ExpectedLineTable3 = Line.getOrParseLineTable( 297 LineData, 0, *Context, nullptr, RecordRecoverable); 298 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 299 EXPECT_FALSE(Recoverable); 300 EXPECT_EQ(Expected, *ExpectedLineTable3); 301 302 Recoverable = Error::success(); 303 auto ExpectedLineTable4 = Line.getOrParseLineTable( 304 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 305 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 306 EXPECT_FALSE(Recoverable); 307 EXPECT_EQ(Expected2, *ExpectedLineTable4); 308 309 // TODO: Add tests that show that the body of the programs have been read 310 // correctly. 311 } 312 313 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 314 if (!setupGenerator()) 315 return; 316 317 LineTable < = Gen->addLineTable(); 318 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 319 320 generate(); 321 322 EXPECT_THAT_EXPECTED( 323 getOrParseLineTableFatalErrors(), 324 FailedWithMessage( 325 "parsing line table prologue at offset 0x00000000: unsupported " 326 "reserved unit length of value 0xfffffff0")); 327 } 328 329 struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>, 330 public CommonFixture { 331 void SetUp() { Version = GetParam(); } 332 333 uint16_t Version; 334 }; 335 336 TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) { 337 if (!setupGenerator()) 338 return; 339 340 LineTable < = Gen->addLineTable(); 341 LT.setCustomPrologue( 342 {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}}); 343 344 generate(); 345 346 EXPECT_THAT_EXPECTED( 347 getOrParseLineTableFatalErrors(), 348 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 349 "unsupported version " + 350 std::to_string(Version))); 351 } 352 353 INSTANTIATE_TEST_CASE_P(UnsupportedVersionTestParams, 354 DebugLineUnsupportedVersionFixture, 355 Values(/*1 below min */ 1, /* 1 above max */ 6, 356 /* Maximum possible */ 0xffff), ); 357 358 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 359 if (!setupGenerator(5)) 360 return; 361 362 LineTable < = Gen->addLineTable(); 363 LT.setCustomPrologue({ 364 {19, LineTable::Long}, // unit length 365 {5, LineTable::Half}, // version 366 {8, LineTable::Byte}, // addr size 367 {0, LineTable::Byte}, // segment selector size 368 {11, LineTable::Long}, // prologue length 369 {1, LineTable::Byte}, // min instruction length 370 {1, LineTable::Byte}, // max ops per instruction 371 {1, LineTable::Byte}, // default is_stmt 372 {0, LineTable::Byte}, // line base 373 {14, LineTable::Byte}, // line range 374 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 375 // setup required). 376 {0, LineTable::Byte}, // standard opcode lengths 377 {0, LineTable::Byte}, // directory entry format count (should not be 378 // zero). 379 {0, LineTable::ULEB}, // directories count 380 {0, LineTable::Byte}, // file name entry format count 381 {0, LineTable::ULEB} // file name entry count 382 }); 383 384 generate(); 385 386 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 387 nullptr, RecordRecoverable); 388 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 389 390 EXPECT_THAT_ERROR( 391 std::move(Recoverable), 392 FailedWithMessage( 393 "parsing line table prologue at 0x00000000 found an invalid " 394 "directory or file table description at 0x00000014", 395 "failed to parse entry content descriptions because no path was " 396 "found")); 397 } 398 399 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 400 if (!setupGenerator(Version)) 401 return; 402 403 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 404 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 405 406 LineTable < = Gen->addLineTable(Format); 407 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 408 ++Prologue.PrologueLength; 409 LT.setPrologue(Prologue); 410 411 generate(); 412 413 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 414 nullptr, RecordRecoverable); 415 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 416 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 417 // Undo the earlier modification so that it can be compared against a 418 // "default" prologue. 419 --Result.Prologue.PrologueLength; 420 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 421 422 uint64_t ExpectedEnd = 423 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 424 EXPECT_THAT_ERROR( 425 std::move(Recoverable), 426 FailedWithMessage(("parsing line table prologue at 0x00000000 should " 427 "have ended at 0x000000" + 428 Twine::utohexstr(ExpectedEnd) + 429 " but it ended at 0x000000" + 430 Twine::utohexstr(ExpectedEnd - 1)) 431 .str())); 432 } 433 434 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 435 if (!setupGenerator(Version)) 436 return; 437 438 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 439 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 440 441 LineTable < = Gen->addLineTable(Format); 442 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 443 Prologue.PrologueLength -= 2; 444 LT.setPrologue(Prologue); 445 446 generate(); 447 448 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 449 nullptr, RecordRecoverable); 450 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 451 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 452 453 if (Version != 5) { 454 // Parsing will stop before reading a complete file entry. 455 ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); 456 EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); 457 EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); 458 } else { 459 // Parsing will continue past the presumed end of prologue. 460 ASSERT_EQ(Result.Prologue.FileNames.size(), 1u); 461 ASSERT_EQ(Result.Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 462 ASSERT_EQ(Result.Prologue.FileNames[0].DirIdx, 0u); 463 EXPECT_EQ(toStringRef(Result.Prologue.FileNames[0].Name), "a file"); 464 } 465 466 uint64_t ExpectedEnd = 467 Prologue.TotalLength - 2 + Prologue.sizeofTotalLength(); 468 std::vector<std::string> Errs; 469 if (Version != 5) { 470 Errs.emplace_back( 471 (Twine("parsing line table prologue at 0x00000000 found an invalid " 472 "directory or file table description at 0x000000") + 473 Twine::utohexstr(ExpectedEnd + 1)) 474 .str()); 475 Errs.emplace_back("file names table was not null terminated before the end " 476 "of the prologue"); 477 } else { 478 Errs.emplace_back( 479 (Twine("parsing line table prologue at 0x00000000 should have ended at " 480 "0x000000") + 481 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 482 Twine::utohexstr(ExpectedEnd + 2)) 483 .str()); 484 } 485 EXPECT_THAT_ERROR(std::move(Recoverable), 486 FailedWithMessageArray(testing::ElementsAreArray(Errs))); 487 } 488 489 INSTANTIATE_TEST_CASE_P( 490 LineTableTestParams, DebugLineParameterisedFixture, 491 Values(std::make_pair( 492 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 493 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 494 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 495 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 496 497 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 498 if (!setupGenerator()) 499 return; 500 501 LineTable < = Gen->addLineTable(); 502 LT.addByte(0xaa); 503 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 504 // The operand will be read for both the discriminator opcode and then parsed 505 // again as DW_LNS_negate_stmt, to respect the claimed length. 506 LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 507 {{DW_LNS_negate_stmt, LineTable::ULEB}}); 508 LT.addByte(0xbb); 509 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 510 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 511 512 generate(); 513 514 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 515 nullptr, RecordRecoverable); 516 EXPECT_THAT_ERROR(std::move(Recoverable), 517 FailedWithMessage("unexpected line op length at offset " 518 "0x00000031 expected 0x01 found 0x02")); 519 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 520 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 521 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 522 EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 523 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 524 } 525 526 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 527 if (!setupGenerator()) 528 return; 529 530 LineTable < = Gen->addLineTable(); 531 LT.addByte(0xaa); 532 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 533 // The Length should be 1 for an end sequence opcode. 534 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 535 // The negate statement opcode will be skipped. 536 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 537 LT.addByte(0xbb); 538 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 539 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 540 541 generate(); 542 543 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 544 nullptr, RecordRecoverable); 545 EXPECT_THAT_ERROR(std::move(Recoverable), 546 FailedWithMessage("unexpected line op length at offset " 547 "0x00000032 expected 0x02 found 0x01")); 548 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 549 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 550 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 551 ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 552 EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 553 } 554 555 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 556 if (!setupGenerator()) 557 return; 558 559 LineTable &Padding = Gen->addLineTable(); 560 // Add some padding to show that a non-zero offset is handled correctly. 561 Padding.setCustomPrologue({{0, LineTable::Byte}}); 562 LineTable < = Gen->addLineTable(); 563 LT.addStandardOpcode(DW_LNS_copy, {}); 564 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 565 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 566 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 567 // Set the total length to 1 higher than the actual length. 568 ++Prologue.TotalLength; 569 LT.setPrologue(Prologue); 570 571 generate(); 572 573 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 574 nullptr, RecordRecoverable); 575 EXPECT_THAT_ERROR( 576 std::move(Recoverable), 577 FailedWithMessage("line table program with offset 0x00000001 has length " 578 "0x00000034 but only 0x00000033 bytes are available")); 579 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 580 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 581 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 582 } 583 584 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 585 if (!setupGenerator(4, 8)) 586 return; 587 588 LineTable < = Gen->addLineTable(); 589 // The line data extractor expects size 8 (Quad) addresses. 590 uint64_t Addr1 = 0x11223344; 591 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 592 LT.addStandardOpcode(DW_LNS_copy, {}); 593 // Show that the expected address size is unchanged, so later valid lines 594 // don't cause a problem. 595 uint64_t Addr2 = 0x1122334455667788; 596 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 597 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 598 599 generate(); 600 601 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 602 nullptr, RecordRecoverable); 603 EXPECT_THAT_ERROR(std::move(Recoverable), 604 FailedWithMessage("mismatching address size at offset " 605 "0x00000030 expected 0x08 found 0x04")); 606 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 607 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 608 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 609 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 610 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 611 } 612 613 TEST_F(DebugLineBasicFixture, 614 ErrorForMismatchedAddressSizeUnsetInitialAddress) { 615 if (!setupGenerator(4, 0)) 616 return; 617 618 LineTable < = Gen->addLineTable(); 619 uint64_t Addr1 = 0x11223344; 620 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 621 LT.addStandardOpcode(DW_LNS_copy, {}); 622 uint64_t Addr2 = 0x1122334455667788; 623 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 624 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 625 626 generate(); 627 628 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 629 nullptr, RecordRecoverable); 630 EXPECT_THAT_ERROR(std::move(Recoverable), 631 FailedWithMessage("mismatching address size at offset " 632 "0x00000038 expected 0x04 found 0x08")); 633 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 634 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 635 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 636 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 637 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 638 } 639 640 TEST_F(DebugLineBasicFixture, 641 ErrorForUnsupportedAddressSizeInSetAddressLength) { 642 // Use DWARF v4, and 0 for data extractor address size so that the address 643 // size is derived from the opcode length. 644 if (!setupGenerator(4, 0)) 645 return; 646 647 LineTable < = Gen->addLineTable(); 648 // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for 649 // the Half (2) + Byte (1) operand, representing the unsupported address size. 650 LT.addExtendedOpcode(4, DW_LNE_set_address, 651 {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}}); 652 LT.addStandardOpcode(DW_LNS_copy, {}); 653 // Special opcode to ensure the address has changed between the first and last 654 // row in the sequence. Without this, the sequence will not be recorded. 655 LT.addByte(0xaa); 656 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 657 658 generate(); 659 660 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 661 nullptr, RecordRecoverable); 662 EXPECT_THAT_ERROR( 663 std::move(Recoverable), 664 FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at " 665 "offset 0x00000030 is unsupported")); 666 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 667 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 668 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 669 // Show that the set address opcode is ignored in this case. 670 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 671 } 672 673 TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) { 674 // Use DWARF v4, and 0 for data extractor address size so that the address 675 // size is derived from the opcode length. 676 if (!setupGenerator(4, 0)) 677 return; 678 679 LineTable < = Gen->addLineTable(); 680 // Specifically use an operand size that has a trailing byte of a supported 681 // size (8), so that any potential truncation would result in a valid size. 682 std::vector<LineTable::ValueAndLength> Operands(0x108); 683 LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands); 684 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 685 686 generate(); 687 688 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 689 nullptr, RecordRecoverable); 690 EXPECT_THAT_ERROR( 691 std::move(Recoverable), 692 FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at " 693 "offset 0x00000031 is unsupported")); 694 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 695 } 696 697 TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) { 698 // Use 0 for data extractor address size so that it does not clash with the 699 // header address size. 700 if (!setupGenerator(5, 0)) 701 return; 702 703 LineTable < = Gen->addLineTable(); 704 // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode 705 // itself and 9 for the Quad (8) + Byte (1) operand representing the 706 // unsupported address size. 707 uint8_t AddressSize = 9; 708 LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address, 709 {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}}); 710 LT.addStandardOpcode(DW_LNS_copy, {}); 711 // Special opcode to ensure the address has changed between the first and last 712 // row in the sequence. Without this, the sequence will not be recorded. 713 LT.addByte(0xaa); 714 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 715 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 716 Prologue.FormParams.AddrSize = AddressSize; 717 LT.setPrologue(Prologue); 718 719 generate(); 720 721 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 722 nullptr, RecordRecoverable); 723 EXPECT_THAT_ERROR( 724 std::move(Recoverable), 725 FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at " 726 "offset 0x00000038 is unsupported")); 727 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 728 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 729 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 730 // Show that the set address opcode is ignored in this case. 731 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 732 } 733 734 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 735 if (!setupGenerator()) 736 return; 737 738 LineTable < = Gen->addLineTable(); 739 LT.addExtendedOpcode(9, DW_LNE_set_address, 740 {{0x1122334455667788, LineTable::Quad}}); 741 LT.addStandardOpcode(DW_LNS_copy, {}); 742 LT.addByte(0xaa); 743 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 744 LT.addExtendedOpcode(9, DW_LNE_set_address, 745 {{0x99aabbccddeeff00, LineTable::Quad}}); 746 LT.addStandardOpcode(DW_LNS_copy, {}); 747 LT.addByte(0xbb); 748 LT.addByte(0xcc); 749 750 generate(); 751 752 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 753 nullptr, RecordRecoverable); 754 EXPECT_THAT_ERROR(std::move(Recoverable), 755 FailedWithMessage("last sequence in debug line table at " 756 "offset 0x00000000 is not terminated")); 757 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 758 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 759 // The unterminated sequence is not added to the sequence list. 760 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 761 } 762 763 struct AdjustAddressFixtureBase : public CommonFixture { 764 virtual ~AdjustAddressFixtureBase() {} 765 766 // Create and update the prologue as specified by the subclass, then return 767 // the length of the table. 768 virtual uint64_t editPrologue(LineTable <) = 0; 769 770 virtual uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncrs, 771 uint64_t SpecialIncrs, 772 uint64_t AdvanceIncrs) { 773 return Base + ConstIncrs + SpecialIncrs + AdvanceIncrs; 774 } 775 776 virtual uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) { 777 return Base + Incr; 778 } 779 780 uint64_t setupNoProblemTable() { 781 LineTable &NoProblem = Gen->addLineTable(); 782 NoProblem.addExtendedOpcode(9, DW_LNE_set_address, 783 {{0xabcd, LineTable::Quad}}); 784 NoProblem.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 785 return editPrologue(NoProblem); 786 } 787 788 uint64_t setupConstAddPcFirstTable() { 789 LineTable &ConstAddPCFirst = Gen->addLineTable(); 790 ConstAddPCFirst.addExtendedOpcode(9, DW_LNE_set_address, 791 {{ConstAddPCAddr, LineTable::Quad}}); 792 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 793 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 794 ConstAddPCFirst.addStandardOpcode(DW_LNS_advance_pc, 795 {{0x10, LineTable::ULEB}}); 796 ConstAddPCFirst.addByte(0x21); // Special opcode, +1 op, +1 line. 797 ConstAddPCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 798 return editPrologue(ConstAddPCFirst); 799 } 800 801 uint64_t setupSpecialFirstTable() { 802 LineTable &SpecialFirst = Gen->addLineTable(); 803 SpecialFirst.addExtendedOpcode(9, DW_LNE_set_address, 804 {{SpecialAddr, LineTable::Quad}}); 805 SpecialFirst.addByte(0x22); // Special opcode, +1 op, +2 line. 806 SpecialFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 807 SpecialFirst.addStandardOpcode(DW_LNS_advance_pc, 808 {{0x20, LineTable::ULEB}}); 809 SpecialFirst.addByte(0x23); // Special opcode, +1 op, +3 line. 810 SpecialFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 811 return editPrologue(SpecialFirst); 812 } 813 814 uint64_t setupAdvancePcFirstTable() { 815 LineTable &AdvancePCFirst = Gen->addLineTable(); 816 AdvancePCFirst.addExtendedOpcode(9, DW_LNE_set_address, 817 {{AdvancePCAddr, LineTable::Quad}}); 818 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 819 {{0x30, LineTable::ULEB}}); 820 AdvancePCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 821 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 822 {{0x40, LineTable::ULEB}}); 823 AdvancePCFirst.addByte(0x24); // Special opcode, +1 op, +4 line. 824 AdvancePCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 825 return editPrologue(AdvancePCFirst); 826 } 827 828 void setupTables(bool AddAdvancePCFirstTable) { 829 LineTable &Padding = Gen->addLineTable(); 830 Padding.setCustomPrologue({{0, LineTable::Byte}}); 831 NoProblemOffset = 1; 832 833 // Show that no warning is generated for the case where no 834 // DW_LNS_const_add_pc or special opcode is used. 835 ConstAddPCOffset = setupNoProblemTable() + NoProblemOffset; 836 837 // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode 838 // and then not again. 839 SpecialOffset = setupConstAddPcFirstTable() + ConstAddPCOffset; 840 841 // Show that the warning is emitted for the first special opcode and then 842 // not again. 843 AdvancePCOffset = setupSpecialFirstTable() + SpecialOffset; 844 845 // Show that the warning is emitted for the first DW_LNS_advance_pc opcode 846 // (if requested) and then not again. 847 if (AddAdvancePCFirstTable) 848 setupAdvancePcFirstTable(); 849 } 850 851 Expected<const DWARFDebugLine::LineTable *> 852 checkTable(uint64_t Offset, StringRef OpcodeType, const Twine &MsgSuffix) { 853 auto ExpectedTable = Line.getOrParseLineTable(LineData, Offset, *Context, 854 nullptr, RecordRecoverable); 855 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 856 if (!IsErrorExpected) { 857 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 858 } else { 859 if (!ExpectedTable) 860 return ExpectedTable; 861 uint64_t ExpectedOffset = Offset + 862 (*ExpectedTable)->Prologue.getLength() + 863 11; // 11 == size of DW_LNE_set_address. 864 std::string OffsetHex = Twine::utohexstr(Offset).str(); 865 std::string OffsetZeroes = std::string(8 - OffsetHex.size(), '0'); 866 std::string ExpectedHex = Twine::utohexstr(ExpectedOffset).str(); 867 std::string ExpectedZeroes = std::string(8 - ExpectedHex.size(), '0'); 868 EXPECT_THAT_ERROR( 869 std::move(Recoverable), 870 FailedWithMessage(("line table program at offset 0x" + OffsetZeroes + 871 OffsetHex + " contains a " + OpcodeType + 872 " opcode at offset 0x" + ExpectedZeroes + 873 ExpectedHex + ", " + MsgSuffix) 874 .str())); 875 } 876 return ExpectedTable; 877 } 878 879 void runTest(bool CheckAdvancePC, Twine MsgSuffix) { 880 if (!setupGenerator(Version)) 881 return; 882 883 setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC); 884 885 generate(); 886 887 auto ExpectedNoProblem = Line.getOrParseLineTable( 888 LineData, NoProblemOffset, *Context, nullptr, RecordRecoverable); 889 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 890 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 891 ASSERT_THAT_EXPECTED(ExpectedNoProblem, Succeeded()); 892 893 auto ExpectedConstAddPC = 894 checkTable(ConstAddPCOffset, "DW_LNS_const_add_pc", MsgSuffix); 895 ASSERT_THAT_EXPECTED(ExpectedConstAddPC, Succeeded()); 896 ASSERT_EQ((*ExpectedConstAddPC)->Rows.size(), 2u); 897 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Address.Address, 898 getAdjustedAddr(ConstAddPCAddr, ConstIncr * 2, 0x1, 0x10)); 899 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Line, getAdjustedLine(1, 1)); 900 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 901 902 auto ExpectedSpecial = checkTable(SpecialOffset, "special", MsgSuffix); 903 ASSERT_THAT_EXPECTED(ExpectedSpecial, Succeeded()); 904 ASSERT_EQ((*ExpectedSpecial)->Rows.size(), 3u); 905 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Address.Address, 906 getAdjustedAddr(SpecialAddr, 0, 1, 0)); 907 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Line, getAdjustedLine(1, 2)); 908 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Address.Address, 909 getAdjustedAddr(SpecialAddr, ConstIncr, 0x2, 0x20)); 910 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Line, getAdjustedLine(1, 5)); 911 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 912 913 if (!CheckAdvancePC) 914 return; 915 916 auto ExpectedAdvancePC = 917 checkTable(AdvancePCOffset, "DW_LNS_advance_pc", MsgSuffix); 918 ASSERT_THAT_EXPECTED(ExpectedAdvancePC, Succeeded()); 919 ASSERT_EQ((*ExpectedAdvancePC)->Rows.size(), 2u); 920 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Address.Address, 921 getAdjustedAddr(AdvancePCAddr, ConstIncr, 0x1, 0x70)); 922 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Line, getAdjustedLine(1, 4)); 923 } 924 925 uint64_t ConstIncr = 0x11; 926 uint64_t ConstAddPCAddr = 0x1234; 927 uint64_t SpecialAddr = 0x5678; 928 uint64_t AdvancePCAddr = 0xabcd; 929 uint64_t NoProblemOffset; 930 uint64_t ConstAddPCOffset; 931 uint64_t SpecialOffset; 932 uint64_t AdvancePCOffset; 933 934 uint16_t Version = 4; 935 bool IsErrorExpected; 936 }; 937 938 struct MaxOpsPerInstFixture 939 : TestWithParam<std::tuple<uint16_t, uint8_t, bool>>, 940 AdjustAddressFixtureBase { 941 void SetUp() override { 942 std::tie(Version, MaxOpsPerInst, IsErrorExpected) = GetParam(); 943 } 944 945 uint64_t editPrologue(LineTable <) override { 946 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 947 Prologue.MaxOpsPerInst = MaxOpsPerInst; 948 LT.setPrologue(Prologue); 949 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 950 } 951 952 uint8_t MaxOpsPerInst; 953 }; 954 955 TEST_P(MaxOpsPerInstFixture, MaxOpsPerInstProblemsReportedCorrectly) { 956 runTest(/*CheckAdvancePC=*/true, 957 "but the prologue maximum_operations_per_instruction value is " + 958 Twine(unsigned(MaxOpsPerInst)) + 959 ", which is unsupported. Assuming a value of 1 instead"); 960 } 961 962 INSTANTIATE_TEST_CASE_P( 963 MaxOpsPerInstParams, MaxOpsPerInstFixture, 964 Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error). 965 std::make_tuple(4, 0, true), // Test zero value for V4 (error). 966 std::make_tuple(4, 1, false), // Test good value for V4 (no error). 967 std::make_tuple( 968 4, 2, true)), ); // Test one higher than permitted V4 (error). 969 970 struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>, 971 AdjustAddressFixtureBase { 972 void SetUp() override { std::tie(LineRange, IsErrorExpected) = GetParam(); } 973 974 uint64_t editPrologue(LineTable <) override { 975 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 976 Prologue.LineRange = LineRange; 977 LT.setPrologue(Prologue); 978 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 979 } 980 981 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 982 uint64_t SpecialIncr, 983 uint64_t AdvanceIncr) override { 984 if (LineRange == 0) 985 return Base + AdvanceIncr; 986 return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr, 987 SpecialIncr, AdvanceIncr); 988 } 989 990 uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override { 991 return LineRange != 0 992 ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr) 993 : Base; 994 } 995 996 uint8_t LineRange; 997 }; 998 999 TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) { 1000 runTest(/*CheckAdvancePC=*/false, 1001 "but the prologue line_range value is 0. The address and line will " 1002 "not be adjusted"); 1003 } 1004 1005 INSTANTIATE_TEST_CASE_P( 1006 LineRangeParams, LineRangeFixture, 1007 Values(std::make_tuple(0, true), // Test zero value (error). 1008 std::make_tuple(14, false)), ); // Test non-zero value (no error). 1009 1010 struct BadMinInstLenFixture : TestWithParam<std::tuple<uint8_t, bool>>, 1011 AdjustAddressFixtureBase { 1012 void SetUp() override { 1013 std::tie(MinInstLength, IsErrorExpected) = GetParam(); 1014 } 1015 1016 uint64_t editPrologue(LineTable <) override { 1017 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1018 Prologue.MinInstLength = MinInstLength; 1019 LT.setPrologue(Prologue); 1020 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1021 } 1022 1023 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 1024 uint64_t SpecialIncr, 1025 uint64_t AdvanceIncr) override { 1026 return MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( 1027 Base, ConstIncr, SpecialIncr, AdvanceIncr) 1028 : Base; 1029 } 1030 1031 uint8_t MinInstLength; 1032 }; 1033 1034 TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) { 1035 runTest(/*CheckAdvancePC=*/true, 1036 "but the prologue minimum_instruction_length value is 0, which " 1037 "prevents any address advancing"); 1038 } 1039 1040 INSTANTIATE_TEST_CASE_P( 1041 BadMinInstLenParams, BadMinInstLenFixture, 1042 Values(std::make_tuple(0, true), // Test zero value (error). 1043 std::make_tuple(1, false)), ); // Test non-zero value (no error). 1044 1045 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 1046 if (!setupGenerator()) 1047 return; 1048 1049 DWARFDebugLine::SectionParser Parser = setupParser(); 1050 1051 EXPECT_EQ(Parser.getOffset(), 0u); 1052 ASSERT_FALSE(Parser.done()); 1053 1054 DWARFDebugLine::LineTable Parsed = 1055 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1056 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 1057 EXPECT_EQ(Parsed.Sequences.size(), 1u); 1058 EXPECT_EQ(Parser.getOffset(), 62u); 1059 ASSERT_FALSE(Parser.done()); 1060 1061 DWARFDebugLine::LineTable Parsed2 = 1062 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1063 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 1064 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 1065 EXPECT_EQ(Parser.getOffset(), 136u); 1066 EXPECT_TRUE(Parser.done()); 1067 1068 EXPECT_FALSE(Recoverable); 1069 EXPECT_FALSE(Unrecoverable); 1070 } 1071 1072 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 1073 if (!setupGenerator()) 1074 return; 1075 1076 DWARFDebugLine::SectionParser Parser = setupParser(); 1077 1078 EXPECT_EQ(Parser.getOffset(), 0u); 1079 ASSERT_FALSE(Parser.done()); 1080 1081 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1082 EXPECT_EQ(Parser.getOffset(), 62u); 1083 ASSERT_FALSE(Parser.done()); 1084 1085 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1086 EXPECT_EQ(Parser.getOffset(), 136u); 1087 EXPECT_TRUE(Parser.done()); 1088 1089 EXPECT_FALSE(Recoverable); 1090 EXPECT_FALSE(Unrecoverable); 1091 } 1092 1093 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 1094 if (!setupGenerator()) 1095 return; 1096 1097 generate(); 1098 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1099 1100 EXPECT_TRUE(Parser.done()); 1101 } 1102 1103 TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) { 1104 if (!setupGenerator()) 1105 return; 1106 1107 LineTable < = Gen->addLineTable(); 1108 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1109 Gen->addLineTable(); 1110 generate(); 1111 1112 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1113 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1114 1115 EXPECT_EQ(Parser.getOffset(), 0u); 1116 EXPECT_TRUE(Parser.done()); 1117 EXPECT_FALSE(Recoverable); 1118 1119 EXPECT_THAT_ERROR( 1120 std::move(Unrecoverable), 1121 FailedWithMessage( 1122 "parsing line table prologue at offset 0x00000000: unsupported " 1123 "reserved unit length of value 0xfffffff0")); 1124 } 1125 1126 TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) { 1127 if (!setupGenerator()) 1128 return; 1129 1130 LineTable < = Gen->addLineTable(); 1131 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1132 Gen->addLineTable(); 1133 generate(); 1134 1135 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1136 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1137 1138 EXPECT_EQ(Parser.getOffset(), 0u); 1139 EXPECT_TRUE(Parser.done()); 1140 EXPECT_FALSE(Recoverable); 1141 1142 EXPECT_THAT_ERROR( 1143 std::move(Unrecoverable), 1144 FailedWithMessage( 1145 "parsing line table prologue at offset 0x00000000: unsupported " 1146 "reserved unit length of value 0xfffffff0")); 1147 } 1148 1149 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 1150 if (!setupGenerator()) 1151 return; 1152 1153 LineTable < = Gen->addLineTable(DWARF32); 1154 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1155 LineTable <2 = Gen->addLineTable(DWARF32); 1156 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1157 generate(); 1158 1159 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1160 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1161 ASSERT_FALSE(Parser.done()); 1162 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1163 1164 EXPECT_TRUE(Parser.done()); 1165 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1166 1167 EXPECT_THAT_ERROR( 1168 std::move(Unrecoverable), 1169 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1170 "unsupported version 0", 1171 "parsing line table prologue at offset 0x00000006: " 1172 "unsupported version 1")); 1173 } 1174 1175 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 1176 if (!setupGenerator()) 1177 return; 1178 1179 LineTable < = Gen->addLineTable(DWARF32); 1180 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 1181 LineTable <2 = Gen->addLineTable(DWARF32); 1182 LT2.addExtendedOpcode(9, DW_LNE_set_address, 1183 {{0x1234567890abcdef, LineTable::Quad}}); 1184 LT2.addStandardOpcode(DW_LNS_copy, {}); 1185 LT2.addByte(0xbb); 1186 generate(); 1187 1188 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1189 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1190 EXPECT_FALSE(Unrecoverable); 1191 ASSERT_FALSE(Parser.done()); 1192 EXPECT_THAT_ERROR(std::move(Recoverable), 1193 FailedWithMessage("unexpected line op length at offset " 1194 "0x00000030 expected 0x42 found 0x01")); 1195 1196 // Reset the error state so that it does not confuse the next set of checks. 1197 Unrecoverable = Error::success(); 1198 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1199 1200 EXPECT_TRUE(Parser.done()); 1201 EXPECT_THAT_ERROR(std::move(Recoverable), 1202 FailedWithMessage("last sequence in debug line table at " 1203 "offset 0x00000031 is not terminated")); 1204 EXPECT_FALSE(Unrecoverable); 1205 } 1206 1207 TEST_F(DebugLineBasicFixture, 1208 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1209 if (!setupGenerator()) 1210 return; 1211 1212 LineTable < = Gen->addLineTable(DWARF32); 1213 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1214 LineTable <2 = Gen->addLineTable(DWARF32); 1215 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1216 generate(); 1217 1218 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1219 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1220 ASSERT_FALSE(Parser.done()); 1221 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1222 1223 EXPECT_TRUE(Parser.done()); 1224 EXPECT_FALSE(Recoverable); 1225 1226 EXPECT_THAT_ERROR( 1227 std::move(Unrecoverable), 1228 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1229 "unsupported version 0", 1230 "parsing line table prologue at offset 0x00000006: " 1231 "unsupported version 1")); 1232 } 1233 1234 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 1235 if (!setupGenerator()) 1236 return; 1237 1238 LineTable < = Gen->addLineTable(DWARF32); 1239 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 1240 generate(); 1241 1242 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1243 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1244 1245 EXPECT_TRUE(Parser.done()); 1246 EXPECT_FALSE(Recoverable); 1247 EXPECT_FALSE(Unrecoverable); 1248 } 1249 1250 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) { 1251 if (!setupGenerator()) 1252 return; 1253 1254 using ValLen = dwarfgen::LineTable::ValueAndLength; 1255 LineTable < = Gen->addLineTable(DWARF32); 1256 LT.addStandardOpcode(DW_LNS_copy, {}); 1257 LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}}); 1258 LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}}); 1259 LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}}); 1260 LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}}); 1261 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 1262 LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 1263 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 1264 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}}); 1265 LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 1266 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 1267 LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}}); 1268 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 1269 generate(); 1270 1271 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 1272 std::string Output; 1273 raw_string_ostream OS(Output); 1274 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS); 1275 OS.flush(); 1276 1277 EXPECT_FALSE(Recoverable); 1278 EXPECT_FALSE(Unrecoverable); 1279 auto InOutput = [&Output](char const *Str) { 1280 return Output.find(Str) != std::string::npos; 1281 }; 1282 EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output; 1283 EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output; 1284 // FIXME: The value printed after DW_LNS_advance_line is currently the result 1285 // of the advance, but it should be the value being advanced by. See 1286 // https://bugs.llvm.org/show_bug.cgi?id=44261 for details. 1287 EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output; 1288 EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output; 1289 EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output; 1290 EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output; 1291 EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output; 1292 EXPECT_TRUE( 1293 InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n")) 1294 << Output; 1295 EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n")) 1296 << Output; 1297 EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output; 1298 EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output; 1299 EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; 1300 } 1301 1302 TEST_F(DebugLineBasicFixture, PrintPathsProperly) { 1303 if (!setupGenerator(5)) 1304 return; 1305 1306 LineTable < = Gen->addLineTable(); 1307 DWARFDebugLine::Prologue P = LT.createBasicPrologue(); 1308 P.IncludeDirectories.push_back( 1309 DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); 1310 P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); 1311 P.FileNames.back().Name = 1312 DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); 1313 P.FileNames.back().DirIdx = 1; 1314 P.PrologueLength += 14; 1315 LT.setPrologue(P); 1316 generate(); 1317 1318 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 1319 nullptr, RecordRecoverable); 1320 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 1321 std::string Result; 1322 // DWARF 5 stores the compilation directory in two places: the Compilation 1323 // Unit and the directory table entry 0, and implementations are free to use 1324 // one or the other. This copy serves as the one stored in the CU. 1325 StringRef CompDir = "a dir"; 1326 EXPECT_FALSE( 1327 (*ExpectedLineTable) 1328 ->Prologue.getFileNameByIndex( 1329 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); 1330 EXPECT_TRUE((*ExpectedLineTable) 1331 ->Prologue.getFileNameByIndex( 1332 1, CompDir, 1333 DILineInfoSpecifier::FileLineInfoKind::RawValue, Result)); 1334 EXPECT_TRUE((*ExpectedLineTable) 1335 ->Prologue.getFileNameByIndex( 1336 1, CompDir, 1337 DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly, 1338 Result)); 1339 EXPECT_STREQ(Result.c_str(), "b file"); 1340 EXPECT_TRUE((*ExpectedLineTable) 1341 ->Prologue.getFileNameByIndex( 1342 1, CompDir, 1343 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, 1344 Result)); 1345 EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file")); 1346 EXPECT_TRUE((*ExpectedLineTable) 1347 ->Prologue.getFileNameByIndex( 1348 1, CompDir, 1349 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 1350 Result)); 1351 EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file")); 1352 } 1353 1354 } // end anonymous namespace 1355