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, Units); 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> Units; 118 }; 119 120 // Fixtures must derive from "Test", but parameterised fixtures from 121 // "TestWithParam". It does not seem possible to inherit from both, so we share 122 // the common state in a separate class, inherited by the two fixture classes. 123 struct DebugLineBasicFixture : public Test, public CommonFixture {}; 124 125 struct DebugLineParameterisedFixture 126 : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 127 public CommonFixture { 128 void SetUp() override { std::tie(Version, Format) = GetParam(); } 129 130 uint16_t Version; 131 DwarfFormat Format; 132 }; 133 134 void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 135 DWARFDebugLine::Prologue Prologue, 136 uint64_t BodyLength) { 137 // Check version specific fields and values. 138 uint64_t UnitLength; 139 uint64_t PrologueLength; 140 switch (Version) { 141 case 4: 142 PrologueLength = 36; 143 UnitLength = PrologueLength + 2; 144 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 145 break; 146 case 2: 147 case 3: 148 PrologueLength = 35; 149 UnitLength = PrologueLength + 2; 150 break; 151 case 5: 152 PrologueLength = 42; 153 UnitLength = PrologueLength + 4; 154 EXPECT_EQ(Prologue.getAddressSize(), 8u); 155 EXPECT_EQ(Prologue.SegSelectorSize, 0u); 156 break; 157 default: 158 llvm_unreachable("unsupported DWARF version"); 159 } 160 UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 161 162 EXPECT_EQ(Prologue.TotalLength, UnitLength); 163 EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 164 EXPECT_EQ(Prologue.MinInstLength, 1u); 165 EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 166 EXPECT_EQ(Prologue.LineBase, -5); 167 EXPECT_EQ(Prologue.LineRange, 14u); 168 EXPECT_EQ(Prologue.OpcodeBase, 13u); 169 std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 170 EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 171 ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 172 ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 173 EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 174 ASSERT_EQ(Prologue.FileNames.size(), 1u); 175 ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 176 ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u); 177 EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 178 } 179 180 #ifdef _AIX 181 TEST_F(DebugLineBasicFixture, DISABLED_GetOrParseLineTableAtInvalidOffset) { 182 #else 183 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 184 #endif 185 if (!setupGenerator()) 186 return; 187 generate(); 188 189 EXPECT_THAT_EXPECTED( 190 getOrParseLineTableFatalErrors(0), 191 FailedWithMessage( 192 "offset 0x00000000 is not a valid debug line section offset")); 193 // Repeat to show that an error is reported each time. 194 EXPECT_THAT_EXPECTED( 195 getOrParseLineTableFatalErrors(0), 196 FailedWithMessage( 197 "offset 0x00000000 is not a valid debug line section offset")); 198 199 // Show that an error is reported for later offsets too. 200 EXPECT_THAT_EXPECTED( 201 getOrParseLineTableFatalErrors(1), 202 FailedWithMessage( 203 "offset 0x00000001 is not a valid debug line section offset")); 204 } 205 206 #ifdef _AIX 207 TEST_F(DebugLineBasicFixture, 208 DISABLED_GetOrParseLineTableAtInvalidOffsetAfterData) { 209 #else 210 TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 211 #endif 212 if (!setupGenerator()) 213 return; 214 215 LineTable < = Gen->addLineTable(); 216 LT.setCustomPrologue({{0, LineTable::Byte}}); 217 218 generate(); 219 220 EXPECT_THAT_EXPECTED( 221 getOrParseLineTableFatalErrors(0), 222 FailedWithMessage( 223 "parsing line table prologue at offset 0x00000000: " 224 "unexpected end of data at offset 0x1 while reading [0x0, 0x4)")); 225 226 EXPECT_THAT_EXPECTED( 227 getOrParseLineTableFatalErrors(1), 228 FailedWithMessage( 229 "offset 0x00000001 is not a valid debug line section offset")); 230 } 231 232 #ifdef _AIX 233 TEST_P(DebugLineParameterisedFixture, DISABLED_PrologueGetLength) { 234 #else 235 TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 236 #endif 237 if (!setupGenerator(Version)) 238 return; 239 LineTable < = Gen->addLineTable(Format); 240 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 241 LT.setPrologue(Prologue); 242 generate(); 243 244 // + 10 for sizes of DWARF-32 unit length, version, prologue length. 245 uint64_t ExpectedLength = Prologue.PrologueLength + 10; 246 if (Version == 5) 247 // Add address and segment selector size fields. 248 ExpectedLength += 2; 249 if (Format == DWARF64) 250 // Unit length grows by 8, prologue length by 4. 251 ExpectedLength += 12; 252 253 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 254 nullptr, RecordRecoverable); 255 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 256 EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 257 } 258 259 #ifdef _AIX 260 TEST_P(DebugLineParameterisedFixture, DISABLED_GetOrParseLineTableValidTable) { 261 #else 262 TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 263 #endif 264 if (!setupGenerator(Version)) 265 return; 266 267 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 268 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 269 270 LineTable < = Gen->addLineTable(Format); 271 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 272 LT.addStandardOpcode(DW_LNS_copy, {}); 273 LT.addByte(0xaa); 274 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 275 276 LineTable <2 = Gen->addLineTable(Format); 277 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 278 LT2.addStandardOpcode(DW_LNS_copy, {}); 279 LT2.addByte(0xbb); 280 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 281 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 282 LT2.addStandardOpcode(DW_LNS_copy, {}); 283 LT2.addByte(0xcc); 284 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 285 286 generate(); 287 288 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 289 nullptr, RecordRecoverable); 290 ASSERT_TRUE(ExpectedLineTable.operator bool()); 291 EXPECT_FALSE(Recoverable); 292 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 293 checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 294 EXPECT_EQ(Expected->Sequences.size(), 1u); 295 296 uint64_t SecondOffset = 297 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 298 Recoverable = Error::success(); 299 auto ExpectedLineTable2 = Line.getOrParseLineTable( 300 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 301 ASSERT_TRUE(ExpectedLineTable2.operator bool()); 302 EXPECT_FALSE(Recoverable); 303 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 304 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 305 EXPECT_EQ(Expected2->Sequences.size(), 2u); 306 307 EXPECT_NE(Expected, Expected2); 308 309 // Check that if the same offset is requested, the exact same pointer is 310 // returned. 311 Recoverable = Error::success(); 312 auto ExpectedLineTable3 = Line.getOrParseLineTable( 313 LineData, 0, *Context, nullptr, RecordRecoverable); 314 ASSERT_TRUE(ExpectedLineTable3.operator bool()); 315 EXPECT_FALSE(Recoverable); 316 EXPECT_EQ(Expected, *ExpectedLineTable3); 317 318 Recoverable = Error::success(); 319 auto ExpectedLineTable4 = Line.getOrParseLineTable( 320 LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 321 ASSERT_TRUE(ExpectedLineTable4.operator bool()); 322 EXPECT_FALSE(Recoverable); 323 EXPECT_EQ(Expected2, *ExpectedLineTable4); 324 325 // TODO: Add tests that show that the body of the programs have been read 326 // correctly. 327 } 328 329 #ifdef _AIX 330 TEST_F(DebugLineBasicFixture, DISABLED_ErrorForReservedLength) { 331 #else 332 TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 333 #endif 334 if (!setupGenerator()) 335 return; 336 337 LineTable < = Gen->addLineTable(); 338 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 339 340 generate(); 341 342 EXPECT_THAT_EXPECTED( 343 getOrParseLineTableFatalErrors(), 344 FailedWithMessage( 345 "parsing line table prologue at offset 0x00000000: unsupported " 346 "reserved unit length of value 0xfffffff0")); 347 } 348 349 struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>, 350 public CommonFixture { 351 void SetUp() override { Version = GetParam(); } 352 353 uint16_t Version; 354 }; 355 356 #ifdef _AIX 357 TEST_P(DebugLineUnsupportedVersionFixture, 358 DISABLED_ErrorForUnsupportedVersion) { 359 #else 360 TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) { 361 #endif 362 if (!setupGenerator()) 363 return; 364 365 LineTable < = Gen->addLineTable(); 366 LT.setCustomPrologue( 367 {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}}); 368 369 generate(); 370 371 EXPECT_THAT_EXPECTED( 372 getOrParseLineTableFatalErrors(), 373 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 374 "unsupported version " + 375 std::to_string(Version))); 376 } 377 378 INSTANTIATE_TEST_SUITE_P(UnsupportedVersionTestParams, 379 DebugLineUnsupportedVersionFixture, 380 Values(/*1 below min */ 1, /* 1 above max */ 6, 381 /* Maximum possible */ 0xffff)); 382 383 #ifdef _AIX 384 TEST_F(DebugLineBasicFixture, DISABLED_ErrorForInvalidV5IncludeDirTable) { 385 #else 386 TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 387 #endif 388 if (!setupGenerator(5)) 389 return; 390 391 LineTable < = Gen->addLineTable(); 392 LT.setCustomPrologue({ 393 {19, LineTable::Long}, // unit length 394 {5, LineTable::Half}, // version 395 {8, LineTable::Byte}, // addr size 396 {0, LineTable::Byte}, // segment selector size 397 {11, LineTable::Long}, // prologue length 398 {1, LineTable::Byte}, // min instruction length 399 {1, LineTable::Byte}, // max ops per instruction 400 {1, LineTable::Byte}, // default is_stmt 401 {0, LineTable::Byte}, // line base 402 {14, LineTable::Byte}, // line range 403 {2, LineTable::Byte}, // opcode base (small to reduce the amount of 404 // setup required). 405 {0, LineTable::Byte}, // standard opcode lengths 406 {0, LineTable::Byte}, // directory entry format count (should not be 407 // zero). 408 {0, LineTable::ULEB}, // directories count 409 {0, LineTable::Byte}, // file name entry format count 410 {0, LineTable::ULEB} // file name entry count 411 }); 412 413 generate(); 414 415 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 416 nullptr, RecordRecoverable); 417 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 418 419 EXPECT_THAT_ERROR( 420 std::move(Recoverable), 421 FailedWithMessage( 422 "parsing line table prologue at 0x00000000 found an invalid " 423 "directory or file table description at 0x00000014", 424 "failed to parse entry content descriptions because no path was " 425 "found")); 426 } 427 428 #ifdef _AIX 429 TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooLargePrologueLength) { 430 #else 431 TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 432 #endif 433 if (!setupGenerator(Version)) 434 return; 435 436 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 437 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 438 439 LineTable < = Gen->addLineTable(Format); 440 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 441 ++Prologue.PrologueLength; 442 LT.setPrologue(Prologue); 443 444 generate(); 445 446 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 447 nullptr, RecordRecoverable); 448 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 449 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 450 // Undo the earlier modification so that it can be compared against a 451 // "default" prologue. 452 --Result.Prologue.PrologueLength; 453 checkDefaultPrologue(Version, Format, Result.Prologue, 0); 454 455 uint64_t ExpectedEnd = 456 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 457 EXPECT_THAT_ERROR( 458 std::move(Recoverable), 459 FailedWithMessage( 460 ("unknown data in line table prologue at offset 0x00000000: " 461 "parsing ended (at offset 0x000000" + 462 Twine::utohexstr(ExpectedEnd - 1) + 463 ") before reaching the prologue end at offset 0x000000" + 464 Twine::utohexstr(ExpectedEnd)) 465 .str())); 466 } 467 468 #ifdef _AIX 469 TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooShortPrologueLength) { 470 #else 471 TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 472 #endif 473 if (!setupGenerator(Version)) 474 return; 475 476 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 477 (Format == DWARF64 ? "DWARF64" : "DWARF32")); 478 479 LineTable < = Gen->addLineTable(Format); 480 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 481 Prologue.PrologueLength -= 2; 482 LT.setPrologue(Prologue); 483 484 generate(); 485 486 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 487 nullptr, RecordRecoverable); 488 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 489 DWARFDebugLine::LineTable Result(**ExpectedLineTable); 490 491 // Parsing will stop before reading a complete file entry. 492 ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); 493 EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); 494 EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); 495 496 // The exact place where the parsing will stop depends on the structure of the 497 // prologue and the last complete field we are able to read. Before V5 we stop 498 // before reading the file length. In V5, we stop before the filename. 499 uint64_t ExpectedEnd = Prologue.TotalLength + Prologue.sizeofTotalLength() - 500 (Version < 5 ? 2 : 8); 501 std::vector<std::string> Errs; 502 Errs.emplace_back( 503 (Twine("parsing line table prologue at 0x00000000 found an invalid " 504 "directory or file table description at 0x000000") + 505 Twine::utohexstr(ExpectedEnd)) 506 .str()); 507 if (Version < 5) { 508 Errs.emplace_back("file names table was not null terminated before the end " 509 "of the prologue"); 510 } else { 511 Errs.emplace_back( 512 "failed to parse file entry because extracting the form value failed"); 513 } 514 EXPECT_THAT_ERROR(std::move(Recoverable), 515 FailedWithMessageArray(testing::ElementsAreArray(Errs))); 516 } 517 518 INSTANTIATE_TEST_SUITE_P( 519 LineTableTestParams, DebugLineParameterisedFixture, 520 Values(std::make_pair( 521 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 522 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 523 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 524 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64))); 525 526 #ifdef _AIX 527 TEST_F(DebugLineBasicFixture, 528 DISABLED_ErrorForExtendedOpcodeLengthSmallerThanExpected) { 529 #else 530 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 531 #endif 532 if (!setupGenerator()) 533 return; 534 535 LineTable < = Gen->addLineTable(); 536 LT.addByte(0xaa); 537 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 538 // The operand will be read for both the discriminator opcode and then parsed 539 // again as DW_LNS_negate_stmt, to respect the claimed length. 540 LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 541 {{DW_LNS_negate_stmt, LineTable::ULEB}}); 542 LT.addByte(0xbb); 543 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 544 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 545 546 generate(); 547 548 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 549 nullptr, RecordRecoverable); 550 EXPECT_THAT_ERROR(std::move(Recoverable), 551 FailedWithMessage("unexpected line op length at offset " 552 "0x00000031 expected 0x01 found 0x02")); 553 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 554 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 555 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 556 EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 557 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 558 } 559 560 #ifdef _AIX 561 TEST_F(DebugLineBasicFixture, 562 DISABLED_ErrorForExtendedOpcodeLengthLargerThanExpected) { 563 #else 564 TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 565 #endif 566 if (!setupGenerator()) 567 return; 568 569 LineTable < = Gen->addLineTable(); 570 LT.addByte(0xaa); 571 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 572 // The Length should be 1 for an end sequence opcode. 573 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 574 // The negate statement opcode will be skipped. 575 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 576 LT.addByte(0xbb); 577 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 578 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 579 580 generate(); 581 582 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 583 nullptr, RecordRecoverable); 584 EXPECT_THAT_ERROR(std::move(Recoverable), 585 FailedWithMessage("unexpected line op length at offset " 586 "0x00000032 expected 0x02 found 0x01")); 587 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 588 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 589 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 590 ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 591 EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 592 } 593 594 #ifdef _AIX 595 TEST_F(DebugLineBasicFixture, DISABLED_ErrorForUnitLengthTooLarge) { 596 #else 597 TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 598 #endif 599 if (!setupGenerator()) 600 return; 601 602 LineTable &Padding = Gen->addLineTable(); 603 // Add some padding to show that a non-zero offset is handled correctly. 604 Padding.setCustomPrologue({{0, LineTable::Byte}}); 605 LineTable < = Gen->addLineTable(); 606 LT.addStandardOpcode(DW_LNS_copy, {}); 607 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 608 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 609 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 610 // Set the total length to 1 higher than the actual length. 611 ++Prologue.TotalLength; 612 LT.setPrologue(Prologue); 613 614 generate(); 615 616 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 617 nullptr, RecordRecoverable); 618 EXPECT_THAT_ERROR( 619 std::move(Recoverable), 620 FailedWithMessage("line table program with offset 0x00000001 has length " 621 "0x00000034 but only 0x00000033 bytes are available")); 622 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 623 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 624 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 625 } 626 627 #ifdef _AIX 628 TEST_F(DebugLineBasicFixture, DISABLED_ErrorForMismatchedAddressSize) { 629 #else 630 TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 631 #endif 632 if (!setupGenerator(4, 8)) 633 return; 634 635 LineTable < = Gen->addLineTable(); 636 // The line data extractor expects size 8 (Quad) addresses. 637 uint64_t Addr1 = 0x11223344; 638 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 639 LT.addStandardOpcode(DW_LNS_copy, {}); 640 // Show that the expected address size is unchanged, so later valid lines 641 // don't cause a problem. 642 uint64_t Addr2 = 0x1122334455667788; 643 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 644 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 645 646 generate(); 647 648 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 649 nullptr, RecordRecoverable); 650 EXPECT_THAT_ERROR(std::move(Recoverable), 651 FailedWithMessage("mismatching address size at offset " 652 "0x00000030 expected 0x08 found 0x04")); 653 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 654 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 655 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 656 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 657 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 658 } 659 660 #ifdef _AIX 661 TEST_F(DebugLineBasicFixture, 662 DISABLED_ErrorForMismatchedAddressSizeUnsetInitialAddress) { 663 #else 664 TEST_F(DebugLineBasicFixture, 665 ErrorForMismatchedAddressSizeUnsetInitialAddress) { 666 #endif 667 if (!setupGenerator(4, 0)) 668 return; 669 670 LineTable < = Gen->addLineTable(); 671 uint64_t Addr1 = 0x11223344; 672 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 673 LT.addStandardOpcode(DW_LNS_copy, {}); 674 uint64_t Addr2 = 0x1122334455667788; 675 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 676 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 677 678 generate(); 679 680 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 681 nullptr, RecordRecoverable); 682 EXPECT_THAT_ERROR(std::move(Recoverable), 683 FailedWithMessage("mismatching address size at offset " 684 "0x00000038 expected 0x04 found 0x08")); 685 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 686 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 687 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 688 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 689 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 690 } 691 692 #ifdef _AIX 693 TEST_F(DebugLineBasicFixture, 694 DISABLED_ErrorForUnsupportedAddressSizeInSetAddressLength) { 695 #else 696 TEST_F(DebugLineBasicFixture, 697 ErrorForUnsupportedAddressSizeInSetAddressLength) { 698 #endif 699 // Use DWARF v4, and 0 for data extractor address size so that the address 700 // size is derived from the opcode length. 701 if (!setupGenerator(4, 0)) 702 return; 703 704 LineTable < = Gen->addLineTable(); 705 // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for 706 // the Half (2) + Byte (1) operand, representing the unsupported address size. 707 LT.addExtendedOpcode(4, DW_LNE_set_address, 708 {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}}); 709 LT.addStandardOpcode(DW_LNS_copy, {}); 710 // Special opcode to ensure the address has changed between the first and last 711 // row in the sequence. Without this, the sequence will not be recorded. 712 LT.addByte(0xaa); 713 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 714 715 generate(); 716 717 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 718 nullptr, RecordRecoverable); 719 EXPECT_THAT_ERROR( 720 std::move(Recoverable), 721 FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at " 722 "offset 0x00000030 is unsupported")); 723 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 724 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 725 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 726 // Show that the set address opcode is ignored in this case. 727 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 728 } 729 730 #ifdef _AIX 731 TEST_F(DebugLineBasicFixture, DISABLED_ErrorForAddressSizeGreaterThanByteSize) { 732 #else 733 TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) { 734 #endif 735 // Use DWARF v4, and 0 for data extractor address size so that the address 736 // size is derived from the opcode length. 737 if (!setupGenerator(4, 0)) 738 return; 739 740 LineTable < = Gen->addLineTable(); 741 // Specifically use an operand size that has a trailing byte of a supported 742 // size (8), so that any potential truncation would result in a valid size. 743 std::vector<LineTable::ValueAndLength> Operands(0x108); 744 LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands); 745 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 746 747 generate(); 748 749 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 750 nullptr, RecordRecoverable); 751 EXPECT_THAT_ERROR( 752 std::move(Recoverable), 753 FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at " 754 "offset 0x00000031 is unsupported")); 755 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 756 } 757 758 #ifdef _AIX 759 TEST_F(DebugLineBasicFixture, 760 DISABLED_ErrorForUnsupportedAddressSizeDefinedInHeader) { 761 #else 762 TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) { 763 #endif 764 // Use 0 for data extractor address size so that it does not clash with the 765 // header address size. 766 if (!setupGenerator(5, 0)) 767 return; 768 769 LineTable < = Gen->addLineTable(); 770 // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode 771 // itself and 9 for the Quad (8) + Byte (1) operand representing the 772 // unsupported address size. 773 uint8_t AddressSize = 9; 774 LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address, 775 {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}}); 776 LT.addStandardOpcode(DW_LNS_copy, {}); 777 // Special opcode to ensure the address has changed between the first and last 778 // row in the sequence. Without this, the sequence will not be recorded. 779 LT.addByte(0xaa); 780 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 781 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 782 Prologue.FormParams.AddrSize = AddressSize; 783 LT.setPrologue(Prologue); 784 785 generate(); 786 787 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 788 nullptr, RecordRecoverable); 789 EXPECT_THAT_ERROR( 790 std::move(Recoverable), 791 FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at " 792 "offset 0x00000038 is unsupported")); 793 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 794 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 795 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 796 // Show that the set address opcode is ignored in this case. 797 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 798 } 799 800 #ifdef _AIX 801 TEST_F(DebugLineBasicFixture, DISABLED_CallbackUsedForUnterminatedSequence) { 802 #else 803 TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 804 #endif 805 if (!setupGenerator()) 806 return; 807 808 LineTable < = Gen->addLineTable(); 809 LT.addExtendedOpcode(9, DW_LNE_set_address, 810 {{0x1122334455667788, LineTable::Quad}}); 811 LT.addStandardOpcode(DW_LNS_copy, {}); 812 LT.addByte(0xaa); 813 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 814 LT.addExtendedOpcode(9, DW_LNE_set_address, 815 {{0x99aabbccddeeff00, LineTable::Quad}}); 816 LT.addStandardOpcode(DW_LNS_copy, {}); 817 LT.addByte(0xbb); 818 LT.addByte(0xcc); 819 820 generate(); 821 822 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 823 nullptr, RecordRecoverable); 824 EXPECT_THAT_ERROR(std::move(Recoverable), 825 FailedWithMessage("last sequence in debug line table at " 826 "offset 0x00000000 is not terminated")); 827 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 828 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 829 // The unterminated sequence is not added to the sequence list. 830 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 831 } 832 833 struct AdjustAddressFixtureBase : public CommonFixture { 834 virtual ~AdjustAddressFixtureBase() {} 835 836 // Create and update the prologue as specified by the subclass, then return 837 // the length of the table. 838 virtual uint64_t editPrologue(LineTable <) = 0; 839 840 virtual uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncrs, 841 uint64_t SpecialIncrs, 842 uint64_t AdvanceIncrs) { 843 return Base + ConstIncrs + SpecialIncrs + AdvanceIncrs; 844 } 845 846 virtual uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) { 847 return Base + Incr; 848 } 849 850 uint64_t setupNoProblemTable() { 851 LineTable &NoProblem = Gen->addLineTable(); 852 NoProblem.addExtendedOpcode(9, DW_LNE_set_address, 853 {{0xabcd, LineTable::Quad}}); 854 NoProblem.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 855 return editPrologue(NoProblem); 856 } 857 858 uint64_t setupConstAddPcFirstTable() { 859 LineTable &ConstAddPCFirst = Gen->addLineTable(); 860 ConstAddPCFirst.addExtendedOpcode(9, DW_LNE_set_address, 861 {{ConstAddPCAddr, LineTable::Quad}}); 862 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 863 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 864 ConstAddPCFirst.addStandardOpcode(DW_LNS_advance_pc, 865 {{0x10, LineTable::ULEB}}); 866 ConstAddPCFirst.addByte(0x21); // Special opcode, +1 op, +1 line. 867 ConstAddPCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 868 return editPrologue(ConstAddPCFirst); 869 } 870 871 uint64_t setupSpecialFirstTable() { 872 LineTable &SpecialFirst = Gen->addLineTable(); 873 SpecialFirst.addExtendedOpcode(9, DW_LNE_set_address, 874 {{SpecialAddr, LineTable::Quad}}); 875 SpecialFirst.addByte(0x22); // Special opcode, +1 op, +2 line. 876 SpecialFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 877 SpecialFirst.addStandardOpcode(DW_LNS_advance_pc, 878 {{0x20, LineTable::ULEB}}); 879 SpecialFirst.addByte(0x23); // Special opcode, +1 op, +3 line. 880 SpecialFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 881 return editPrologue(SpecialFirst); 882 } 883 884 uint64_t setupAdvancePcFirstTable() { 885 LineTable &AdvancePCFirst = Gen->addLineTable(); 886 AdvancePCFirst.addExtendedOpcode(9, DW_LNE_set_address, 887 {{AdvancePCAddr, LineTable::Quad}}); 888 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 889 {{0x30, LineTable::ULEB}}); 890 AdvancePCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 891 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 892 {{0x40, LineTable::ULEB}}); 893 AdvancePCFirst.addByte(0x24); // Special opcode, +1 op, +4 line. 894 AdvancePCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 895 return editPrologue(AdvancePCFirst); 896 } 897 898 void setupTables(bool AddAdvancePCFirstTable) { 899 LineTable &Padding = Gen->addLineTable(); 900 Padding.setCustomPrologue({{0, LineTable::Byte}}); 901 NoProblemOffset = 1; 902 903 // Show that no warning is generated for the case where no 904 // DW_LNS_const_add_pc or special opcode is used. 905 ConstAddPCOffset = setupNoProblemTable() + NoProblemOffset; 906 907 // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode 908 // and then not again. 909 SpecialOffset = setupConstAddPcFirstTable() + ConstAddPCOffset; 910 911 // Show that the warning is emitted for the first special opcode and then 912 // not again. 913 AdvancePCOffset = setupSpecialFirstTable() + SpecialOffset; 914 915 // Show that the warning is emitted for the first DW_LNS_advance_pc opcode 916 // (if requested) and then not again. 917 if (AddAdvancePCFirstTable) 918 setupAdvancePcFirstTable(); 919 } 920 921 Expected<const DWARFDebugLine::LineTable *> 922 checkTable(uint64_t Offset, StringRef OpcodeType, const Twine &MsgSuffix) { 923 auto ExpectedTable = Line.getOrParseLineTable(LineData, Offset, *Context, 924 nullptr, RecordRecoverable); 925 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 926 if (!IsErrorExpected) { 927 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 928 } else { 929 if (!ExpectedTable) 930 return ExpectedTable; 931 uint64_t ExpectedOffset = Offset + 932 (*ExpectedTable)->Prologue.getLength() + 933 11; // 11 == size of DW_LNE_set_address. 934 std::string OffsetHex = Twine::utohexstr(Offset).str(); 935 std::string OffsetZeroes = std::string(8 - OffsetHex.size(), '0'); 936 std::string ExpectedHex = Twine::utohexstr(ExpectedOffset).str(); 937 std::string ExpectedZeroes = std::string(8 - ExpectedHex.size(), '0'); 938 EXPECT_THAT_ERROR( 939 std::move(Recoverable), 940 FailedWithMessage(("line table program at offset 0x" + OffsetZeroes + 941 OffsetHex + " contains a " + OpcodeType + 942 " opcode at offset 0x" + ExpectedZeroes + 943 ExpectedHex + ", " + MsgSuffix) 944 .str())); 945 } 946 return ExpectedTable; 947 } 948 949 void runTest(bool CheckAdvancePC, Twine MsgSuffix) { 950 if (!setupGenerator(Version)) 951 return; 952 953 setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC); 954 955 generate(); 956 957 auto ExpectedNoProblem = Line.getOrParseLineTable( 958 LineData, NoProblemOffset, *Context, nullptr, RecordRecoverable); 959 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 960 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 961 ASSERT_THAT_EXPECTED(ExpectedNoProblem, Succeeded()); 962 963 auto ExpectedConstAddPC = 964 checkTable(ConstAddPCOffset, "DW_LNS_const_add_pc", MsgSuffix); 965 ASSERT_THAT_EXPECTED(ExpectedConstAddPC, Succeeded()); 966 ASSERT_EQ((*ExpectedConstAddPC)->Rows.size(), 2u); 967 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Address.Address, 968 getAdjustedAddr(ConstAddPCAddr, ConstIncr * 2, 0x1, 0x10)); 969 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Line, getAdjustedLine(1, 1)); 970 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 971 972 auto ExpectedSpecial = checkTable(SpecialOffset, "special", MsgSuffix); 973 ASSERT_THAT_EXPECTED(ExpectedSpecial, Succeeded()); 974 ASSERT_EQ((*ExpectedSpecial)->Rows.size(), 3u); 975 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Address.Address, 976 getAdjustedAddr(SpecialAddr, 0, 1, 0)); 977 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Line, getAdjustedLine(1, 2)); 978 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Address.Address, 979 getAdjustedAddr(SpecialAddr, ConstIncr, 0x2, 0x20)); 980 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Line, getAdjustedLine(1, 5)); 981 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 982 983 if (!CheckAdvancePC) 984 return; 985 986 auto ExpectedAdvancePC = 987 checkTable(AdvancePCOffset, "DW_LNS_advance_pc", MsgSuffix); 988 ASSERT_THAT_EXPECTED(ExpectedAdvancePC, Succeeded()); 989 ASSERT_EQ((*ExpectedAdvancePC)->Rows.size(), 2u); 990 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Address.Address, 991 getAdjustedAddr(AdvancePCAddr, ConstIncr, 0x1, 0x70)); 992 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Line, getAdjustedLine(1, 4)); 993 } 994 995 uint64_t ConstIncr = 0x11; 996 uint64_t ConstAddPCAddr = 0x1234; 997 uint64_t SpecialAddr = 0x5678; 998 uint64_t AdvancePCAddr = 0xabcd; 999 uint64_t NoProblemOffset; 1000 uint64_t ConstAddPCOffset; 1001 uint64_t SpecialOffset; 1002 uint64_t AdvancePCOffset; 1003 1004 uint16_t Version = 4; 1005 bool IsErrorExpected; 1006 }; 1007 1008 struct MaxOpsPerInstFixture 1009 : TestWithParam<std::tuple<uint16_t, uint8_t, bool>>, 1010 AdjustAddressFixtureBase { 1011 void SetUp() override { 1012 std::tie(Version, MaxOpsPerInst, IsErrorExpected) = GetParam(); 1013 } 1014 1015 uint64_t editPrologue(LineTable <) override { 1016 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1017 Prologue.MaxOpsPerInst = MaxOpsPerInst; 1018 LT.setPrologue(Prologue); 1019 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1020 } 1021 1022 uint8_t MaxOpsPerInst; 1023 }; 1024 1025 #ifdef _AIX 1026 TEST_P(MaxOpsPerInstFixture, DISABLED_MaxOpsPerInstProblemsReportedCorrectly) { 1027 #else 1028 TEST_P(MaxOpsPerInstFixture, MaxOpsPerInstProblemsReportedCorrectly) { 1029 #endif 1030 runTest(/*CheckAdvancePC=*/true, 1031 "but the prologue maximum_operations_per_instruction value is " + 1032 Twine(unsigned(MaxOpsPerInst)) + 1033 ", which is unsupported. Assuming a value of 1 instead"); 1034 } 1035 1036 INSTANTIATE_TEST_SUITE_P( 1037 MaxOpsPerInstParams, MaxOpsPerInstFixture, 1038 Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error). 1039 std::make_tuple(4, 0, true), // Test zero value for V4 (error). 1040 std::make_tuple(4, 1, false), // Test good value for V4 (no error). 1041 std::make_tuple( 1042 4, 2, true))); // Test one higher than permitted V4 (error). 1043 1044 struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>, 1045 AdjustAddressFixtureBase { 1046 void SetUp() override { std::tie(LineRange, IsErrorExpected) = GetParam(); } 1047 1048 uint64_t editPrologue(LineTable <) override { 1049 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1050 Prologue.LineRange = LineRange; 1051 LT.setPrologue(Prologue); 1052 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1053 } 1054 1055 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 1056 uint64_t SpecialIncr, 1057 uint64_t AdvanceIncr) override { 1058 if (LineRange == 0) 1059 return Base + AdvanceIncr; 1060 return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr, 1061 SpecialIncr, AdvanceIncr); 1062 } 1063 1064 uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override { 1065 return LineRange != 0 1066 ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr) 1067 : Base; 1068 } 1069 1070 uint8_t LineRange; 1071 }; 1072 1073 #ifdef _AIX 1074 TEST_P(LineRangeFixture, DISABLED_LineRangeProblemsReportedCorrectly) { 1075 #else 1076 TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) { 1077 #endif 1078 runTest(/*CheckAdvancePC=*/false, 1079 "but the prologue line_range value is 0. The address and line will " 1080 "not be adjusted"); 1081 } 1082 1083 INSTANTIATE_TEST_SUITE_P( 1084 LineRangeParams, LineRangeFixture, 1085 Values(std::make_tuple(0, true), // Test zero value (error). 1086 std::make_tuple(14, false))); // Test non-zero value (no error). 1087 1088 struct BadMinInstLenFixture : TestWithParam<std::tuple<uint8_t, bool>>, 1089 AdjustAddressFixtureBase { 1090 void SetUp() override { 1091 std::tie(MinInstLength, IsErrorExpected) = GetParam(); 1092 } 1093 1094 uint64_t editPrologue(LineTable <) override { 1095 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1096 Prologue.MinInstLength = MinInstLength; 1097 LT.setPrologue(Prologue); 1098 return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1099 } 1100 1101 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 1102 uint64_t SpecialIncr, 1103 uint64_t AdvanceIncr) override { 1104 return MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( 1105 Base, ConstIncr, SpecialIncr, AdvanceIncr) 1106 : Base; 1107 } 1108 1109 uint8_t MinInstLength; 1110 }; 1111 1112 #ifdef _AIX 1113 TEST_P(BadMinInstLenFixture, DISABLED_MinInstLengthProblemsReportedCorrectly) { 1114 #else 1115 TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) { 1116 #endif 1117 runTest(/*CheckAdvancePC=*/true, 1118 "but the prologue minimum_instruction_length value is 0, which " 1119 "prevents any address advancing"); 1120 } 1121 1122 INSTANTIATE_TEST_SUITE_P( 1123 BadMinInstLenParams, BadMinInstLenFixture, 1124 Values(std::make_tuple(0, true), // Test zero value (error). 1125 std::make_tuple(1, false))); // Test non-zero value (no error). 1126 1127 #ifdef _AIX 1128 TEST_F(DebugLineBasicFixture, DISABLED_ParserParsesCorrectly) { 1129 #else 1130 TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 1131 #endif 1132 if (!setupGenerator()) 1133 return; 1134 1135 DWARFDebugLine::SectionParser Parser = setupParser(); 1136 1137 EXPECT_EQ(Parser.getOffset(), 0u); 1138 ASSERT_FALSE(Parser.done()); 1139 1140 DWARFDebugLine::LineTable Parsed = 1141 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1142 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 1143 EXPECT_EQ(Parsed.Sequences.size(), 1u); 1144 EXPECT_EQ(Parser.getOffset(), 62u); 1145 ASSERT_FALSE(Parser.done()); 1146 1147 DWARFDebugLine::LineTable Parsed2 = 1148 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1149 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 1150 EXPECT_EQ(Parsed2.Sequences.size(), 1u); 1151 EXPECT_EQ(Parser.getOffset(), 136u); 1152 EXPECT_TRUE(Parser.done()); 1153 1154 EXPECT_FALSE(Recoverable); 1155 EXPECT_FALSE(Unrecoverable); 1156 } 1157 1158 #ifdef _AIX 1159 TEST_F(DebugLineBasicFixture, DISABLED_ParserSkipsCorrectly) { 1160 #else 1161 TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 1162 #endif 1163 if (!setupGenerator()) 1164 return; 1165 1166 DWARFDebugLine::SectionParser Parser = setupParser(); 1167 1168 EXPECT_EQ(Parser.getOffset(), 0u); 1169 ASSERT_FALSE(Parser.done()); 1170 1171 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1172 EXPECT_EQ(Parser.getOffset(), 62u); 1173 ASSERT_FALSE(Parser.done()); 1174 1175 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1176 EXPECT_EQ(Parser.getOffset(), 136u); 1177 EXPECT_TRUE(Parser.done()); 1178 1179 EXPECT_FALSE(Recoverable); 1180 EXPECT_FALSE(Unrecoverable); 1181 } 1182 1183 #ifdef _AIX 1184 TEST_F(DebugLineBasicFixture, DISABLED_ParserAlwaysDoneForEmptySection) { 1185 #else 1186 TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 1187 #endif 1188 if (!setupGenerator()) 1189 return; 1190 1191 generate(); 1192 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1193 1194 EXPECT_TRUE(Parser.done()); 1195 } 1196 1197 #ifdef _AIX 1198 TEST_F(DebugLineBasicFixture, 1199 DISABLED_ParserMarkedAsDoneForBadLengthWhenParsing) { 1200 #else 1201 TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) { 1202 #endif 1203 if (!setupGenerator()) 1204 return; 1205 1206 LineTable < = Gen->addLineTable(); 1207 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1208 Gen->addLineTable(); 1209 generate(); 1210 1211 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1212 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1213 1214 EXPECT_EQ(Parser.getOffset(), 0u); 1215 EXPECT_TRUE(Parser.done()); 1216 EXPECT_FALSE(Recoverable); 1217 1218 EXPECT_THAT_ERROR( 1219 std::move(Unrecoverable), 1220 FailedWithMessage( 1221 "parsing line table prologue at offset 0x00000000: unsupported " 1222 "reserved unit length of value 0xfffffff0")); 1223 } 1224 1225 #ifdef _AIX 1226 TEST_F(DebugLineBasicFixture, 1227 DISABLED_ParserMarkedAsDoneForBadLengthWhenSkipping) { 1228 #else 1229 TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) { 1230 #endif 1231 if (!setupGenerator()) 1232 return; 1233 1234 LineTable < = Gen->addLineTable(); 1235 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1236 Gen->addLineTable(); 1237 generate(); 1238 1239 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1240 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1241 1242 EXPECT_EQ(Parser.getOffset(), 0u); 1243 EXPECT_TRUE(Parser.done()); 1244 EXPECT_FALSE(Recoverable); 1245 1246 EXPECT_THAT_ERROR( 1247 std::move(Unrecoverable), 1248 FailedWithMessage( 1249 "parsing line table prologue at offset 0x00000000: unsupported " 1250 "reserved unit length of value 0xfffffff0")); 1251 } 1252 1253 #ifdef _AIX 1254 TEST_F(DebugLineBasicFixture, 1255 DISABLED_ParserReportsFirstErrorInEachTableWhenParsing) { 1256 #else 1257 TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 1258 #endif 1259 if (!setupGenerator()) 1260 return; 1261 1262 LineTable < = Gen->addLineTable(DWARF32); 1263 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1264 LineTable <2 = Gen->addLineTable(DWARF32); 1265 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1266 generate(); 1267 1268 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1269 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1270 ASSERT_FALSE(Parser.done()); 1271 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1272 1273 EXPECT_TRUE(Parser.done()); 1274 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1275 1276 EXPECT_THAT_ERROR( 1277 std::move(Unrecoverable), 1278 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1279 "unsupported version 0", 1280 "parsing line table prologue at offset 0x00000006: " 1281 "unsupported version 1")); 1282 } 1283 1284 #ifdef _AIX 1285 TEST_F(DebugLineBasicFixture, 1286 DISABLED_ParserReportsNonPrologueProblemsWhenParsing) { 1287 #else 1288 TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 1289 #endif 1290 if (!setupGenerator()) 1291 return; 1292 1293 LineTable < = Gen->addLineTable(DWARF32); 1294 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 1295 LineTable <2 = Gen->addLineTable(DWARF32); 1296 LT2.addExtendedOpcode(9, DW_LNE_set_address, 1297 {{0x1234567890abcdef, LineTable::Quad}}); 1298 LT2.addStandardOpcode(DW_LNS_copy, {}); 1299 LT2.addByte(0xbb); 1300 generate(); 1301 1302 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1303 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1304 EXPECT_FALSE(Unrecoverable); 1305 ASSERT_FALSE(Parser.done()); 1306 EXPECT_THAT_ERROR(std::move(Recoverable), 1307 FailedWithMessage("unexpected line op length at offset " 1308 "0x00000030 expected 0x42 found 0x01")); 1309 1310 // Reset the error state so that it does not confuse the next set of checks. 1311 Unrecoverable = Error::success(); 1312 Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1313 1314 EXPECT_TRUE(Parser.done()); 1315 EXPECT_THAT_ERROR(std::move(Recoverable), 1316 FailedWithMessage("last sequence in debug line table at " 1317 "offset 0x00000031 is not terminated")); 1318 EXPECT_FALSE(Unrecoverable); 1319 } 1320 1321 #ifdef _AIX 1322 TEST_F(DebugLineBasicFixture, 1323 DISABLED_ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1324 #else 1325 TEST_F(DebugLineBasicFixture, 1326 ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1327 #endif 1328 if (!setupGenerator()) 1329 return; 1330 1331 LineTable < = Gen->addLineTable(DWARF32); 1332 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1333 LineTable <2 = Gen->addLineTable(DWARF32); 1334 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1335 generate(); 1336 1337 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1338 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1339 ASSERT_FALSE(Parser.done()); 1340 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1341 1342 EXPECT_TRUE(Parser.done()); 1343 EXPECT_FALSE(Recoverable); 1344 1345 EXPECT_THAT_ERROR( 1346 std::move(Unrecoverable), 1347 FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1348 "unsupported version 0", 1349 "parsing line table prologue at offset 0x00000006: " 1350 "unsupported version 1")); 1351 } 1352 1353 #ifdef _AIX 1354 TEST_F(DebugLineBasicFixture, 1355 DISABLED_ParserIgnoresNonPrologueErrorsWhenSkipping) { 1356 #else 1357 TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 1358 #endif 1359 if (!setupGenerator()) 1360 return; 1361 1362 LineTable < = Gen->addLineTable(DWARF32); 1363 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 1364 generate(); 1365 1366 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1367 Parser.skip(RecordRecoverable, RecordUnrecoverable); 1368 1369 EXPECT_TRUE(Parser.done()); 1370 EXPECT_FALSE(Recoverable); 1371 EXPECT_FALSE(Unrecoverable); 1372 } 1373 1374 #ifdef _AIX 1375 TEST_F(DebugLineBasicFixture, DISABLED_VerboseOutput) { 1376 #else 1377 TEST_F(DebugLineBasicFixture, VerboseOutput) { 1378 #endif 1379 if (!setupGenerator(5)) 1380 return; 1381 1382 LineTable < = Gen->addLineTable(); 1383 LT.addByte(0); // Extended opcode with zero length. 1384 LT.addByte(0); 1385 // Zero-value extended opcode. 1386 LT.addExtendedOpcode(2, 0, {{1, LineTable::Byte}}); 1387 // Unknown extended opcode. 1388 LT.addExtendedOpcode(2, 0x42, {{1, LineTable::Byte}}); 1389 LT.addExtendedOpcode(9, DW_LNE_set_address, 1390 {{0x123456789abcdef, LineTable::Quad}}); 1391 LT.addExtendedOpcode(6, DW_LNE_define_file, 1392 {{'a', LineTable::Byte}, 1393 {'\0', LineTable::Byte}, 1394 {2, LineTable::ULEB}, 1395 {3, LineTable::ULEB}, 1396 {4, LineTable::ULEB}}); 1397 LT.addExtendedOpcode(2, DW_LNE_set_discriminator, {{0x7f, LineTable::ULEB}}); 1398 LT.addStandardOpcode(DW_LNS_copy, {}); 1399 LT.addStandardOpcode(DW_LNS_advance_pc, {{11, LineTable::ULEB}}); 1400 LT.addStandardOpcode(DW_LNS_advance_line, {{22, LineTable::SLEB}}); 1401 LT.addStandardOpcode(DW_LNS_set_file, {{33, LineTable::ULEB}}); 1402 LT.addStandardOpcode(DW_LNS_set_column, {{44, LineTable::ULEB}}); 1403 LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 1404 LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 1405 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 1406 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{55, LineTable::Half}}); 1407 LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 1408 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 1409 LT.addStandardOpcode(DW_LNS_set_isa, {{66, LineTable::ULEB}}); 1410 // Add unknown standard opcode with operands. 1411 LT.addStandardOpcode( 1412 0xd, {{1, LineTable::ULEB}, {0x123456789abcdef, LineTable::ULEB}}); 1413 // Add unknown standard opcode without operands. 1414 LT.addStandardOpcode(0xe, {}); 1415 LT.addByte(0xff); // Special opcode. 1416 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 1417 1418 // Adjust the prologue to account for the extra standard opcode. 1419 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1420 Prologue.TotalLength += 2; 1421 Prologue.PrologueLength += 2; 1422 Prologue.OpcodeBase += 2; 1423 Prologue.StandardOpcodeLengths.push_back(2); 1424 Prologue.StandardOpcodeLengths.push_back(0); 1425 LT.setPrologue(Prologue); 1426 1427 generate(); 1428 1429 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1430 std::string Output; 1431 raw_string_ostream OS(Output); 1432 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1433 /*Verbose=*/true); 1434 OS.flush(); 1435 StringRef OutputRef(Output); 1436 1437 size_t Pos = 0; 1438 auto NextLine = [&Pos, &OutputRef]() { 1439 size_t EOL = OutputRef.find_first_of('\n', Pos); 1440 StringRef Line = OutputRef.substr(Pos, EOL - Pos); 1441 Pos = EOL + 1; 1442 return Line; 1443 }; 1444 EXPECT_EQ(NextLine(), "Line table prologue:"); 1445 EXPECT_EQ(NextLine(), " total_length: 0x00000078"); 1446 EXPECT_EQ(NextLine(), " format: DWARF32"); 1447 EXPECT_EQ(NextLine(), " version: 5"); 1448 EXPECT_EQ(NextLine(), " address_size: 8"); 1449 EXPECT_EQ(NextLine(), " seg_select_size: 0"); 1450 EXPECT_EQ(NextLine(), " prologue_length: 0x0000002c"); 1451 EXPECT_EQ(NextLine(), " min_inst_length: 1"); 1452 EXPECT_EQ(NextLine(), "max_ops_per_inst: 1"); 1453 EXPECT_EQ(NextLine(), " default_is_stmt: 1"); 1454 EXPECT_EQ(NextLine(), " line_base: -5"); 1455 EXPECT_EQ(NextLine(), " line_range: 14"); 1456 EXPECT_EQ(NextLine(), " opcode_base: 15"); 1457 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_copy] = 0"); 1458 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_pc] = 1"); 1459 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_line] = 1"); 1460 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_file] = 1"); 1461 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_column] = 1"); 1462 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_negate_stmt] = 0"); 1463 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_basic_block] = 0"); 1464 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_const_add_pc] = 0"); 1465 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1"); 1466 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_prologue_end] = 0"); 1467 EXPECT_EQ(NextLine(), 1468 "standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0"); 1469 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_isa] = 1"); 1470 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_d] = 2"); 1471 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_e] = 0"); 1472 EXPECT_EQ(NextLine(), "include_directories[ 0] = \"a dir\""); 1473 EXPECT_EQ(NextLine(), "file_names[ 0]:"); 1474 EXPECT_EQ(NextLine(), " name: \"a file\""); 1475 EXPECT_EQ(NextLine(), " dir_index: 0"); 1476 EXPECT_EQ(NextLine(), ""); 1477 EXPECT_EQ(NextLine(), " Address Line Column File ISA Discriminator Flags"); 1478 EXPECT_EQ(NextLine(), " ------------------ ------ ------ ------ --- ------------- -------------"); 1479 EXPECT_EQ(NextLine(), 1480 "0x00000038: 00 Badly formed extended line op (length 0)"); 1481 EXPECT_EQ(NextLine(), 1482 "0x0000003a: 00 Unrecognized extended op 0x00 length 2"); 1483 EXPECT_EQ(NextLine(), 1484 "0x0000003e: 00 Unrecognized extended op 0x42 length 2"); 1485 EXPECT_EQ(NextLine(), 1486 "0x00000042: 00 DW_LNE_set_address (0x0123456789abcdef)"); 1487 EXPECT_EQ(NextLine(), "0x0000004d: 00 DW_LNE_define_file (a, dir=2, " 1488 "mod_time=(0x0000000000000003), length=4)"); 1489 EXPECT_EQ(NextLine(), "0x00000055: 00 DW_LNE_set_discriminator (127)"); 1490 EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy"); 1491 EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 " 1492 "0 127 is_stmt"); 1493 EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (11)"); 1494 EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)"); 1495 EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)"); 1496 EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)"); 1497 EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt"); 1498 EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block"); 1499 EXPECT_EQ(NextLine(), 1500 "0x00000064: 08 DW_LNS_const_add_pc (0x0000000000000011)"); 1501 EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (0x0037)"); 1502 EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end"); 1503 EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin"); 1504 EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)"); 1505 EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode " 1506 "(operands: 0x0000000000000001, 0x0123456789abcdef)"); 1507 EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode"); 1508 EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3"); 1509 EXPECT_EQ(NextLine(), 1510 " 0x0123456789abce53 20 44 33 66 " 1511 " 0 basic_block prologue_end epilogue_begin"); 1512 EXPECT_EQ(NextLine(), "0x00000079: 00 DW_LNE_end_sequence"); 1513 EXPECT_EQ(NextLine(), " 0x0123456789abce53 20 44 33 " 1514 "66 0 end_sequence"); 1515 EXPECT_EQ(NextLine(), ""); 1516 EXPECT_EQ(Output.size(), Pos); 1517 } 1518 1519 struct TruncatedPrologueFixture 1520 : public TestWithParam< 1521 std::tuple<uint64_t, uint64_t, uint16_t, DwarfFormat, StringRef>>, 1522 public CommonFixture { 1523 void SetUp() override { 1524 std::tie(Length, ExpectedOffset, Version, Format, ExpectedErr) = GetParam(); 1525 } 1526 1527 uint64_t Length; 1528 uint64_t ExpectedOffset; 1529 uint16_t Version; 1530 DwarfFormat Format; 1531 StringRef ExpectedErr; 1532 }; 1533 1534 #ifdef _AIX 1535 TEST_P(TruncatedPrologueFixture, DISABLED_ErrorForTruncatedPrologue) { 1536 #else 1537 TEST_P(TruncatedPrologueFixture, ErrorForTruncatedPrologue) { 1538 #endif 1539 if (!setupGenerator(Version)) 1540 return; 1541 1542 LineTable &Padding = Gen->addLineTable(); 1543 // Add some padding to show that a non-zero offset is handled correctly. 1544 Padding.setCustomPrologue({{0, LineTable::Byte}}); 1545 1546 // Add a table with only two standard opcodes - we don't need to test the full 1547 // set. 1548 LineTable &Table = Gen->addLineTable(Format); 1549 DWARFDebugLine::Prologue InputPrologue = Table.createBasicPrologue(); 1550 InputPrologue.OpcodeBase = 3; 1551 InputPrologue.StandardOpcodeLengths.resize(2); 1552 Table.setPrologue(InputPrologue); 1553 1554 generate(); 1555 // Truncate the data extractor to the specified length. 1556 LineData = DWARFDataExtractor(LineData, Length); 1557 1558 DWARFDebugLine::Prologue Prologue; 1559 uint64_t Offset = 1; 1560 Error Err = Prologue.parse(LineData, &Offset, RecordRecoverable, *Context); 1561 1562 EXPECT_THAT_ERROR(std::move(Err), FailedWithMessage(ExpectedErr.str())); 1563 EXPECT_EQ(Offset, ExpectedOffset); 1564 } 1565 1566 INSTANTIATE_TEST_SUITE_P( 1567 TruncatedPrologueParams, TruncatedPrologueFixture, 1568 Values( 1569 // Truncated length: 1570 std::make_tuple( 1571 4, 1, 4, DWARF32, 1572 "parsing line table prologue at offset 0x00000001: unexpected end " 1573 "of data at offset 0x4 while reading [0x1, 0x5)"), 1574 std::make_tuple( 1575 4, 1, 4, DWARF64, 1576 "parsing line table prologue at offset 0x00000001: unexpected end " 1577 "of data at offset 0x4 while reading [0x1, 0x5)"), 1578 std::make_tuple( 1579 0xc, 1, 4, DWARF64, 1580 "parsing line table prologue at offset 0x00000001: unexpected end " 1581 "of data at offset 0xc while reading [0x5, 0xd)"), 1582 // Truncated version: 1583 std::make_tuple( 1584 6, 5, 4, DWARF32, 1585 "parsing line table prologue at offset 0x00000001: unexpected end " 1586 "of data at offset 0x6 while reading [0x5, 0x7)"), 1587 // Truncated address size: 1588 std::make_tuple( 1589 7, 7, 5, DWARF32, 1590 "parsing line table prologue at offset 0x00000001: unexpected end " 1591 "of data at offset 0x7 while reading [0x7, 0x8)"), 1592 // Truncated segment selector size: 1593 std::make_tuple( 1594 8, 8, 5, DWARF32, 1595 "parsing line table prologue at offset 0x00000001: unexpected end " 1596 "of data at offset 0x8 while reading [0x8, 0x9)"), 1597 // Truncated prologue length: 1598 std::make_tuple( 1599 0xa, 7, 4, DWARF32, 1600 "parsing line table prologue at offset 0x00000001: unexpected end " 1601 "of data at offset 0xa while reading [0x7, 0xb)"), 1602 std::make_tuple( 1603 0x16, 0xf, 4, DWARF64, 1604 "parsing line table prologue at offset 0x00000001: unexpected end " 1605 "of data at offset 0x16 while reading [0xf, 0x17)"), 1606 // Truncated min instruction length: 1607 std::make_tuple( 1608 0xb, 0xb, 4, DWARF32, 1609 "parsing line table prologue at offset 0x00000001: unexpected end " 1610 "of data at offset 0xb while reading [0xb, 0xc)"), 1611 // Truncated max ops per inst: 1612 std::make_tuple( 1613 0xc, 0xc, 4, DWARF32, 1614 "parsing line table prologue at offset 0x00000001: unexpected end " 1615 "of data at offset 0xc while reading [0xc, 0xd)"), 1616 // Truncated default is stmt: 1617 std::make_tuple( 1618 0xd, 0xd, 4, DWARF32, 1619 "parsing line table prologue at offset 0x00000001: unexpected end " 1620 "of data at offset 0xd while reading [0xd, 0xe)"), 1621 // Truncated line base: 1622 std::make_tuple( 1623 0xe, 0xe, 4, DWARF32, 1624 "parsing line table prologue at offset 0x00000001: unexpected end " 1625 "of data at offset 0xe while reading [0xe, 0xf)"), 1626 // Truncated line range: 1627 std::make_tuple( 1628 0xf, 0xf, 4, DWARF32, 1629 "parsing line table prologue at offset 0x00000001: unexpected end " 1630 "of data at offset 0xf while reading [0xf, 0x10)"), 1631 // Truncated opcode base: 1632 std::make_tuple( 1633 0x10, 0x10, 4, DWARF32, 1634 "parsing line table prologue at offset 0x00000001: unexpected end " 1635 "of data at offset 0x10 while reading [0x10, 0x11)"), 1636 // Truncated first standard opcode: 1637 std::make_tuple( 1638 0x11, 0x11, 4, DWARF32, 1639 "parsing line table prologue at offset 0x00000001: unexpected end " 1640 "of data at offset 0x11 while reading [0x11, 0x12)"), 1641 // Truncated second standard opcode: 1642 std::make_tuple( 1643 0x12, 0x12, 4, DWARF32, 1644 "parsing line table prologue at offset 0x00000001: unexpected end " 1645 "of data at offset 0x12 while reading [0x12, 0x13)"))); 1646 1647 using ValueAndLengths = std::vector<LineTable::ValueAndLength>; 1648 1649 struct TruncatedOpcodeFixtureBase : public CommonFixture { 1650 LineTable &setupTable() { 1651 LineTable < = Gen->addLineTable(); 1652 1653 // Creating the prologue before adding any opcodes ensures that the unit 1654 // length does not include the table body. 1655 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1656 1657 // Add an unrecognised standard opcode, and adjust prologue properties 1658 // accordingly. 1659 Prologue.TotalLength += BodyLength + 1; 1660 ++Prologue.PrologueLength; 1661 ++Prologue.OpcodeBase; 1662 Prologue.StandardOpcodeLengths.push_back(2); 1663 LT.setPrologue(Prologue); 1664 1665 return LT; 1666 } 1667 1668 void runTest(uint8_t OpcodeValue) { 1669 generate(); 1670 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1671 std::string Output; 1672 raw_string_ostream OS(Output); 1673 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1674 /*Verbose=*/true); 1675 OS.flush(); 1676 1677 std::string LinePrefix = 1678 ("0x0000002f: 0" + Twine::utohexstr(OpcodeValue) + " ").str(); 1679 StringRef OutputRef(Output); 1680 StringRef OutputToCheck = OutputRef.split(LinePrefix).second; 1681 // Each extended opcode ends with a new line and then the table ends with an 1682 // additional blank line. 1683 EXPECT_EQ((ExpectedOutput + "\n\n").str(), OutputToCheck); 1684 } 1685 1686 uint64_t BodyLength; 1687 uint8_t Opcode; 1688 ValueAndLengths Operands; 1689 StringRef ExpectedOutput; 1690 StringRef ExpectedErr; 1691 }; 1692 1693 struct TruncatedStandardOpcodeFixture 1694 : public TestWithParam< 1695 std::tuple<uint64_t, uint8_t, ValueAndLengths, StringRef, StringRef>>, 1696 public TruncatedOpcodeFixtureBase { 1697 void SetUp() override { 1698 std::tie(BodyLength, Opcode, Operands, ExpectedOutput, ExpectedErr) = 1699 GetParam(); 1700 } 1701 }; 1702 1703 struct TruncatedExtendedOpcodeFixture 1704 : public TestWithParam<std::tuple<uint64_t, uint64_t, uint8_t, 1705 ValueAndLengths, StringRef, StringRef>>, 1706 public TruncatedOpcodeFixtureBase { 1707 void SetUp() override { 1708 std::tie(BodyLength, OpcodeLength, Opcode, Operands, ExpectedOutput, 1709 ExpectedErr) = GetParam(); 1710 } 1711 1712 uint64_t OpcodeLength; 1713 }; 1714 1715 #ifdef _AIX 1716 TEST_P(TruncatedExtendedOpcodeFixture, 1717 DISABLED_ErrorForTruncatedExtendedOpcode) { 1718 #else 1719 TEST_P(TruncatedExtendedOpcodeFixture, ErrorForTruncatedExtendedOpcode) { 1720 #endif 1721 if (!setupGenerator()) 1722 return; 1723 LineTable < = setupTable(); 1724 LT.addExtendedOpcode(OpcodeLength, Opcode, Operands); 1725 runTest(0); 1726 EXPECT_THAT_ERROR(std::move(Recoverable), 1727 FailedWithMessage(ExpectedErr.str())); 1728 } 1729 1730 INSTANTIATE_TEST_SUITE_P( 1731 TruncatedExtendedOpcodeParams, TruncatedExtendedOpcodeFixture, 1732 Values( 1733 // Truncated length: 1734 std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 1735 "unable to decode LEB128 at offset 0x00000030: " 1736 "malformed uleb128, extends past end"), 1737 // Truncated opcode: 1738 std::make_tuple( 1739 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 1740 "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"), 1741 // Truncated operands: 1742 std::make_tuple( 1743 3, 9, DW_LNE_set_address, 1744 ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}}, 1745 "DW_LNE_set_address", 1746 "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"), 1747 std::make_tuple( 1748 10, 9, DW_LNE_set_address, 1749 ValueAndLengths{{0x1234567878563412, LineTable::Quad}}, 1750 "DW_LNE_set_address (<parsing error> 12 34 56 78 78 56 34)", 1751 "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"), 1752 std::make_tuple(3, 6, DW_LNE_define_file, 1753 ValueAndLengths{{'a', LineTable::Byte}, 1754 {'\0', LineTable::Byte}, 1755 {1, LineTable::ULEB}, 1756 {1, LineTable::ULEB}, 1757 {1, LineTable::ULEB}}, 1758 "DW_LNE_define_file", 1759 "no null terminated string at offset 0x32"), 1760 std::make_tuple(5, 6, DW_LNE_define_file, 1761 ValueAndLengths{{'a', LineTable::Byte}, 1762 {'\0', LineTable::Byte}, 1763 {1, LineTable::ULEB}, 1764 {1, LineTable::ULEB}, 1765 {1, LineTable::ULEB}}, 1766 "DW_LNE_define_file (<parsing error> 61 00)", 1767 "unable to decode LEB128 at offset 0x00000034: " 1768 "malformed uleb128, extends past end"), 1769 std::make_tuple(6, 6, DW_LNE_define_file, 1770 ValueAndLengths{{'a', LineTable::Byte}, 1771 {'\0', LineTable::Byte}, 1772 {1, LineTable::ULEB}, 1773 {1, LineTable::ULEB}, 1774 {1, LineTable::ULEB}}, 1775 "DW_LNE_define_file (<parsing error> 61 00 01)", 1776 "unable to decode LEB128 at offset 0x00000035: " 1777 "malformed uleb128, extends past end"), 1778 std::make_tuple(7, 6, DW_LNE_define_file, 1779 ValueAndLengths{{'a', LineTable::Byte}, 1780 {'\0', LineTable::Byte}, 1781 {1, LineTable::ULEB}, 1782 {1, LineTable::ULEB}, 1783 {1, LineTable::ULEB}}, 1784 "DW_LNE_define_file (<parsing error> 61 00 01 01)", 1785 "unable to decode LEB128 at offset 0x00000036: " 1786 "malformed uleb128, extends past end"), 1787 std::make_tuple(3, 2, DW_LNE_set_discriminator, 1788 ValueAndLengths{{1, LineTable::ULEB}}, 1789 "DW_LNE_set_discriminator", 1790 "unable to decode LEB128 at offset 0x00000032: " 1791 "malformed uleb128, extends past end"), 1792 std::make_tuple( 1793 6, 5, /*Unknown=*/0x7f, 1794 ValueAndLengths{{0x12343412, LineTable::Long}}, 1795 "Unrecognized extended op 0x7f length 5 (<parsing error> 12 34 34)", 1796 "unexpected end of data at offset 0x35 while reading [0x32, " 1797 "0x36)"))); 1798 1799 #ifdef _AIX 1800 TEST_P(TruncatedStandardOpcodeFixture, 1801 DISABLED_ErrorForTruncatedStandardOpcode) { 1802 #else 1803 TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) { 1804 #endif 1805 if (!setupGenerator()) 1806 return; 1807 LineTable < = setupTable(); 1808 LT.addStandardOpcode(Opcode, Operands); 1809 runTest(Opcode); 1810 EXPECT_THAT_ERROR(std::move(Unrecoverable), 1811 FailedWithMessage(ExpectedErr.str())); 1812 } 1813 1814 INSTANTIATE_TEST_SUITE_P( 1815 TruncatedStandardOpcodeParams, TruncatedStandardOpcodeFixture, 1816 Values( 1817 std::make_tuple(2, DW_LNS_advance_pc, 1818 ValueAndLengths{{0x100, LineTable::ULEB}}, 1819 "DW_LNS_advance_pc", 1820 "unable to decode LEB128 at offset 0x00000030: " 1821 "malformed uleb128, extends past end"), 1822 std::make_tuple(2, DW_LNS_advance_line, 1823 ValueAndLengths{{0x200, LineTable::SLEB}}, 1824 "DW_LNS_advance_line", 1825 "unable to decode LEB128 at offset 0x00000030: " 1826 "malformed sleb128, extends past end"), 1827 std::make_tuple(2, DW_LNS_set_file, 1828 ValueAndLengths{{0x300, LineTable::ULEB}}, 1829 "DW_LNS_set_file", 1830 "unable to decode LEB128 at offset 0x00000030: " 1831 "malformed uleb128, extends past end"), 1832 std::make_tuple(2, DW_LNS_set_column, 1833 ValueAndLengths{{0x400, LineTable::ULEB}}, 1834 "DW_LNS_set_column", 1835 "unable to decode LEB128 at offset 0x00000030: " 1836 "malformed uleb128, extends past end"), 1837 std::make_tuple( 1838 2, DW_LNS_fixed_advance_pc, 1839 ValueAndLengths{{0x500, LineTable::Half}}, 1840 "DW_LNS_fixed_advance_pc", 1841 "unexpected end of data at offset 0x31 while reading [0x30, 0x32)"), 1842 std::make_tuple(2, DW_LNS_set_isa, 1843 ValueAndLengths{{0x600, LineTable::ULEB}}, 1844 "DW_LNS_set_isa", 1845 "unable to decode LEB128 at offset 0x00000030: " 1846 "malformed uleb128, extends past end"), 1847 std::make_tuple(2, 0xd, 1848 ValueAndLengths{{0x700, LineTable::ULEB}, 1849 {0x800, LineTable::ULEB}}, 1850 "Unrecognized standard opcode", 1851 "unable to decode LEB128 at offset 0x00000030: " 1852 "malformed uleb128, extends past end"), 1853 std::make_tuple( 1854 4, 0xd, 1855 ValueAndLengths{{0x900, LineTable::ULEB}, {0xa00, LineTable::ULEB}}, 1856 "Unrecognized standard opcode (operands: 0x0000000000000900)", 1857 "unable to decode LEB128 at offset 0x00000032: " 1858 "malformed uleb128, extends past end"))); 1859 1860 #ifdef _AIX 1861 TEST_F(DebugLineBasicFixture, DISABLED_PrintPathsProperly) { 1862 #else 1863 TEST_F(DebugLineBasicFixture, PrintPathsProperly) { 1864 #endif 1865 if (!setupGenerator(5)) 1866 return; 1867 1868 LineTable < = Gen->addLineTable(); 1869 DWARFDebugLine::Prologue P = LT.createBasicPrologue(); 1870 P.IncludeDirectories.push_back( 1871 DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); 1872 P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); 1873 P.FileNames.back().Name = 1874 DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); 1875 P.FileNames.back().DirIdx = 1; 1876 P.TotalLength += 14; 1877 P.PrologueLength += 14; 1878 LT.setPrologue(P); 1879 generate(); 1880 1881 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 1882 nullptr, RecordRecoverable); 1883 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 1884 std::string Result; 1885 // DWARF 5 stores the compilation directory in two places: the Compilation 1886 // Unit and the directory table entry 0, and implementations are free to use 1887 // one or the other. This copy serves as the one stored in the CU. 1888 StringRef CompDir = "a dir"; 1889 EXPECT_FALSE( 1890 (*ExpectedLineTable) 1891 ->Prologue.getFileNameByIndex( 1892 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); 1893 EXPECT_TRUE((*ExpectedLineTable) 1894 ->Prologue.getFileNameByIndex( 1895 1, CompDir, 1896 DILineInfoSpecifier::FileLineInfoKind::RawValue, Result)); 1897 EXPECT_TRUE((*ExpectedLineTable) 1898 ->Prologue.getFileNameByIndex( 1899 1, CompDir, 1900 DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly, 1901 Result)); 1902 EXPECT_STREQ(Result.c_str(), "b file"); 1903 EXPECT_TRUE((*ExpectedLineTable) 1904 ->Prologue.getFileNameByIndex( 1905 1, CompDir, 1906 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, 1907 Result)); 1908 EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file")); 1909 EXPECT_TRUE((*ExpectedLineTable) 1910 ->Prologue.getFileNameByIndex( 1911 1, CompDir, 1912 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 1913 Result)); 1914 EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file")); 1915 } 1916 1917 } // end anonymous namespace 1918