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