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