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(1), 214 FailedWithMessage( 215 "offset 0x00000001 is not a valid debug line section offset")); 216 } 217 218 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 219 if (!setupGenerator(Version)) 220 return; 221 LineTable < = Gen->addLineTable(Format); 222 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 223 LT.setPrologue(Prologue); 224 generate(); 225 226 // + 10 for sizes of DWARF-32 unit length, version, prologue length. 227 uint64_t ExpectedLength = Prologue.PrologueLength + 10; 228 if (Version == 5) 229 // Add address and segment selector size fields. 230 ExpectedLength += 2; 231 if (Format == DWARF64) 232 // Unit length grows by 8, prologue length by 4. 233 ExpectedLength += 12; 234 235 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 236 nullptr, RecordRecoverable); 237 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 238 EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 239 } 240 241 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 242 if (!setupGenerator(Version)) 243 return; 244 245 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 246 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 247 248 LineTable < = Gen->addLineTable(Format); 249 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 250 LT.addStandardOpcode(DW_LNS_copy, {}); 251 LT.addByte(0xaa); 252 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 253 254 LineTable <2 = Gen->addLineTable(Format); 255 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 256 LT2.addStandardOpcode(DW_LNS_copy, {}); 257 LT2.addByte(0xbb); 258 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 259 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 260 LT2.addStandardOpcode(DW_LNS_copy, {}); 261 LT2.addByte(0xcc); 262 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 263 264 generate(); 265 266 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 267 nullptr, RecordRecoverable); 268 ASSERT_TRUE(ExpectedLineTable.operator bool()); 269 EXPECT_FALSE(Recoverable); 270 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 271 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 272 EXPECT_EQ(Expected->Sequences.size(), 1u); 273 274 uint64_t SecondOffset = 275 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 276 Recoverable = Error::success(); 277 auto ExpectedLineTable2 = Line.getOrParseLineTable( 278 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 279 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 280 EXPECT_FALSE(Recoverable); 281 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 282 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 283 EXPECT_EQ(Expected2->Sequences.size(), 2u); 284 285 EXPECT_NE(Expected, Expected2); 286 287 // Check that if the same offset is requested, the exact same pointer is 288 // returned. 289 Recoverable = Error::success(); 290 auto ExpectedLineTable3 = Line.getOrParseLineTable( 291 LineData, 0, *Context, nullptr, RecordRecoverable); 292 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 293 EXPECT_FALSE(Recoverable); 294 EXPECT_EQ(Expected, *ExpectedLineTable3); 295 296 Recoverable = Error::success(); 297 auto ExpectedLineTable4 = Line.getOrParseLineTable( 298 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 299 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 300 EXPECT_FALSE(Recoverable); 301 EXPECT_EQ(Expected2, *ExpectedLineTable4); 302 303 // TODO: Add tests that show that the body of the programs have been read 304 // correctly. 305 } 306 307 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 308 if (!setupGenerator()) 309 return; 310 311 LineTable < = Gen->addLineTable(); 312 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 313 314 generate(); 315 316 EXPECT_THAT_EXPECTED( 317 getOrParseLineTableFatalErrors(), 318 FailedWithMessage( 319 "parsing line table prologue at offset 0x00000000 unsupported " 320 "reserved unit length found of value 0xfffffff0")); 321 } 322 323 struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>, 324 public CommonFixture { 325 void SetUp() { Version = GetParam(); } 326 327 uint16_t Version; 328 }; 329 330 TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) { 331 if (!setupGenerator()) 332 return; 333 334 LineTable < = Gen->addLineTable(); 335 LT.setCustomPrologue( 336 {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}}); 337 338 generate(); 339 340 EXPECT_THAT_EXPECTED( 341 getOrParseLineTableFatalErrors(), 342 FailedWithMessage("parsing line table prologue at offset 0x00000000 " 343 "found unsupported version " + 344 std::to_string(Version))); 345 } 346 347 INSTANTIATE_TEST_CASE_P(UnsupportedVersionTestParams, 348 DebugLineUnsupportedVersionFixture, 349 Values(/*1 below min */ 1, /* 1 above max */ 6, 350 /* Maximum possible */ 0xffff), ); 351 352 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 353 if (!setupGenerator(5)) 354 return; 355 356 LineTable < = Gen->addLineTable(); 357 LT.setCustomPrologue({ 358 {19, LineTable::Long}, // unit length 359 {5, LineTable::Half}, // version 360 {8, LineTable::Byte}, // addr size 361 {0, LineTable::Byte}, // segment selector size 362 {11, LineTable::Long}, // prologue length 363 {1, LineTable::Byte}, // min instruction length 364 {1, LineTable::Byte}, // max ops per instruction 365 {1, LineTable::Byte}, // default is_stmt 366 {0, LineTable::Byte}, // line base 367 {14, LineTable::Byte}, // line range 368 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 369 // setup required). 370 {0, LineTable::Byte}, // standard opcode lengths 371 {0, LineTable::Byte}, // directory entry format count (should not be 372 // zero). 373 {0, LineTable::ULEB}, // directories count 374 {0, LineTable::Byte}, // file name entry format count 375 {0, LineTable::ULEB} // file name entry count 376 }); 377 378 generate(); 379 380 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 381 nullptr, RecordRecoverable); 382 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 383 384 EXPECT_THAT_ERROR( 385 std::move(Recoverable), 386 FailedWithMessage( 387 "parsing line table prologue at 0x00000000 found an invalid " 388 "directory or file table description at 0x00000014", 389 "failed to parse entry content descriptions because no path was " 390 "found")); 391 } 392 393 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 394 if (!setupGenerator(Version)) 395 return; 396 397 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 398 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 399 400 LineTable < = Gen->addLineTable(Format); 401 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 402 ++Prologue.PrologueLength; 403 LT.setPrologue(Prologue); 404 405 generate(); 406 407 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 408 nullptr, RecordRecoverable); 409 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 410 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 411 // Undo the earlier modification so that it can be compared against a 412 // "default" prologue. 413 --Result.Prologue.PrologueLength; 414 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 415 416 uint64_t ExpectedEnd = 417 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 418 EXPECT_THAT_ERROR( 419 std::move(Recoverable), 420 FailedWithMessage(("parsing line table prologue at 0x00000000 should " 421 "have ended at 0x000000" + 422 Twine::utohexstr(ExpectedEnd) + 423 " but it ended at 0x000000" + 424 Twine::utohexstr(ExpectedEnd - 1)) 425 .str())); 426 } 427 428 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 429 if (!setupGenerator(Version)) 430 return; 431 432 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 433 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 434 435 LineTable < = Gen->addLineTable(Format); 436 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 437 Prologue.PrologueLength -= 2; 438 LT.setPrologue(Prologue); 439 440 generate(); 441 442 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 443 nullptr, RecordRecoverable); 444 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 445 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 446 // Undo the earlier modification so that it can be compared against a 447 // "default" prologue. 448 Result.Prologue.PrologueLength += 2; 449 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 450 451 uint64_t ExpectedEnd = 452 Prologue.TotalLength - 2 + Prologue.sizeofTotalLength(); 453 std::vector<std::string> Errs; 454 // Parsing of a DWARFv2-4 file table stops at the end of an entry once the 455 // prologue end has been reached, whether or not the trailing null terminator 456 // has been found. As such, the expected error message will be slightly 457 // different. 458 uint64_t ActualEnd = Version == 5 ? ExpectedEnd + 2 : ExpectedEnd + 1; 459 if (Version != 5) { 460 Errs.emplace_back( 461 (Twine("parsing line table prologue at 0x00000000 found an invalid " 462 "directory or file table description at 0x000000") + 463 Twine::utohexstr(ActualEnd)) 464 .str()); 465 Errs.emplace_back("file names table was not null terminated before the end " 466 "of the prologue"); 467 } 468 Errs.emplace_back( 469 (Twine("parsing line table prologue at 0x00000000 should have ended at " 470 "0x000000") + 471 Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 472 Twine::utohexstr(ActualEnd)) 473 .str()); 474 EXPECT_THAT_ERROR(std::move(Recoverable), 475 FailedWithMessageArray(testing::ElementsAreArray(Errs))); 476 } 477 478 INSTANTIATE_TEST_CASE_P( 479 LineTableTestParams, DebugLineParameterisedFixture, 480 Values(std::make_pair( 481 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 482 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 483 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 484 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 485 486 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 487 if (!setupGenerator()) 488 return; 489 490 LineTable < = Gen->addLineTable(); 491 LT.addByte(0xaa); 492 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 493 // The operand will be read for both the discriminator opcode and then parsed 494 // again as DW_LNS_negate_stmt, to respect the claimed length. 495 LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 496 {{DW_LNS_negate_stmt, LineTable::ULEB}}); 497 LT.addByte(0xbb); 498 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 499 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 500 501 generate(); 502 503 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 504 nullptr, RecordRecoverable); 505 EXPECT_THAT_ERROR(std::move(Recoverable), 506 FailedWithMessage("unexpected line op length at offset " 507 "0x00000031 expected 0x01 found 0x02")); 508 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 509 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 510 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 511 EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 512 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 513 } 514 515 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 516 if (!setupGenerator()) 517 return; 518 519 LineTable < = Gen->addLineTable(); 520 LT.addByte(0xaa); 521 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 522 // The Length should be 1 for an end sequence opcode. 523 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 524 // The negate statement opcode will be skipped. 525 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 526 LT.addByte(0xbb); 527 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 528 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 529 530 generate(); 531 532 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 533 nullptr, RecordRecoverable); 534 EXPECT_THAT_ERROR(std::move(Recoverable), 535 FailedWithMessage("unexpected line op length at offset " 536 "0x00000032 expected 0x02 found 0x01")); 537 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 538 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 539 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 540 ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 541 EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 542 } 543 544 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 545 if (!setupGenerator()) 546 return; 547 548 LineTable &Padding = Gen->addLineTable(); 549 // Add some padding to show that a non-zero offset is handled correctly. 550 Padding.setCustomPrologue({{0, LineTable::Byte}}); 551 LineTable < = Gen->addLineTable(); 552 LT.addStandardOpcode(DW_LNS_copy, {}); 553 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 554 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 555 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 556 // Set the total length to 1 higher than the actual length. 557 ++Prologue.TotalLength; 558 LT.setPrologue(Prologue); 559 560 generate(); 561 562 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 563 nullptr, RecordRecoverable); 564 EXPECT_THAT_ERROR( 565 std::move(Recoverable), 566 FailedWithMessage("line table program with offset 0x00000001 has length " 567 "0x00000034 but only 0x00000033 bytes are available")); 568 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 569 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 570 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 571 } 572 573 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 574 if (!setupGenerator(4, 8)) 575 return; 576 577 LineTable < = Gen->addLineTable(); 578 // The line data extractor expects size 8 (Quad) addresses. 579 uint64_t Addr1 = 0x11223344; 580 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 581 LT.addStandardOpcode(DW_LNS_copy, {}); 582 // Show that the expected address size is unchanged, so later valid lines 583 // don't cause a problem. 584 uint64_t Addr2 = 0x1122334455667788; 585 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 586 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 587 588 generate(); 589 590 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 591 nullptr, RecordRecoverable); 592 EXPECT_THAT_ERROR(std::move(Recoverable), 593 FailedWithMessage("mismatching address size at offset " 594 "0x00000030 expected 0x08 found 0x04")); 595 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 596 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 597 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 598 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 599 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 600 } 601 602 TEST_F(DebugLineBasicFixture, 603 ErrorForMismatchedAddressSizeUnsetInitialAddress) { 604 if (!setupGenerator(4, 0)) 605 return; 606 607 LineTable < = Gen->addLineTable(); 608 uint64_t Addr1 = 0x11223344; 609 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 610 LT.addStandardOpcode(DW_LNS_copy, {}); 611 uint64_t Addr2 = 0x1122334455667788; 612 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 613 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 614 615 generate(); 616 617 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 618 nullptr, RecordRecoverable); 619 EXPECT_THAT_ERROR(std::move(Recoverable), 620 FailedWithMessage("mismatching address size at offset " 621 "0x00000038 expected 0x04 found 0x08")); 622 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 623 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 624 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 625 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 626 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 627 } 628 629 TEST_F(DebugLineBasicFixture, 630 ErrorForUnsupportedAddressSizeInSetAddressLength) { 631 // Use DWARF v4, and 0 for data extractor address size so that the address 632 // size is derived from the opcode length. 633 if (!setupGenerator(4, 0)) 634 return; 635 636 LineTable < = Gen->addLineTable(); 637 // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for 638 // the Half (2) + Byte (1) operand, representing the unsupported address size. 639 LT.addExtendedOpcode(4, DW_LNE_set_address, 640 {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}}); 641 LT.addStandardOpcode(DW_LNS_copy, {}); 642 // Special opcode to ensure the address has changed between the first and last 643 // row in the sequence. Without this, the sequence will not be recorded. 644 LT.addByte(0xaa); 645 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 646 647 generate(); 648 649 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 650 nullptr, RecordRecoverable); 651 EXPECT_THAT_ERROR( 652 std::move(Recoverable), 653 FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at " 654 "offset 0x00000030 is unsupported")); 655 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 656 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 657 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 658 // Show that the set address opcode is ignored in this case. 659 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 660 } 661 662 TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) { 663 // Use DWARF v4, and 0 for data extractor address size so that the address 664 // size is derived from the opcode length. 665 if (!setupGenerator(4, 0)) 666 return; 667 668 LineTable < = Gen->addLineTable(); 669 // Specifically use an operand size that has a trailing byte of a supported 670 // size (8), so that any potential truncation would result in a valid size. 671 std::vector<LineTable::ValueAndLength> Operands(0x108); 672 LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands); 673 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 674 675 generate(); 676 677 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 678 nullptr, RecordRecoverable); 679 EXPECT_THAT_ERROR( 680 std::move(Recoverable), 681 FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at " 682 "offset 0x00000031 is unsupported")); 683 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 684 } 685 686 TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) { 687 // Use 0 for data extractor address size so that it does not clash with the 688 // header address size. 689 if (!setupGenerator(5, 0)) 690 return; 691 692 LineTable < = Gen->addLineTable(); 693 // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode 694 // itself and 9 for the Quad (8) + Byte (1) operand representing the 695 // unsupported address size. 696 uint8_t AddressSize = 9; 697 LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address, 698 {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}}); 699 LT.addStandardOpcode(DW_LNS_copy, {}); 700 // Special opcode to ensure the address has changed between the first and last 701 // row in the sequence. Without this, the sequence will not be recorded. 702 LT.addByte(0xaa); 703 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 704 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 705 Prologue.FormParams.AddrSize = AddressSize; 706 LT.setPrologue(Prologue); 707 708 generate(); 709 710 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 711 nullptr, RecordRecoverable); 712 EXPECT_THAT_ERROR( 713 std::move(Recoverable), 714 FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at " 715 "offset 0x00000038 is unsupported")); 716 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 717 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 718 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 719 // Show that the set address opcode is ignored in this case. 720 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 721 } 722 723 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 724 if (!setupGenerator()) 725 return; 726 727 LineTable < = Gen->addLineTable(); 728 LT.addExtendedOpcode(9, DW_LNE_set_address, 729 {{0x1122334455667788, LineTable::Quad}}); 730 LT.addStandardOpcode(DW_LNS_copy, {}); 731 LT.addByte(0xaa); 732 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 733 LT.addExtendedOpcode(9, DW_LNE_set_address, 734 {{0x99aabbccddeeff00, LineTable::Quad}}); 735 LT.addStandardOpcode(DW_LNS_copy, {}); 736 LT.addByte(0xbb); 737 LT.addByte(0xcc); 738 739 generate(); 740 741 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 742 nullptr, RecordRecoverable); 743 EXPECT_THAT_ERROR(std::move(Recoverable), 744 FailedWithMessage("last sequence in debug line table at " 745 "offset 0x00000000 is not terminated")); 746 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 747 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 748 // The unterminated sequence is not added to the sequence list. 749 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 750 } 751 752 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 753 if (!setupGenerator()) 754 return; 755 756 DWARFDebugLine::SectionParser Parser = setupParser(); 757 758 EXPECT_EQ(Parser.getOffset(), 0u); 759 ASSERT_FALSE(Parser.done()); 760 761 DWARFDebugLine::LineTable Parsed = 762 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 763 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 764 EXPECT_EQ(Parsed.Sequences.size(), 1u); 765 EXPECT_EQ(Parser.getOffset(), 62u); 766 ASSERT_FALSE(Parser.done()); 767 768 DWARFDebugLine::LineTable Parsed2 = 769 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 770 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 771 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 772 EXPECT_EQ(Parser.getOffset(), 136u); 773 EXPECT_TRUE(Parser.done()); 774 775 EXPECT_FALSE(Recoverable); 776 EXPECT_FALSE(Unrecoverable); 777 } 778 779 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 780 if (!setupGenerator()) 781 return; 782 783 DWARFDebugLine::SectionParser Parser = setupParser(); 784 785 EXPECT_EQ(Parser.getOffset(), 0u); 786 ASSERT_FALSE(Parser.done()); 787 788 Parser.skip(RecordRecoverable, RecordUnrecoverable); 789 EXPECT_EQ(Parser.getOffset(), 62u); 790 ASSERT_FALSE(Parser.done()); 791 792 Parser.skip(RecordRecoverable, RecordUnrecoverable); 793 EXPECT_EQ(Parser.getOffset(), 136u); 794 EXPECT_TRUE(Parser.done()); 795 796 EXPECT_FALSE(Recoverable); 797 EXPECT_FALSE(Unrecoverable); 798 } 799 800 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 801 if (!setupGenerator()) 802 return; 803 804 generate(); 805 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 806 807 EXPECT_TRUE(Parser.done()); 808 } 809 810 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { 811 if (!setupGenerator()) 812 return; 813 814 LineTable < = Gen->addLineTable(); 815 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 816 Gen->addLineTable(); 817 generate(); 818 819 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 820 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 821 822 EXPECT_EQ(Parser.getOffset(), 4u); 823 EXPECT_TRUE(Parser.done()); 824 EXPECT_FALSE(Recoverable); 825 826 EXPECT_THAT_ERROR( 827 std::move(Unrecoverable), 828 FailedWithMessage( 829 "parsing line table prologue at offset 0x00000000 unsupported " 830 "reserved unit length found of value 0xfffffff0")); 831 } 832 833 TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { 834 if (!setupGenerator()) 835 return; 836 837 LineTable < = Gen->addLineTable(); 838 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 839 Gen->addLineTable(); 840 generate(); 841 842 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 843 Parser.skip(RecordRecoverable, RecordUnrecoverable); 844 845 EXPECT_EQ(Parser.getOffset(), 4u); 846 EXPECT_TRUE(Parser.done()); 847 EXPECT_FALSE(Recoverable); 848 849 EXPECT_THAT_ERROR( 850 std::move(Unrecoverable), 851 FailedWithMessage( 852 "parsing line table prologue at offset 0x00000000 unsupported " 853 "reserved unit length found of value 0xfffffff0")); 854 } 855 856 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 857 if (!setupGenerator()) 858 return; 859 860 LineTable < = Gen->addLineTable(DWARF32); 861 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 862 LineTable <2 = Gen->addLineTable(DWARF32); 863 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 864 generate(); 865 866 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 867 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 868 ASSERT_FALSE(Parser.done()); 869 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 870 871 EXPECT_TRUE(Parser.done()); 872 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 873 874 EXPECT_THAT_ERROR( 875 std::move(Unrecoverable), 876 FailedWithMessage("parsing line table prologue at offset 0x00000000 " 877 "found unsupported version 0", 878 "parsing line table prologue at offset 0x00000006 " 879 "found unsupported version 1")); 880 } 881 882 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 883 if (!setupGenerator()) 884 return; 885 886 LineTable < = Gen->addLineTable(DWARF32); 887 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 888 LineTable <2 = Gen->addLineTable(DWARF32); 889 LT2.addExtendedOpcode(9, DW_LNE_set_address, 890 {{0x1234567890abcdef, LineTable::Quad}}); 891 LT2.addStandardOpcode(DW_LNS_copy, {}); 892 LT2.addByte(0xbb); 893 generate(); 894 895 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 896 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 897 EXPECT_FALSE(Unrecoverable); 898 ASSERT_FALSE(Parser.done()); 899 EXPECT_THAT_ERROR(std::move(Recoverable), 900 FailedWithMessage("unexpected line op length at offset " 901 "0x00000030 expected 0x42 found 0x01")); 902 903 // Reset the error state so that it does not confuse the next set of checks. 904 Unrecoverable = Error::success(); 905 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 906 907 EXPECT_TRUE(Parser.done()); 908 EXPECT_THAT_ERROR(std::move(Recoverable), 909 FailedWithMessage("last sequence in debug line table at " 910 "offset 0x00000031 is not terminated")); 911 EXPECT_FALSE(Unrecoverable); 912 } 913 914 TEST_F(DebugLineBasicFixture, 915 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 916 if (!setupGenerator()) 917 return; 918 919 LineTable < = Gen->addLineTable(DWARF32); 920 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 921 LineTable <2 = Gen->addLineTable(DWARF32); 922 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 923 generate(); 924 925 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 926 Parser.skip(RecordRecoverable, RecordUnrecoverable); 927 ASSERT_FALSE(Parser.done()); 928 Parser.skip(RecordRecoverable, RecordUnrecoverable); 929 930 EXPECT_TRUE(Parser.done()); 931 EXPECT_FALSE(Recoverable); 932 933 EXPECT_THAT_ERROR( 934 std::move(Unrecoverable), 935 FailedWithMessage("parsing line table prologue at offset 0x00000000 " 936 "found unsupported version 0", 937 "parsing line table prologue at offset 0x00000006 " 938 "found unsupported version 1")); 939 } 940 941 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 942 if (!setupGenerator()) 943 return; 944 945 LineTable < = Gen->addLineTable(DWARF32); 946 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 947 generate(); 948 949 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 950 Parser.skip(RecordRecoverable, RecordUnrecoverable); 951 952 EXPECT_TRUE(Parser.done()); 953 EXPECT_FALSE(Recoverable); 954 EXPECT_FALSE(Unrecoverable); 955 } 956 957 TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) { 958 if (!setupGenerator()) 959 return; 960 961 using ValLen = dwarfgen::LineTable::ValueAndLength; 962 LineTable < = Gen->addLineTable(DWARF32); 963 LT.addStandardOpcode(DW_LNS_copy, {}); 964 LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}}); 965 LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}}); 966 LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}}); 967 LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}}); 968 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 969 LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 970 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 971 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}}); 972 LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 973 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 974 LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}}); 975 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 976 generate(); 977 978 DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 979 std::string Output; 980 raw_string_ostream OS(Output); 981 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS); 982 OS.flush(); 983 984 EXPECT_FALSE(Recoverable); 985 EXPECT_FALSE(Unrecoverable); 986 auto InOutput = [&Output](char const *Str) { 987 return Output.find(Str) != std::string::npos; 988 }; 989 EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output; 990 EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output; 991 // FIXME: The value printed after DW_LNS_advance_line is currently the result 992 // of the advance, but it should be the value being advanced by. See 993 // https://bugs.llvm.org/show_bug.cgi?id=44261 for details. 994 EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output; 995 EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output; 996 EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output; 997 EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output; 998 EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output; 999 EXPECT_TRUE( 1000 InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n")) 1001 << Output; 1002 EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n")) 1003 << Output; 1004 EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output; 1005 EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output; 1006 EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; 1007 } 1008 1009 TEST_F(DebugLineBasicFixture, PrintPathsProperly) { 1010 if (!setupGenerator(5)) 1011 return; 1012 1013 LineTable < = Gen->addLineTable(); 1014 DWARFDebugLine::Prologue P = LT.createBasicPrologue(); 1015 P.IncludeDirectories.push_back( 1016 DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); 1017 P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); 1018 P.FileNames.back().Name = 1019 DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); 1020 P.FileNames.back().DirIdx = 1; 1021 P.PrologueLength += 14; 1022 LT.setPrologue(P); 1023 generate(); 1024 1025 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 1026 nullptr, RecordRecoverable); 1027 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 1028 std::string Result; 1029 // DWARF 5 stores the compilation directory in two places: the Compilation 1030 // Unit and the directory table entry 0, and implementations are free to use 1031 // one or the other. This copy serves as the one stored in the CU. 1032 StringRef CompDir = "a dir"; 1033 EXPECT_FALSE( 1034 (*ExpectedLineTable) 1035 ->Prologue.getFileNameByIndex( 1036 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); 1037 EXPECT_TRUE((*ExpectedLineTable) 1038 ->Prologue.getFileNameByIndex( 1039 1, CompDir, 1040 DILineInfoSpecifier::FileLineInfoKind::Default, Result)); 1041 EXPECT_STREQ(Result.c_str(), "b file"); 1042 EXPECT_TRUE((*ExpectedLineTable) 1043 ->Prologue.getFileNameByIndex( 1044 1, CompDir, 1045 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, 1046 Result)); 1047 EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file")); 1048 EXPECT_TRUE((*ExpectedLineTable) 1049 ->Prologue.getFileNameByIndex( 1050 1, CompDir, 1051 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 1052 Result)); 1053 EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file")); 1054 } 1055 1056 } // end anonymous namespace 1057