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