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