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