2152 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"10#include "DwarfGenerator.h"11#include "DwarfUtils.h"12#include "llvm/DebugInfo/DWARF/DWARFContext.h"13#include "llvm/Object/ObjectFile.h"14#include "llvm/Testing/Support/Error.h"15#include "gtest/gtest.h"16 17// AIX doesn't support the debug_addr section18#ifdef _AIX19#define NO_SUPPORT_DEBUG_ADDR20#endif21 22using namespace llvm;23using namespace dwarf;24using namespace dwarfgen;25using namespace object;26using namespace utils;27using namespace testing;28 29namespace {30struct CommonFixture {31 CommonFixture()32 : LineData("", true, 0), Recoverable(Error::success()),33 RecordRecoverable(std::bind(&CommonFixture::recordRecoverable, this,34 std::placeholders::_1)),35 Unrecoverable(Error::success()),36 RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this,37 std::placeholders::_1)){};38 39 ~CommonFixture() {40 EXPECT_FALSE(Recoverable);41 EXPECT_FALSE(Unrecoverable);42 }43 44 // Note: ASSERT_THAT_EXPECTED cannot be used in a non-void function, so45 // setupGenerator() is split into two.46 void setupGeneratorImpl(uint16_t Version, uint8_t AddrSize) {47 AddressSize = AddrSize;48 Triple T = getDefaultTargetTripleForAddrSize(AddressSize ? AddressSize : 8);49 if (!isConfigurationSupported(T))50 return;51 auto ExpectedGenerator = Generator::create(T, Version);52 ASSERT_THAT_EXPECTED(ExpectedGenerator, Succeeded());53 Gen = std::move(*ExpectedGenerator);54 }55 56 bool setupGenerator(uint16_t Version = 4, uint8_t AddrSize = 8) {57 setupGeneratorImpl(Version, AddrSize);58 return Gen != nullptr;59 }60 61 void generate() {62 Context = createContext();63 assert(Context != nullptr && "test state is not valid");64 const DWARFObject &Obj = Context->getDWARFObj();65 uint8_t TargetAddrSize = AddressSize == 0 ? 8 : AddressSize;66 LineData = DWARFDataExtractor(67 Obj, Obj.getLineSection(),68 getDefaultTargetTripleForAddrSize(TargetAddrSize).isLittleEndian(),69 AddressSize);70 }71 72 std::unique_ptr<DWARFContext> createContext() {73 assert(Gen != nullptr && "Generator is not set up");74 StringRef FileBytes = Gen->generate();75 MemoryBufferRef FileBuffer(FileBytes, "dwarf");76 auto Obj = object::ObjectFile::createObjectFile(FileBuffer);77 if (Obj)78 return DWARFContext::create(**Obj);79 return nullptr;80 }81 82 DWARFDebugLine::SectionParser setupParser() {83 LineTable < = Gen->addLineTable(DWARF32);84 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});85 LT.addStandardOpcode(DW_LNS_copy, {});86 LT.addByte(0xaa);87 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});88 89 LineTable <2 = Gen->addLineTable(DWARF64);90 LT2.addExtendedOpcode(9, DW_LNE_set_address,91 {{0x11223344, LineTable::Quad}});92 LT2.addStandardOpcode(DW_LNS_copy, {});93 LT2.addByte(0xbb);94 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});95 96 generate();97 98 return DWARFDebugLine::SectionParser(LineData, *Context, Units);99 }100 101 void recordRecoverable(Error Err) {102 Recoverable = joinErrors(std::move(Recoverable), std::move(Err));103 }104 void recordUnrecoverable(Error Err) {105 Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err));106 }107 108 Expected<const DWARFDebugLine::LineTable *>109 getOrParseLineTableFatalErrors(uint64_t Offset = 0) {110 auto ExpectedLineTable = Line.getOrParseLineTable(111 LineData, Offset, *Context, nullptr, RecordRecoverable);112 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());113 return ExpectedLineTable;114 }115 116 uint8_t AddressSize;117 std::unique_ptr<Generator> Gen;118 std::unique_ptr<DWARFContext> Context;119 DWARFDataExtractor LineData;120 DWARFDebugLine Line;121 Error Recoverable;122 std::function<void(Error)> RecordRecoverable;123 Error Unrecoverable;124 std::function<void(Error)> RecordUnrecoverable;125 126 SmallVector<std::unique_ptr<DWARFUnit>, 2> Units;127};128 129// Fixtures must derive from "Test", but parameterised fixtures from130// "TestWithParam". It does not seem possible to inherit from both, so we share131// the common state in a separate class, inherited by the two fixture classes.132struct DebugLineBasicFixture : public Test, public CommonFixture {};133 134struct DebugLineParameterisedFixture135 : public TestWithParam<std::pair<uint16_t, DwarfFormat>>,136 public CommonFixture {137 void SetUp() override { std::tie(Version, Format) = GetParam(); }138 139 uint16_t Version;140 DwarfFormat Format;141};142 143void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,144 DWARFDebugLine::Prologue Prologue,145 uint64_t BodyLength) {146 // Check version specific fields and values.147 uint64_t UnitLength;148 uint64_t PrologueLength;149 switch (Version) {150 case 4:151 PrologueLength = 36;152 UnitLength = PrologueLength + 2;153 EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);154 break;155 case 2:156 case 3:157 PrologueLength = 35;158 UnitLength = PrologueLength + 2;159 break;160 case 5:161 PrologueLength = 42;162 UnitLength = PrologueLength + 4;163 EXPECT_EQ(Prologue.getAddressSize(), 8u);164 EXPECT_EQ(Prologue.SegSelectorSize, 0u);165 break;166 default:167 llvm_unreachable("unsupported DWARF version");168 }169 UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8);170 171 EXPECT_EQ(Prologue.TotalLength, UnitLength);172 EXPECT_EQ(Prologue.PrologueLength, PrologueLength);173 EXPECT_EQ(Prologue.MinInstLength, 1u);174 EXPECT_EQ(Prologue.DefaultIsStmt, 1u);175 EXPECT_EQ(Prologue.LineBase, -5);176 EXPECT_EQ(Prologue.LineRange, 14u);177 EXPECT_EQ(Prologue.OpcodeBase, 13u);178 std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};179 EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths);180 ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u);181 ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string);182 EXPECT_STREQ(*toString(Prologue.IncludeDirectories[0]), "a dir");183 ASSERT_EQ(Prologue.FileNames.size(), 1u);184 ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string);185 ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u);186 EXPECT_STREQ(*toString(Prologue.FileNames[0].Name), "a file");187}188 189TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) {190 if (!setupGenerator())191 GTEST_SKIP();192 generate();193 194 EXPECT_THAT_EXPECTED(195 getOrParseLineTableFatalErrors(0),196 FailedWithMessage(197 "offset 0x00000000 is not a valid debug line section offset"));198 // Repeat to show that an error is reported each time.199 EXPECT_THAT_EXPECTED(200 getOrParseLineTableFatalErrors(0),201 FailedWithMessage(202 "offset 0x00000000 is not a valid debug line section offset"));203 204 // Show that an error is reported for later offsets too.205 EXPECT_THAT_EXPECTED(206 getOrParseLineTableFatalErrors(1),207 FailedWithMessage(208 "offset 0x00000001 is not a valid debug line section offset"));209}210 211TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) {212 if (!setupGenerator())213 GTEST_SKIP();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 NO_SUPPORT_DEBUG_ADDR233TEST_P(DebugLineParameterisedFixture, DISABLED_PrologueGetLength) {234#else235TEST_P(DebugLineParameterisedFixture, PrologueGetLength) {236#endif237 if (!setupGenerator(Version))238 GTEST_SKIP();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 NO_SUPPORT_DEBUG_ADDR260TEST_P(DebugLineParameterisedFixture, DISABLED_GetOrParseLineTableValidTable) {261#else262TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {263#endif264 if (!setupGenerator(Version))265 GTEST_SKIP();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 is310 // 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 read326 // correctly.327}328 329#ifdef NO_SUPPORT_DEBUG_ADDR330TEST_P(DebugLineParameterisedFixture, DISABLED_ClearLineValidTable) {331#else332TEST_P(DebugLineParameterisedFixture, ClearLineValidTable) {333#endif334 if (!setupGenerator(Version))335 GTEST_SKIP();336 337 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +338 (Format == DWARF64 ? "DWARF64" : "DWARF32"));339 340 LineTable < = Gen->addLineTable(Format);341 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}});342 LT.addStandardOpcode(DW_LNS_copy, {});343 LT.addByte(0xaa);344 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});345 346 LineTable <2 = Gen->addLineTable(Format);347 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}});348 LT2.addStandardOpcode(DW_LNS_copy, {});349 LT2.addByte(0xbb);350 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});351 LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}});352 LT2.addStandardOpcode(DW_LNS_copy, {});353 LT2.addByte(0xcc);354 LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});355 356 generate();357 358 // Check that we have what we expect before calling clearLineTable().359 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,360 nullptr, RecordRecoverable);361 ASSERT_TRUE((bool)ExpectedLineTable);362 EXPECT_FALSE(Recoverable);363 const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable;364 checkDefaultPrologue(Version, Format, Expected->Prologue, 16);365 EXPECT_EQ(Expected->Sequences.size(), 1u);366 367 uint64_t SecondOffset =368 Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength;369 Recoverable = Error::success();370 auto ExpectedLineTable2 = Line.getOrParseLineTable(371 LineData, SecondOffset, *Context, nullptr, RecordRecoverable);372 ASSERT_TRUE((bool)ExpectedLineTable2);373 EXPECT_FALSE(Recoverable);374 const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2;375 checkDefaultPrologue(Version, Format, Expected2->Prologue, 32);376 EXPECT_EQ(Expected2->Sequences.size(), 2u);377 378 // Check that we no longer get the line tables after clearLineTable().379 Line.clearLineTable(0);380 Line.clearLineTable(SecondOffset);381 EXPECT_EQ(Line.getLineTable(0), nullptr);382 EXPECT_EQ(Line.getLineTable(SecondOffset), nullptr);383 384 // Check that if the same offset is requested, the contents match what we385 // had before.386 Recoverable = Error::success();387 auto ExpectedLineTable3 = Line.getOrParseLineTable(388 LineData, 0, *Context, nullptr, RecordRecoverable);389 ASSERT_TRUE((bool)ExpectedLineTable3);390 EXPECT_FALSE(Recoverable);391 const DWARFDebugLine::LineTable *Expected3 = *ExpectedLineTable3;392 checkDefaultPrologue(Version, Format, Expected3->Prologue, 16);393 EXPECT_EQ(Expected3->Sequences.size(), 1u);394 395 Recoverable = Error::success();396 auto ExpectedLineTable4 = Line.getOrParseLineTable(397 LineData, SecondOffset, *Context, nullptr, RecordRecoverable);398 ASSERT_TRUE((bool)ExpectedLineTable4);399 EXPECT_FALSE(Recoverable);400 const DWARFDebugLine::LineTable *Expected4 = *ExpectedLineTable4;401 checkDefaultPrologue(Version, Format, Expected4->Prologue, 32);402 EXPECT_EQ(Expected4->Sequences.size(), 2u);403}404 405TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {406 if (!setupGenerator())407 GTEST_SKIP();408 409 LineTable < = Gen->addLineTable();410 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});411 412 generate();413 414 EXPECT_THAT_EXPECTED(415 getOrParseLineTableFatalErrors(),416 FailedWithMessage(417 "parsing line table prologue at offset 0x00000000: unsupported "418 "reserved unit length of value 0xfffffff0"));419}420 421struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>,422 public CommonFixture {423 void SetUp() override { Version = GetParam(); }424 425 uint16_t Version;426};427 428TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) {429 if (!setupGenerator())430 GTEST_SKIP();431 432 LineTable < = Gen->addLineTable();433 LT.setCustomPrologue(434 {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}});435 436 generate();437 438 EXPECT_THAT_EXPECTED(439 getOrParseLineTableFatalErrors(),440 FailedWithMessage("parsing line table prologue at offset 0x00000000: "441 "unsupported version " +442 std::to_string(Version)));443}444 445INSTANTIATE_TEST_SUITE_P(UnsupportedVersionTestParams,446 DebugLineUnsupportedVersionFixture,447 Values(/*1 below min */ 1, /* 1 above max */ 6,448 /* Maximum possible */ 0xffff));449 450#ifdef NO_SUPPORT_DEBUG_ADDR451TEST_F(DebugLineBasicFixture, DISABLED_ErrorForInvalidV5IncludeDirTable) {452#else453TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {454#endif455 if (!setupGenerator(5))456 GTEST_SKIP();457 458 LineTable < = Gen->addLineTable();459 LT.setCustomPrologue({460 {19, LineTable::Long}, // unit length461 {5, LineTable::Half}, // version462 {8, LineTable::Byte}, // addr size463 {0, LineTable::Byte}, // segment selector size464 {11, LineTable::Long}, // prologue length465 {1, LineTable::Byte}, // min instruction length466 {1, LineTable::Byte}, // max ops per instruction467 {1, LineTable::Byte}, // default is_stmt468 {0, LineTable::Byte}, // line base469 {14, LineTable::Byte}, // line range470 {2, LineTable::Byte}, // opcode base (small to reduce the amount of471 // setup required).472 {0, LineTable::Byte}, // standard opcode lengths473 {0, LineTable::Byte}, // directory entry format count (should not be474 // zero).475 {0, LineTable::ULEB}, // directories count476 {0, LineTable::Byte}, // file name entry format count477 {0, LineTable::ULEB} // file name entry count478 });479 480 generate();481 482 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,483 nullptr, RecordRecoverable);484 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());485 486 EXPECT_THAT_ERROR(487 std::move(Recoverable),488 FailedWithMessage(489 "parsing line table prologue at 0x00000000 found an invalid "490 "directory or file table description at 0x00000014",491 "failed to parse entry content descriptions because no path was "492 "found"));493}494 495#ifdef NO_SUPPORT_DEBUG_ADDR496TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooLargePrologueLength) {497#else498TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {499#endif500 if (!setupGenerator(Version))501 GTEST_SKIP();502 503 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +504 (Format == DWARF64 ? "DWARF64" : "DWARF32"));505 506 LineTable < = Gen->addLineTable(Format);507 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();508 ++Prologue.PrologueLength;509 LT.setPrologue(Prologue);510 511 generate();512 513 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,514 nullptr, RecordRecoverable);515 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());516 DWARFDebugLine::LineTable Result(**ExpectedLineTable);517 // Undo the earlier modification so that it can be compared against a518 // "default" prologue.519 --Result.Prologue.PrologueLength;520 checkDefaultPrologue(Version, Format, Result.Prologue, 0);521 522 uint64_t ExpectedEnd =523 Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();524 EXPECT_THAT_ERROR(525 std::move(Recoverable),526 FailedWithMessage(527 ("unknown data in line table prologue at offset 0x00000000: "528 "parsing ended (at offset 0x000000" +529 Twine::utohexstr(ExpectedEnd - 1) +530 ") before reaching the prologue end at offset 0x000000" +531 Twine::utohexstr(ExpectedEnd))532 .str()));533}534 535#ifdef NO_SUPPORT_DEBUG_ADDR536TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooShortPrologueLength) {537#else538TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {539#endif540 if (!setupGenerator(Version))541 GTEST_SKIP();542 543 SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " +544 (Format == DWARF64 ? "DWARF64" : "DWARF32"));545 546 LineTable < = Gen->addLineTable(Format);547 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();548 Prologue.PrologueLength -= 2;549 LT.setPrologue(Prologue);550 551 generate();552 553 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,554 nullptr, RecordRecoverable);555 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());556 DWARFDebugLine::LineTable Result(**ExpectedLineTable);557 558 // Parsing will stop before reading a complete file entry.559 ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u);560 EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir");561 EXPECT_EQ(Result.Prologue.FileNames.size(), 0u);562 563 // The exact place where the parsing will stop depends on the structure of the564 // prologue and the last complete field we are able to read. Before V5 we stop565 // before reading the file length. In V5, we stop before the filename.566 uint64_t ExpectedEnd = Prologue.TotalLength + Prologue.sizeofTotalLength() -567 (Version < 5 ? 2 : 8);568 std::vector<std::string> Errs;569 Errs.emplace_back(570 (Twine("parsing line table prologue at 0x00000000 found an invalid "571 "directory or file table description at 0x000000") +572 Twine::utohexstr(ExpectedEnd))573 .str());574 if (Version < 5) {575 Errs.emplace_back("file names table was not null terminated before the end "576 "of the prologue");577 } else {578 Errs.emplace_back(579 "failed to parse file entry because extracting the form value failed");580 }581 EXPECT_THAT_ERROR(std::move(Recoverable),582 FailedWithMessageArray(testing::ElementsAreArray(Errs)));583}584 585INSTANTIATE_TEST_SUITE_P(586 LineTableTestParams, DebugLineParameterisedFixture,587 Values(std::make_pair(588 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32.589 std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields.590 std::make_pair(4, DWARF64), // Test v4 fields and DWARF64.591 std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)));592 593TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) {594 if (!setupGenerator())595 GTEST_SKIP();596 597 LineTable < = Gen->addLineTable();598 LT.addByte(0xaa);599 // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode.600 // The operand will be read for both the discriminator opcode and then parsed601 // again as DW_LNS_negate_stmt, to respect the claimed length.602 LT.addExtendedOpcode(1, DW_LNE_set_discriminator,603 {{DW_LNS_negate_stmt, LineTable::ULEB}});604 LT.addByte(0xbb);605 LT.addStandardOpcode(DW_LNS_const_add_pc, {});606 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});607 608 generate();609 610 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,611 nullptr, RecordRecoverable);612 EXPECT_THAT_ERROR(std::move(Recoverable),613 FailedWithMessage("unexpected line op length at offset "614 "0x00000031 expected 0x01 found 0x02"));615 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());616 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);617 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);618 EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u);619 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt);620}621 622TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) {623 if (!setupGenerator())624 GTEST_SKIP();625 626 LineTable < = Gen->addLineTable();627 LT.addByte(0xaa);628 LT.addStandardOpcode(DW_LNS_const_add_pc, {});629 // The Length should be 1 for an end sequence opcode.630 LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});631 // The negate statement opcode will be skipped.632 LT.addStandardOpcode(DW_LNS_negate_stmt, {});633 LT.addByte(0xbb);634 LT.addStandardOpcode(DW_LNS_const_add_pc, {});635 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});636 637 generate();638 639 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,640 nullptr, RecordRecoverable);641 EXPECT_THAT_ERROR(std::move(Recoverable),642 FailedWithMessage("unexpected line op length at offset "643 "0x00000032 expected 0x02 found 0x01"));644 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());645 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u);646 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u);647 ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u);648 EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u);649}650 651TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {652 if (!setupGenerator())653 GTEST_SKIP();654 655 LineTable &Padding = Gen->addLineTable();656 // Add some padding to show that a non-zero offset is handled correctly.657 Padding.setCustomPrologue({{0, LineTable::Byte}});658 LineTable < = Gen->addLineTable();659 LT.addStandardOpcode(DW_LNS_copy, {});660 LT.addStandardOpcode(DW_LNS_const_add_pc, {});661 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});662 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();663 // Set the total length to 1 higher than the actual length.664 ++Prologue.TotalLength;665 LT.setPrologue(Prologue);666 667 generate();668 669 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context,670 nullptr, RecordRecoverable);671 EXPECT_THAT_ERROR(672 std::move(Recoverable),673 FailedWithMessage("line table program with offset 0x00000001 has length "674 "0x00000034 but only 0x00000033 bytes are available"));675 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());676 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);677 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);678}679 680TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {681 if (!setupGenerator(4, 8))682 GTEST_SKIP();683 684 LineTable < = Gen->addLineTable();685 // The line data extractor expects size 8 (Quad) addresses.686 uint64_t Addr1 = 0x11223344;687 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});688 LT.addStandardOpcode(DW_LNS_copy, {});689 // Show that the expected address size is unchanged, so later valid lines690 // don't cause a problem.691 uint64_t Addr2 = 0x1122334455667788;692 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});693 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});694 695 generate();696 697 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,698 nullptr, RecordRecoverable);699 EXPECT_THAT_ERROR(std::move(Recoverable),700 FailedWithMessage("mismatching address size at offset "701 "0x00000030 expected 0x08 found 0x04"));702 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());703 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);704 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);705 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);706 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);707}708 709TEST_F(DebugLineBasicFixture,710 ErrorForMismatchedAddressSizeUnsetInitialAddress) {711 if (!setupGenerator(4, 0))712 GTEST_SKIP();713 714 LineTable < = Gen->addLineTable();715 uint64_t Addr1 = 0x11223344;716 LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}});717 LT.addStandardOpcode(DW_LNS_copy, {});718 uint64_t Addr2 = 0x1122334455667788;719 LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}});720 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});721 722 generate();723 724 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,725 nullptr, RecordRecoverable);726 EXPECT_THAT_ERROR(std::move(Recoverable),727 FailedWithMessage("mismatching address size at offset "728 "0x00000038 expected 0x04 found 0x08"));729 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());730 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u);731 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);732 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1);733 EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2);734}735 736TEST_F(DebugLineBasicFixture,737 ErrorForUnsupportedAddressSizeInSetAddressLength) {738 // Use DWARF v4, and 0 for data extractor address size so that the address739 // size is derived from the opcode length.740 if (!setupGenerator(4, 0))741 GTEST_SKIP();742 743 LineTable < = Gen->addLineTable();744 // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for745 // the Half (2) + Byte (1) operand, representing the unsupported address size.746 LT.addExtendedOpcode(4, DW_LNE_set_address,747 {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}});748 LT.addStandardOpcode(DW_LNS_copy, {});749 // Special opcode to ensure the address has changed between the first and last750 // row in the sequence. Without this, the sequence will not be recorded.751 LT.addByte(0xaa);752 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});753 754 generate();755 756 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,757 nullptr, RecordRecoverable);758 EXPECT_THAT_ERROR(759 std::move(Recoverable),760 FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at "761 "offset 0x00000030 is unsupported"));762 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());763 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);764 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);765 // Show that the set address opcode is ignored in this case.766 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u);767}768 769TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) {770 // Use DWARF v4, and 0 for data extractor address size so that the address771 // size is derived from the opcode length.772 if (!setupGenerator(4, 0))773 GTEST_SKIP();774 775 LineTable < = Gen->addLineTable();776 // Specifically use an operand size that has a trailing byte of a supported777 // size (8), so that any potential truncation would result in a valid size.778 std::vector<LineTable::ValueAndLength> Operands(0x108);779 LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands);780 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});781 782 generate();783 784 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,785 nullptr, RecordRecoverable);786 EXPECT_THAT_ERROR(787 std::move(Recoverable),788 FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at "789 "offset 0x00000031 is unsupported"));790 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());791}792 793#ifdef NO_SUPPORT_DEBUG_ADDR794TEST_F(DebugLineBasicFixture,795 DISABLED_ErrorForUnsupportedAddressSizeDefinedInHeader) {796#else797TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) {798#endif799 // Use 0 for data extractor address size so that it does not clash with the800 // header address size.801 if (!setupGenerator(5, 0))802 GTEST_SKIP();803 804 LineTable < = Gen->addLineTable();805 // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode806 // itself and 9 for the Quad (8) + Byte (1) operand representing the807 // unsupported address size.808 uint8_t AddressSize = 9;809 LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address,810 {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}});811 LT.addStandardOpcode(DW_LNS_copy, {});812 // Special opcode to ensure the address has changed between the first and last813 // row in the sequence. Without this, the sequence will not be recorded.814 LT.addByte(0xaa);815 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});816 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();817 Prologue.FormParams.AddrSize = AddressSize;818 LT.setPrologue(Prologue);819 820 generate();821 822 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,823 nullptr, RecordRecoverable);824 EXPECT_THAT_ERROR(825 std::move(Recoverable),826 FailedWithMessage("parsing line table prologue at offset 0x00000000: "827 "invalid address size 9",828 "address size 0x09 of DW_LNE_set_address opcode at "829 "offset 0x00000038 is unsupported"));830 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());831 ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u);832 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);833 // Show that the set address opcode is ignored in this case.834 EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u);835}836 837TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {838 if (!setupGenerator())839 GTEST_SKIP();840 841 LineTable < = Gen->addLineTable();842 LT.addExtendedOpcode(9, DW_LNE_set_address,843 {{0x1122334455667788, LineTable::Quad}});844 LT.addStandardOpcode(DW_LNS_copy, {});845 LT.addByte(0xaa);846 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});847 LT.addExtendedOpcode(9, DW_LNE_set_address,848 {{0x99aabbccddeeff00, LineTable::Quad}});849 LT.addStandardOpcode(DW_LNS_copy, {});850 LT.addByte(0xbb);851 LT.addByte(0xcc);852 853 generate();854 855 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,856 nullptr, RecordRecoverable);857 EXPECT_THAT_ERROR(std::move(Recoverable),858 FailedWithMessage("last sequence in debug line table at "859 "offset 0x00000000 is not terminated"));860 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());861 EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u);862 // The unterminated sequence is not added to the sequence list.863 EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);864}865 866struct AdjustAddressFixtureBase : public CommonFixture {867 virtual ~AdjustAddressFixtureBase() = default;868 869 // Create and update the prologue as specified by the subclass, then return870 // the length of the table.871 virtual uint64_t editPrologue(LineTable <) = 0;872 873 virtual uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncrs,874 uint64_t SpecialIncrs,875 uint64_t AdvanceIncrs) {876 return Base + ConstIncrs + SpecialIncrs + AdvanceIncrs;877 }878 879 virtual uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) {880 return Base + Incr;881 }882 883 uint64_t setupNoProblemTable() {884 LineTable &NoProblem = Gen->addLineTable();885 NoProblem.addExtendedOpcode(9, DW_LNE_set_address,886 {{0xabcd, LineTable::Quad}});887 NoProblem.addExtendedOpcode(1, DW_LNE_end_sequence, {});888 return editPrologue(NoProblem);889 }890 891 uint64_t setupConstAddPcFirstTable() {892 LineTable &ConstAddPCFirst = Gen->addLineTable();893 ConstAddPCFirst.addExtendedOpcode(9, DW_LNE_set_address,894 {{ConstAddPCAddr, LineTable::Quad}});895 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {});896 ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {});897 ConstAddPCFirst.addStandardOpcode(DW_LNS_advance_pc,898 {{0x10, LineTable::ULEB}});899 ConstAddPCFirst.addByte(0x21); // Special opcode, +1 op, +1 line.900 ConstAddPCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {});901 return editPrologue(ConstAddPCFirst);902 }903 904 uint64_t setupSpecialFirstTable() {905 LineTable &SpecialFirst = Gen->addLineTable();906 SpecialFirst.addExtendedOpcode(9, DW_LNE_set_address,907 {{SpecialAddr, LineTable::Quad}});908 SpecialFirst.addByte(0x22); // Special opcode, +1 op, +2 line.909 SpecialFirst.addStandardOpcode(DW_LNS_const_add_pc, {});910 SpecialFirst.addStandardOpcode(DW_LNS_advance_pc,911 {{0x20, LineTable::ULEB}});912 SpecialFirst.addByte(0x23); // Special opcode, +1 op, +3 line.913 SpecialFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {});914 return editPrologue(SpecialFirst);915 }916 917 uint64_t setupAdvancePcFirstTable() {918 LineTable &AdvancePCFirst = Gen->addLineTable();919 AdvancePCFirst.addExtendedOpcode(9, DW_LNE_set_address,920 {{AdvancePCAddr, LineTable::Quad}});921 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc,922 {{0x30, LineTable::ULEB}});923 AdvancePCFirst.addStandardOpcode(DW_LNS_const_add_pc, {});924 AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc,925 {{0x40, LineTable::ULEB}});926 AdvancePCFirst.addByte(0x24); // Special opcode, +1 op, +4 line.927 AdvancePCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {});928 return editPrologue(AdvancePCFirst);929 }930 931 void setupTables(bool AddAdvancePCFirstTable) {932 LineTable &Padding = Gen->addLineTable();933 Padding.setCustomPrologue({{0, LineTable::Byte}});934 NoProblemOffset = 1;935 936 // Show that no warning is generated for the case where no937 // DW_LNS_const_add_pc or special opcode is used.938 ConstAddPCOffset = setupNoProblemTable() + NoProblemOffset;939 940 // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode941 // and then not again.942 SpecialOffset = setupConstAddPcFirstTable() + ConstAddPCOffset;943 944 // Show that the warning is emitted for the first special opcode and then945 // not again.946 AdvancePCOffset = setupSpecialFirstTable() + SpecialOffset;947 948 // Show that the warning is emitted for the first DW_LNS_advance_pc opcode949 // (if requested) and then not again.950 if (AddAdvancePCFirstTable)951 setupAdvancePcFirstTable();952 }953 954 Expected<const DWARFDebugLine::LineTable *>955 checkTable(uint64_t Offset, StringRef OpcodeType, const Twine &MsgSuffix) {956 auto ExpectedTable = Line.getOrParseLineTable(LineData, Offset, *Context,957 nullptr, RecordRecoverable);958 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());959 if (!IsErrorExpected) {960 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());961 } else {962 if (!ExpectedTable)963 return ExpectedTable;964 uint64_t ExpectedOffset = Offset +965 (*ExpectedTable)->Prologue.getLength() +966 11; // 11 == size of DW_LNE_set_address.967 std::string OffsetHex = Twine::utohexstr(Offset).str();968 std::string OffsetZeroes = std::string(8 - OffsetHex.size(), '0');969 std::string ExpectedHex = Twine::utohexstr(ExpectedOffset).str();970 std::string ExpectedZeroes = std::string(8 - ExpectedHex.size(), '0');971 EXPECT_THAT_ERROR(972 std::move(Recoverable),973 FailedWithMessage(("line table program at offset 0x" + OffsetZeroes +974 OffsetHex + " contains a " + OpcodeType +975 " opcode at offset 0x" + ExpectedZeroes +976 ExpectedHex + ", " + MsgSuffix)977 .str()));978 }979 return ExpectedTable;980 }981 982 void runTest(bool CheckAdvancePC, Twine MsgSuffix) {983 if (!setupGenerator(Version))984 GTEST_SKIP();985 986 setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC);987 988 generate();989 990 auto ExpectedNoProblem = Line.getOrParseLineTable(991 LineData, NoProblemOffset, *Context, nullptr, RecordRecoverable);992 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());993 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());994 ASSERT_THAT_EXPECTED(ExpectedNoProblem, Succeeded());995 996 auto ExpectedConstAddPC =997 checkTable(ConstAddPCOffset, "DW_LNS_const_add_pc", MsgSuffix);998 ASSERT_THAT_EXPECTED(ExpectedConstAddPC, Succeeded());999 ASSERT_EQ((*ExpectedConstAddPC)->Rows.size(), 2u);1000 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Address.Address,1001 getAdjustedAddr(ConstAddPCAddr, ConstIncr * 2, 0x1, 0x10));1002 EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Line, getAdjustedLine(1, 1));1003 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1004 1005 auto ExpectedSpecial = checkTable(SpecialOffset, "special", MsgSuffix);1006 ASSERT_THAT_EXPECTED(ExpectedSpecial, Succeeded());1007 ASSERT_EQ((*ExpectedSpecial)->Rows.size(), 3u);1008 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Address.Address,1009 getAdjustedAddr(SpecialAddr, 0, 1, 0));1010 EXPECT_EQ((*ExpectedSpecial)->Rows[0].Line, getAdjustedLine(1, 2));1011 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Address.Address,1012 getAdjustedAddr(SpecialAddr, ConstIncr, 0x2, 0x20));1013 EXPECT_EQ((*ExpectedSpecial)->Rows[1].Line, getAdjustedLine(1, 5));1014 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1015 1016 if (!CheckAdvancePC)1017 return;1018 1019 auto ExpectedAdvancePC =1020 checkTable(AdvancePCOffset, "DW_LNS_advance_pc", MsgSuffix);1021 ASSERT_THAT_EXPECTED(ExpectedAdvancePC, Succeeded());1022 ASSERT_EQ((*ExpectedAdvancePC)->Rows.size(), 2u);1023 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Address.Address,1024 getAdjustedAddr(AdvancePCAddr, ConstIncr, 0x1, 0x70));1025 EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Line, getAdjustedLine(1, 4));1026 }1027 1028 uint64_t ConstIncr = 0x11;1029 uint64_t ConstAddPCAddr = 0x1234;1030 uint64_t SpecialAddr = 0x5678;1031 uint64_t AdvancePCAddr = 0xabcd;1032 uint64_t NoProblemOffset;1033 uint64_t ConstAddPCOffset;1034 uint64_t SpecialOffset;1035 uint64_t AdvancePCOffset;1036 1037 uint16_t Version = 4;1038 bool IsErrorExpected;1039};1040 1041struct OpIndexFixture : Test, CommonFixture {1042 void createPrologue(LineTable <, uint8_t MaxOpsPerInst,1043 uint8_t MinInstLength) {1044 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();1045 Prologue.MaxOpsPerInst = MaxOpsPerInst;1046 Prologue.MinInstLength = MinInstLength;1047 LT.setPrologue(Prologue);1048 }1049};1050 1051TEST_F(OpIndexFixture, OpIndexAdvance) {1052 if (!setupGenerator(4, 4))1053 GTEST_SKIP();1054 1055 uint8_t MaxOpsPerInst = 13;1056 uint8_t MinInstLength = 4;1057 1058 LineTable < = Gen->addLineTable();1059 1060 // Row 0-2: Different locations for one bundle set up using special opcodes.1061 LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x20, LineTable::Long}});1062 LT.addByte(0x13); // Special opcode, +1 line.1063 LT.addByte(0x23); // Special opcode, +3 line, +1 op-index.1064 LT.addByte(0x3a); // Special opcode, -2 line, +3 op-index.1065 1066 // Row 3: New bundle, set up using DW_LNS_advance pc.1067 // Operation advance 0x84, which gives +40 addr, +2 op-index1068 LT.addStandardOpcode(DW_LNS_advance_line, {{100, LineTable::SLEB}});1069 LT.addStandardOpcode(DW_LNS_advance_pc, {{0x84, LineTable::ULEB}});1070 LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.1071 1072 // Row 4: New bundle, set up using a single special opcode.1073 LT.addByte(0x71); // Special opcode, +4 addr, -3 line, -6 op-index.1074 1075 // Row 5: New bundle, set up using using DW_LNS_const_add_pc.1076 // Corresponds to advancing address and op-index using special opcode 255,1077 // which gives +4 addr, +4 op-index.1078 LT.addStandardOpcode(DW_LNS_advance_line, {{10, LineTable::SLEB}});1079 LT.addStandardOpcode(DW_LNS_const_add_pc, {});1080 LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.1081 1082 // Row 6: End sequence to have the input well-formed.1083 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});1084 1085 createPrologue(LT, MaxOpsPerInst, MinInstLength);1086 1087 generate();1088 1089 auto VerifyRow = [](const DWARFDebugLine::Row &Row, uint64_t Address,1090 uint8_t OpIndex, uint32_t Line) {1091 EXPECT_EQ(Row.Address.Address, Address);1092 EXPECT_EQ(Row.OpIndex, OpIndex);1093 EXPECT_EQ(Row.Line, Line);1094 };1095 1096 auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,1097 RecordRecoverable);1098 EXPECT_THAT_ERROR(1099 std::move(Recoverable),1100 FailedWithMessage("line table program at offset 0x00000000 contains a "1101 "special opcode at offset 0x00000035, but the prologue "1102 "maximum_operations_per_instruction value is 13, which "1103 "is experimentally supported, so line number "1104 "information may be incorrect"));1105 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1106 ASSERT_THAT_EXPECTED(Table, Succeeded());1107 1108 ASSERT_EQ((*Table)->Rows.size(), 7u);1109 1110 VerifyRow((*Table)->Rows[0], 0x20, 0, 2);1111 VerifyRow((*Table)->Rows[1], 0x20, 1, 5);1112 VerifyRow((*Table)->Rows[2], 0x20, 4, 3);1113 VerifyRow((*Table)->Rows[3], 0x48, 6, 103);1114 VerifyRow((*Table)->Rows[4], 0x4c, 0, 100);1115 VerifyRow((*Table)->Rows[5], 0x50, 4, 110);1116}1117 1118TEST_F(OpIndexFixture, OpIndexReset) {1119 if (!setupGenerator(4, 4))1120 GTEST_SKIP();1121 1122 uint8_t MaxOpsPerInst = 13;1123 uint8_t MinInstLength = 4;1124 1125 LineTable < = Gen->addLineTable();1126 1127 // Row 0: Just set op-index to some value > 0.1128 LT.addExtendedOpcode(5, DW_LNE_set_address, {{0, LineTable::Long}});1129 LT.addByte(0x20); // Special opcode, +1 op-index1130 1131 // Row 1: DW_LNE_fixed_advance_pc should set op-index to 0.1132 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{10, LineTable::Half}});1133 LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.1134 1135 // Row 2: Just set op-index to some value > 0.1136 LT.addByte(0x66); // Special opcode, +6 op-index1137 1138 // Row 3: DW_LNE_set_address should set op-index to 0.1139 LT.addExtendedOpcode(5, DW_LNE_set_address, {{20, LineTable::Long}});1140 LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.1141 1142 // Row 4: Just set op-index to some value > 0.1143 LT.addByte(0xba); // Special opcode, +12 op-index1144 1145 // Row 5: End sequence (op-index unchanged for this row)...1146 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});1147 1148 // Row 6: ... but shall be reset after the DW_LNE_end_sequence row.1149 LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.1150 1151 // Row 7: End sequence to have the input well-formed.1152 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});1153 1154 createPrologue(LT, MaxOpsPerInst, MinInstLength);1155 1156 generate();1157 1158 auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,1159 RecordRecoverable);1160 EXPECT_THAT_ERROR(1161 std::move(Recoverable),1162 FailedWithMessage("line table program at offset 0x00000000 contains a "1163 "special opcode at offset 0x00000035, but the prologue "1164 "maximum_operations_per_instruction value is 13, which "1165 "is experimentally supported, so line number "1166 "information may be incorrect"));1167 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1168 ASSERT_THAT_EXPECTED(Table, Succeeded());1169 1170 ASSERT_EQ((*Table)->Rows.size(), 8u);1171 EXPECT_EQ((*Table)->Rows[0].OpIndex, 1u);1172 EXPECT_EQ((*Table)->Rows[1].OpIndex, 0u); // DW_LNS_fixed_advance_pc.1173 EXPECT_EQ((*Table)->Rows[2].OpIndex, 6u);1174 EXPECT_EQ((*Table)->Rows[3].OpIndex, 0u); // DW_LNE_set_address.1175 EXPECT_EQ((*Table)->Rows[4].OpIndex, 12u);1176 EXPECT_EQ((*Table)->Rows[5].OpIndex, 12u);1177 EXPECT_EQ((*Table)->Rows[6].OpIndex, 0u); // row after DW_LNE_end_sequence.1178 EXPECT_EQ((*Table)->Rows[7].OpIndex, 0u);1179}1180 1181TEST_F(OpIndexFixture, MaxOpsZeroDwarf3) {1182 if (!setupGenerator(3, 4))1183 GTEST_SKIP();1184 1185 LineTable < = Gen->addLineTable();1186 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); // Just some opcode to advance.1187 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); //1188 createPrologue(LT, /*MaxOpsPerInst=*/0, /*MinInstLength=*/1);1189 generate();1190 1191 auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,1192 RecordRecoverable);1193 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());1194 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1195 ASSERT_THAT_EXPECTED(Table, Succeeded());1196}1197 1198TEST_F(OpIndexFixture, MaxOpsZeroDwarf4) {1199 if (!setupGenerator(4, 4))1200 GTEST_SKIP();1201 1202 LineTable < = Gen->addLineTable();1203 LT.addStandardOpcode(DW_LNS_const_add_pc, {}); // Just some opcode to advance.1204 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); //1205 createPrologue(LT, /*MaxOpsPerInst=*/0, /*MinInstLength=*/1);1206 generate();1207 1208 auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,1209 RecordRecoverable);1210 EXPECT_THAT_ERROR(1211 std::move(Recoverable),1212 FailedWithMessage(1213 "line table program at offset 0x00000000 contains a "1214 "DW_LNS_const_add_pc opcode at offset 0x0000002e, but "1215 "the prologue maximum_operations_per_instruction value "1216 "is 0, which is invalid. Assuming a value of 1 instead"));1217 EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());1218 ASSERT_THAT_EXPECTED(Table, Succeeded());1219}1220 1221struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>,1222 AdjustAddressFixtureBase {1223 void SetUp() override { std::tie(LineRange, IsErrorExpected) = GetParam(); }1224 1225 uint64_t editPrologue(LineTable <) override {1226 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();1227 Prologue.LineRange = LineRange;1228 LT.setPrologue(Prologue);1229 return Prologue.TotalLength + Prologue.sizeofTotalLength();1230 }1231 1232 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr,1233 uint64_t SpecialIncr,1234 uint64_t AdvanceIncr) override {1235 if (LineRange == 0)1236 return Base + AdvanceIncr;1237 return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr,1238 SpecialIncr, AdvanceIncr);1239 }1240 1241 uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override {1242 return LineRange != 01243 ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr)1244 : Base;1245 }1246 1247 uint8_t LineRange;1248};1249 1250TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) {1251 runTest(/*CheckAdvancePC=*/false,1252 "but the prologue line_range value is 0. The address and line will "1253 "not be adjusted");1254}1255 1256INSTANTIATE_TEST_SUITE_P(1257 LineRangeParams, LineRangeFixture,1258 Values(std::make_tuple(0, true), // Test zero value (error).1259 std::make_tuple(14, false))); // Test non-zero value (no error).1260 1261struct BadMinInstLenFixture : TestWithParam<std::tuple<uint8_t, bool>>,1262 AdjustAddressFixtureBase {1263 void SetUp() override {1264 std::tie(MinInstLength, IsErrorExpected) = GetParam();1265 }1266 1267 uint64_t editPrologue(LineTable <) override {1268 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();1269 Prologue.MinInstLength = MinInstLength;1270 LT.setPrologue(Prologue);1271 return Prologue.TotalLength + Prologue.sizeofTotalLength();1272 }1273 1274 uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr,1275 uint64_t SpecialIncr,1276 uint64_t AdvanceIncr) override {1277 return MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr(1278 Base, ConstIncr, SpecialIncr, AdvanceIncr)1279 : Base;1280 }1281 1282 uint8_t MinInstLength;1283};1284 1285TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) {1286 runTest(/*CheckAdvancePC=*/true,1287 "but the prologue minimum_instruction_length value is 0, which "1288 "prevents any address advancing");1289}1290 1291INSTANTIATE_TEST_SUITE_P(1292 BadMinInstLenParams, BadMinInstLenFixture,1293 Values(std::make_tuple(0, true), // Test zero value (error).1294 std::make_tuple(1, false))); // Test non-zero value (no error).1295 1296TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) {1297 if (!setupGenerator())1298 GTEST_SKIP();1299 1300 DWARFDebugLine::SectionParser Parser = setupParser();1301 1302 EXPECT_EQ(Parser.getOffset(), 0u);1303 ASSERT_FALSE(Parser.done());1304 1305 DWARFDebugLine::LineTable Parsed =1306 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1307 checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16);1308 EXPECT_EQ(Parsed.Sequences.size(), 1u);1309 EXPECT_EQ(Parser.getOffset(), 62u);1310 ASSERT_FALSE(Parser.done());1311 1312 DWARFDebugLine::LineTable Parsed2 =1313 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1314 checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16);1315 EXPECT_EQ(Parsed2.Sequences.size(), 1u);1316 EXPECT_EQ(Parser.getOffset(), 136u);1317 EXPECT_TRUE(Parser.done());1318 1319 EXPECT_FALSE(Recoverable);1320 EXPECT_FALSE(Unrecoverable);1321}1322 1323TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {1324 if (!setupGenerator())1325 GTEST_SKIP();1326 1327 DWARFDebugLine::SectionParser Parser = setupParser();1328 1329 EXPECT_EQ(Parser.getOffset(), 0u);1330 ASSERT_FALSE(Parser.done());1331 1332 Parser.skip(RecordRecoverable, RecordUnrecoverable);1333 EXPECT_EQ(Parser.getOffset(), 62u);1334 ASSERT_FALSE(Parser.done());1335 1336 Parser.skip(RecordRecoverable, RecordUnrecoverable);1337 EXPECT_EQ(Parser.getOffset(), 136u);1338 EXPECT_TRUE(Parser.done());1339 1340 EXPECT_FALSE(Recoverable);1341 EXPECT_FALSE(Unrecoverable);1342}1343 1344TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) {1345 if (!setupGenerator())1346 GTEST_SKIP();1347 1348 generate();1349 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1350 1351 EXPECT_TRUE(Parser.done());1352}1353 1354TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) {1355 if (!setupGenerator())1356 GTEST_SKIP();1357 1358 LineTable < = Gen->addLineTable();1359 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});1360 Gen->addLineTable();1361 generate();1362 1363 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1364 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1365 1366 EXPECT_EQ(Parser.getOffset(), 0u);1367 EXPECT_TRUE(Parser.done());1368 EXPECT_FALSE(Recoverable);1369 1370 EXPECT_THAT_ERROR(1371 std::move(Unrecoverable),1372 FailedWithMessage(1373 "parsing line table prologue at offset 0x00000000: unsupported "1374 "reserved unit length of value 0xfffffff0"));1375}1376 1377TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) {1378 if (!setupGenerator())1379 GTEST_SKIP();1380 1381 LineTable < = Gen->addLineTable();1382 LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});1383 Gen->addLineTable();1384 generate();1385 1386 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1387 Parser.skip(RecordRecoverable, RecordUnrecoverable);1388 1389 EXPECT_EQ(Parser.getOffset(), 0u);1390 EXPECT_TRUE(Parser.done());1391 EXPECT_FALSE(Recoverable);1392 1393 EXPECT_THAT_ERROR(1394 std::move(Unrecoverable),1395 FailedWithMessage(1396 "parsing line table prologue at offset 0x00000000: unsupported "1397 "reserved unit length of value 0xfffffff0"));1398}1399 1400TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) {1401 if (!setupGenerator())1402 GTEST_SKIP();1403 1404 LineTable < = Gen->addLineTable(DWARF32);1405 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});1406 LineTable <2 = Gen->addLineTable(DWARF32);1407 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});1408 generate();1409 1410 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1411 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1412 ASSERT_FALSE(Parser.done());1413 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1414 1415 EXPECT_TRUE(Parser.done());1416 EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());1417 1418 EXPECT_THAT_ERROR(1419 std::move(Unrecoverable),1420 FailedWithMessage("parsing line table prologue at offset 0x00000000: "1421 "unsupported version 0",1422 "parsing line table prologue at offset 0x00000006: "1423 "unsupported version 1"));1424}1425 1426TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) {1427 if (!setupGenerator())1428 GTEST_SKIP();1429 1430 LineTable < = Gen->addLineTable(DWARF32);1431 LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});1432 LineTable <2 = Gen->addLineTable(DWARF32);1433 LT2.addExtendedOpcode(9, DW_LNE_set_address,1434 {{0x1234567890abcdef, LineTable::Quad}});1435 LT2.addStandardOpcode(DW_LNS_copy, {});1436 LT2.addByte(0xbb);1437 generate();1438 1439 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1440 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1441 EXPECT_FALSE(Unrecoverable);1442 ASSERT_FALSE(Parser.done());1443 EXPECT_THAT_ERROR(std::move(Recoverable),1444 FailedWithMessage("unexpected line op length at offset "1445 "0x00000030 expected 0x42 found 0x01"));1446 1447 // Reset the error state so that it does not confuse the next set of checks.1448 Unrecoverable = Error::success();1449 Parser.parseNext(RecordRecoverable, RecordUnrecoverable);1450 1451 EXPECT_TRUE(Parser.done());1452 EXPECT_THAT_ERROR(std::move(Recoverable),1453 FailedWithMessage("last sequence in debug line table at "1454 "offset 0x00000031 is not terminated"));1455 EXPECT_FALSE(Unrecoverable);1456}1457 1458TEST_F(DebugLineBasicFixture,1459 ParserReportsPrologueErrorsInEachTableWhenSkipping) {1460 if (!setupGenerator())1461 GTEST_SKIP();1462 1463 LineTable < = Gen->addLineTable(DWARF32);1464 LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});1465 LineTable <2 = Gen->addLineTable(DWARF32);1466 LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});1467 generate();1468 1469 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1470 Parser.skip(RecordRecoverable, RecordUnrecoverable);1471 ASSERT_FALSE(Parser.done());1472 Parser.skip(RecordRecoverable, RecordUnrecoverable);1473 1474 EXPECT_TRUE(Parser.done());1475 EXPECT_FALSE(Recoverable);1476 1477 EXPECT_THAT_ERROR(1478 std::move(Unrecoverable),1479 FailedWithMessage("parsing line table prologue at offset 0x00000000: "1480 "unsupported version 0",1481 "parsing line table prologue at offset 0x00000006: "1482 "unsupported version 1"));1483}1484 1485TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) {1486 if (!setupGenerator())1487 GTEST_SKIP();1488 1489 LineTable < = Gen->addLineTable(DWARF32);1490 LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});1491 generate();1492 1493 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1494 Parser.skip(RecordRecoverable, RecordUnrecoverable);1495 1496 EXPECT_TRUE(Parser.done());1497 EXPECT_FALSE(Recoverable);1498 EXPECT_FALSE(Unrecoverable);1499}1500 1501#ifdef NO_SUPPORT_DEBUG_ADDR1502TEST_F(DebugLineBasicFixture, DISABLED_VerboseOutput) {1503#else1504TEST_F(DebugLineBasicFixture, VerboseOutput) {1505#endif1506 if (!setupGenerator(5))1507 GTEST_SKIP();1508 1509 LineTable < = Gen->addLineTable();1510 LT.addByte(0); // Extended opcode with zero length.1511 LT.addByte(0);1512 // Zero-value extended opcode.1513 LT.addExtendedOpcode(2, 0, {{1, LineTable::Byte}});1514 // Unknown extended opcode.1515 LT.addExtendedOpcode(2, 0x42, {{1, LineTable::Byte}});1516 LT.addExtendedOpcode(9, DW_LNE_set_address,1517 {{0x123456789abcdef, LineTable::Quad}});1518 LT.addExtendedOpcode(6, DW_LNE_define_file,1519 {{'a', LineTable::Byte},1520 {'\0', LineTable::Byte},1521 {2, LineTable::ULEB},1522 {3, LineTable::ULEB},1523 {4, LineTable::ULEB}});1524 LT.addExtendedOpcode(2, DW_LNE_set_discriminator, {{0x7f, LineTable::ULEB}});1525 LT.addStandardOpcode(DW_LNS_copy, {});1526 LT.addStandardOpcode(DW_LNS_advance_pc, {{11, LineTable::ULEB}});1527 LT.addStandardOpcode(DW_LNS_advance_line, {{22, LineTable::SLEB}});1528 LT.addStandardOpcode(DW_LNS_set_file, {{33, LineTable::ULEB}});1529 LT.addStandardOpcode(DW_LNS_set_column, {{44, LineTable::ULEB}});1530 LT.addStandardOpcode(DW_LNS_negate_stmt, {});1531 LT.addStandardOpcode(DW_LNS_set_basic_block, {});1532 LT.addStandardOpcode(DW_LNS_const_add_pc, {});1533 LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{55, LineTable::Half}});1534 LT.addStandardOpcode(DW_LNS_set_prologue_end, {});1535 LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {});1536 LT.addStandardOpcode(DW_LNS_set_isa, {{66, LineTable::ULEB}});1537 // Add unknown standard opcode with operands.1538 LT.addStandardOpcode(1539 0xd, {{1, LineTable::ULEB}, {0x123456789abcdef, LineTable::ULEB}});1540 // Add unknown standard opcode without operands.1541 LT.addStandardOpcode(0xe, {});1542 LT.addByte(0xff); // Special opcode.1543 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});1544 1545 // Adjust the prologue to account for the extra standard opcode.1546 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();1547 Prologue.TotalLength += 2;1548 Prologue.PrologueLength += 2;1549 Prologue.OpcodeBase += 2;1550 Prologue.StandardOpcodeLengths.push_back(2);1551 Prologue.StandardOpcodeLengths.push_back(0);1552 LT.setPrologue(Prologue);1553 1554 generate();1555 1556 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1557 std::string Output;1558 raw_string_ostream OS(Output);1559 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS,1560 /*Verbose=*/true);1561 StringRef OutputRef(Output);1562 1563 size_t Pos = 0;1564 auto NextLine = [&Pos, &OutputRef]() {1565 size_t EOL = OutputRef.find_first_of('\n', Pos);1566 StringRef Line = OutputRef.substr(Pos, EOL - Pos);1567 Pos = EOL + 1;1568 return Line;1569 };1570 EXPECT_EQ(NextLine(), "Line table prologue:");1571 EXPECT_EQ(NextLine(), " total_length: 0x00000078");1572 EXPECT_EQ(NextLine(), " format: DWARF32");1573 EXPECT_EQ(NextLine(), " version: 5");1574 EXPECT_EQ(NextLine(), " address_size: 8");1575 EXPECT_EQ(NextLine(), " seg_select_size: 0");1576 EXPECT_EQ(NextLine(), " prologue_length: 0x0000002c");1577 EXPECT_EQ(NextLine(), " min_inst_length: 1");1578 EXPECT_EQ(NextLine(), "max_ops_per_inst: 1");1579 EXPECT_EQ(NextLine(), " default_is_stmt: 1");1580 EXPECT_EQ(NextLine(), " line_base: -5");1581 EXPECT_EQ(NextLine(), " line_range: 14");1582 EXPECT_EQ(NextLine(), " opcode_base: 15");1583 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_copy] = 0");1584 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_pc] = 1");1585 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_line] = 1");1586 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_file] = 1");1587 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_column] = 1");1588 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_negate_stmt] = 0");1589 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_basic_block] = 0");1590 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_const_add_pc] = 0");1591 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1");1592 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_prologue_end] = 0");1593 EXPECT_EQ(NextLine(),1594 "standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0");1595 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_isa] = 1");1596 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_d] = 2");1597 EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_e] = 0");1598 EXPECT_EQ(NextLine(), "include_directories[ 0] = \"a dir\"");1599 EXPECT_EQ(NextLine(), "file_names[ 0]:");1600 EXPECT_EQ(NextLine(), " name: \"a file\"");1601 EXPECT_EQ(NextLine(), " dir_index: 0");1602 EXPECT_EQ(NextLine(), "");1603 EXPECT_EQ(NextLine(), " Address Line Column File "1604 "ISA Discriminator OpIndex Flags");1605 EXPECT_EQ(NextLine(), " ------------------ ------ ------ ------ "1606 "--- ------------- ------- -------------");1607 EXPECT_EQ(NextLine(),1608 "0x00000038: 00 Badly formed extended line op (length 0)");1609 EXPECT_EQ(NextLine(),1610 "0x0000003a: 00 Unrecognized extended op 0x00 length 2");1611 EXPECT_EQ(NextLine(),1612 "0x0000003e: 00 Unrecognized extended op 0x42 length 2");1613 EXPECT_EQ(NextLine(),1614 "0x00000042: 00 DW_LNE_set_address (0x0123456789abcdef)");1615 EXPECT_EQ(NextLine(), "0x0000004d: 00 DW_LNE_define_file (a, dir=2, "1616 "mod_time=(0x0000000000000003), length=4)");1617 EXPECT_EQ(NextLine(), "0x00000055: 00 DW_LNE_set_discriminator (127)");1618 EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy");1619 EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 "1620 "0 127 0 is_stmt");1621 EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (addr += 11, "1622 "op-index += 0)");1623 EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)");1624 EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)");1625 EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)");1626 EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt");1627 EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block");1628 EXPECT_EQ(NextLine(),1629 "0x00000064: 08 DW_LNS_const_add_pc (addr += 0x0000000000000011, "1630 "op-index += 0)");1631 EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (addr += 0x0037"1632 ", op-index = 0)");1633 EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end");1634 EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin");1635 EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)");1636 EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode "1637 "(operands: 0x0000000000000001, 0x0123456789abcdef)");1638 EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode");1639 EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3, "1640 "op-index += 0");1641 EXPECT_EQ(NextLine(),1642 " 0x0123456789abce53 20 44 33 66 "1643 " 0 0 basic_block prologue_end epilogue_begin");1644 EXPECT_EQ(NextLine(), "0x00000079: 00 DW_LNE_end_sequence");1645 EXPECT_EQ(NextLine(), " 0x0123456789abce53 20 44 33 "1646 "66 0 0 end_sequence");1647 EXPECT_EQ(NextLine(), "");1648 EXPECT_EQ(Output.size(), Pos);1649}1650 1651struct TruncatedPrologueFixture1652 : public TestWithParam<1653 std::tuple<uint64_t, uint64_t, uint16_t, DwarfFormat, StringRef>>,1654 public CommonFixture {1655 void SetUp() override {1656 std::tie(Length, ExpectedOffset, Version, Format, ExpectedErr) = GetParam();1657 }1658 1659 uint64_t Length;1660 uint64_t ExpectedOffset;1661 uint16_t Version;1662 DwarfFormat Format;1663 StringRef ExpectedErr;1664};1665 1666#ifdef NO_SUPPORT_DEBUG_ADDR1667TEST_P(TruncatedPrologueFixture, DISABLED_ErrorForTruncatedPrologue) {1668#else1669TEST_P(TruncatedPrologueFixture, ErrorForTruncatedPrologue) {1670#endif1671 if (!setupGenerator(Version))1672 GTEST_SKIP();1673 1674 LineTable &Padding = Gen->addLineTable();1675 // Add some padding to show that a non-zero offset is handled correctly.1676 Padding.setCustomPrologue({{0, LineTable::Byte}});1677 1678 // Add a table with only two standard opcodes - we don't need to test the full1679 // set.1680 LineTable &Table = Gen->addLineTable(Format);1681 DWARFDebugLine::Prologue InputPrologue = Table.createBasicPrologue();1682 InputPrologue.OpcodeBase = 3;1683 InputPrologue.StandardOpcodeLengths.resize(2);1684 Table.setPrologue(InputPrologue);1685 1686 generate();1687 // Truncate the data extractor to the specified length.1688 LineData = DWARFDataExtractor(LineData, Length);1689 1690 DWARFDebugLine::Prologue Prologue;1691 uint64_t Offset = 1;1692 Error Err = Prologue.parse(LineData, &Offset, RecordRecoverable, *Context);1693 1694 EXPECT_THAT_ERROR(std::move(Err), FailedWithMessage(ExpectedErr.str()));1695 EXPECT_EQ(Offset, ExpectedOffset);1696}1697 1698INSTANTIATE_TEST_SUITE_P(1699 TruncatedPrologueParams, TruncatedPrologueFixture,1700 Values(1701 // Truncated length:1702 std::make_tuple(1703 4, 1, 4, DWARF32,1704 "parsing line table prologue at offset 0x00000001: unexpected end "1705 "of data at offset 0x4 while reading [0x1, 0x5)"),1706 std::make_tuple(1707 4, 1, 4, DWARF64,1708 "parsing line table prologue at offset 0x00000001: unexpected end "1709 "of data at offset 0x4 while reading [0x1, 0x5)"),1710 std::make_tuple(1711 0xc, 1, 4, DWARF64,1712 "parsing line table prologue at offset 0x00000001: unexpected end "1713 "of data at offset 0xc while reading [0x5, 0xd)"),1714 // Truncated version:1715 std::make_tuple(1716 6, 5, 4, DWARF32,1717 "parsing line table prologue at offset 0x00000001: unexpected end "1718 "of data at offset 0x6 while reading [0x5, 0x7)"),1719 // Truncated address size:1720 std::make_tuple(1721 7, 7, 5, DWARF32,1722 "parsing line table prologue at offset 0x00000001: unexpected end "1723 "of data at offset 0x7 while reading [0x7, 0x8)"),1724 // Truncated segment selector size:1725 std::make_tuple(1726 8, 8, 5, DWARF32,1727 "parsing line table prologue at offset 0x00000001: unexpected end "1728 "of data at offset 0x8 while reading [0x8, 0x9)"),1729 // Truncated prologue length:1730 std::make_tuple(1731 0xa, 7, 4, DWARF32,1732 "parsing line table prologue at offset 0x00000001: unexpected end "1733 "of data at offset 0xa while reading [0x7, 0xb)"),1734 std::make_tuple(1735 0x16, 0xf, 4, DWARF64,1736 "parsing line table prologue at offset 0x00000001: unexpected end "1737 "of data at offset 0x16 while reading [0xf, 0x17)"),1738 // Truncated min instruction length:1739 std::make_tuple(1740 0xb, 0xb, 4, DWARF32,1741 "parsing line table prologue at offset 0x00000001: unexpected end "1742 "of data at offset 0xb while reading [0xb, 0xc)"),1743 // Truncated max ops per inst:1744 std::make_tuple(1745 0xc, 0xc, 4, DWARF32,1746 "parsing line table prologue at offset 0x00000001: unexpected end "1747 "of data at offset 0xc while reading [0xc, 0xd)"),1748 // Truncated default is stmt:1749 std::make_tuple(1750 0xd, 0xd, 4, DWARF32,1751 "parsing line table prologue at offset 0x00000001: unexpected end "1752 "of data at offset 0xd while reading [0xd, 0xe)"),1753 // Truncated line base:1754 std::make_tuple(1755 0xe, 0xe, 4, DWARF32,1756 "parsing line table prologue at offset 0x00000001: unexpected end "1757 "of data at offset 0xe while reading [0xe, 0xf)"),1758 // Truncated line range:1759 std::make_tuple(1760 0xf, 0xf, 4, DWARF32,1761 "parsing line table prologue at offset 0x00000001: unexpected end "1762 "of data at offset 0xf while reading [0xf, 0x10)"),1763 // Truncated opcode base:1764 std::make_tuple(1765 0x10, 0x10, 4, DWARF32,1766 "parsing line table prologue at offset 0x00000001: unexpected end "1767 "of data at offset 0x10 while reading [0x10, 0x11)"),1768 // Truncated first standard opcode:1769 std::make_tuple(1770 0x11, 0x11, 4, DWARF32,1771 "parsing line table prologue at offset 0x00000001: unexpected end "1772 "of data at offset 0x11 while reading [0x11, 0x12)"),1773 // Truncated second standard opcode:1774 std::make_tuple(1775 0x12, 0x12, 4, DWARF32,1776 "parsing line table prologue at offset 0x00000001: unexpected end "1777 "of data at offset 0x12 while reading [0x12, 0x13)")));1778 1779using ValueAndLengths = std::vector<LineTable::ValueAndLength>;1780 1781struct TruncatedOpcodeFixtureBase : public CommonFixture {1782 LineTable &setupTable() {1783 LineTable < = Gen->addLineTable();1784 1785 // Creating the prologue before adding any opcodes ensures that the unit1786 // length does not include the table body.1787 DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();1788 1789 // Add an unrecognised standard opcode, and adjust prologue properties1790 // accordingly.1791 Prologue.TotalLength += BodyLength + 1;1792 ++Prologue.PrologueLength;1793 ++Prologue.OpcodeBase;1794 Prologue.StandardOpcodeLengths.push_back(2);1795 LT.setPrologue(Prologue);1796 1797 return LT;1798 }1799 1800 void runTest(uint8_t OpcodeValue) {1801 generate();1802 DWARFDebugLine::SectionParser Parser(LineData, *Context, Units);1803 std::string Output;1804 raw_string_ostream OS(Output);1805 Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS,1806 /*Verbose=*/true);1807 1808 std::string LinePrefix =1809 ("0x0000002f: 0" + Twine::utohexstr(OpcodeValue) + " ").str();1810 StringRef OutputRef(Output);1811 StringRef OutputToCheck = OutputRef.split(LinePrefix).second;1812 // Each extended opcode ends with a new line and then the table ends with an1813 // additional blank line.1814 EXPECT_EQ((ExpectedOutput + "\n\n").str(), OutputToCheck);1815 }1816 1817 uint64_t BodyLength;1818 uint8_t Opcode;1819 ValueAndLengths Operands;1820 StringRef ExpectedOutput;1821 StringRef ExpectedErr;1822};1823 1824struct TruncatedStandardOpcodeFixture1825 : public TestWithParam<1826 std::tuple<uint64_t, uint8_t, ValueAndLengths, StringRef, StringRef>>,1827 public TruncatedOpcodeFixtureBase {1828 void SetUp() override {1829 std::tie(BodyLength, Opcode, Operands, ExpectedOutput, ExpectedErr) =1830 GetParam();1831 }1832};1833 1834struct TruncatedExtendedOpcodeFixture1835 : public TestWithParam<std::tuple<uint64_t, uint64_t, uint8_t,1836 ValueAndLengths, StringRef, StringRef>>,1837 public TruncatedOpcodeFixtureBase {1838 void SetUp() override {1839 std::tie(BodyLength, OpcodeLength, Opcode, Operands, ExpectedOutput,1840 ExpectedErr) = GetParam();1841 }1842 1843 uint64_t OpcodeLength;1844};1845 1846TEST_P(TruncatedExtendedOpcodeFixture, ErrorForTruncatedExtendedOpcode) {1847 if (!setupGenerator())1848 GTEST_SKIP();1849 LineTable < = setupTable();1850 LT.addExtendedOpcode(OpcodeLength, Opcode, Operands);1851 runTest(0);1852 EXPECT_THAT_ERROR(std::move(Recoverable),1853 FailedWithMessage(ExpectedErr.str()));1854}1855 1856INSTANTIATE_TEST_SUITE_P(1857 TruncatedExtendedOpcodeParams, TruncatedExtendedOpcodeFixture,1858 Values(1859 // Truncated length:1860 std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "",1861 "unable to decode LEB128 at offset 0x00000030: "1862 "malformed uleb128, extends past end"),1863 // Truncated opcode:1864 std::make_tuple(1865 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "",1866 "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"),1867 // Truncated operands:1868 std::make_tuple(1869 3, 9, DW_LNE_set_address,1870 ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}},1871 "DW_LNE_set_address",1872 "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"),1873 std::make_tuple(1874 10, 9, DW_LNE_set_address,1875 ValueAndLengths{{0x1234567878563412, LineTable::Quad}},1876 "DW_LNE_set_address (<parsing error> 12 34 56 78 78 56 34)",1877 "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"),1878 std::make_tuple(3, 6, DW_LNE_define_file,1879 ValueAndLengths{{'a', LineTable::Byte},1880 {'\0', LineTable::Byte},1881 {1, LineTable::ULEB},1882 {1, LineTable::ULEB},1883 {1, LineTable::ULEB}},1884 "DW_LNE_define_file",1885 "no null terminated string at offset 0x32"),1886 std::make_tuple(5, 6, DW_LNE_define_file,1887 ValueAndLengths{{'a', LineTable::Byte},1888 {'\0', LineTable::Byte},1889 {1, LineTable::ULEB},1890 {1, LineTable::ULEB},1891 {1, LineTable::ULEB}},1892 "DW_LNE_define_file (<parsing error> 61 00)",1893 "unable to decode LEB128 at offset 0x00000034: "1894 "malformed uleb128, extends past end"),1895 std::make_tuple(6, 6, DW_LNE_define_file,1896 ValueAndLengths{{'a', LineTable::Byte},1897 {'\0', LineTable::Byte},1898 {1, LineTable::ULEB},1899 {1, LineTable::ULEB},1900 {1, LineTable::ULEB}},1901 "DW_LNE_define_file (<parsing error> 61 00 01)",1902 "unable to decode LEB128 at offset 0x00000035: "1903 "malformed uleb128, extends past end"),1904 std::make_tuple(7, 6, DW_LNE_define_file,1905 ValueAndLengths{{'a', LineTable::Byte},1906 {'\0', LineTable::Byte},1907 {1, LineTable::ULEB},1908 {1, LineTable::ULEB},1909 {1, LineTable::ULEB}},1910 "DW_LNE_define_file (<parsing error> 61 00 01 01)",1911 "unable to decode LEB128 at offset 0x00000036: "1912 "malformed uleb128, extends past end"),1913 std::make_tuple(3, 2, DW_LNE_set_discriminator,1914 ValueAndLengths{{1, LineTable::ULEB}},1915 "DW_LNE_set_discriminator",1916 "unable to decode LEB128 at offset 0x00000032: "1917 "malformed uleb128, extends past end"),1918 std::make_tuple(1919 6, 5, /*Unknown=*/0x7f,1920 ValueAndLengths{{0x12343412, LineTable::Long}},1921 "Unrecognized extended op 0x7f length 5 (<parsing error> 12 34 34)",1922 "unexpected end of data at offset 0x35 while reading [0x32, "1923 "0x36)")));1924 1925TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) {1926 if (!setupGenerator())1927 GTEST_SKIP();1928 LineTable < = setupTable();1929 LT.addStandardOpcode(Opcode, Operands);1930 runTest(Opcode);1931 EXPECT_THAT_ERROR(std::move(Unrecoverable),1932 FailedWithMessage(ExpectedErr.str()));1933}1934 1935INSTANTIATE_TEST_SUITE_P(1936 TruncatedStandardOpcodeParams, TruncatedStandardOpcodeFixture,1937 Values(1938 std::make_tuple(2, DW_LNS_advance_pc,1939 ValueAndLengths{{0x100, LineTable::ULEB}},1940 "DW_LNS_advance_pc",1941 "unable to decode LEB128 at offset 0x00000030: "1942 "malformed uleb128, extends past end"),1943 std::make_tuple(2, DW_LNS_advance_line,1944 ValueAndLengths{{0x200, LineTable::SLEB}},1945 "DW_LNS_advance_line",1946 "unable to decode LEB128 at offset 0x00000030: "1947 "malformed sleb128, extends past end"),1948 std::make_tuple(2, DW_LNS_set_file,1949 ValueAndLengths{{0x300, LineTable::ULEB}},1950 "DW_LNS_set_file",1951 "unable to decode LEB128 at offset 0x00000030: "1952 "malformed uleb128, extends past end"),1953 std::make_tuple(2, DW_LNS_set_column,1954 ValueAndLengths{{0x400, LineTable::ULEB}},1955 "DW_LNS_set_column",1956 "unable to decode LEB128 at offset 0x00000030: "1957 "malformed uleb128, extends past end"),1958 std::make_tuple(1959 2, DW_LNS_fixed_advance_pc,1960 ValueAndLengths{{0x500, LineTable::Half}},1961 "DW_LNS_fixed_advance_pc",1962 "unexpected end of data at offset 0x31 while reading [0x30, 0x32)"),1963 std::make_tuple(2, DW_LNS_set_isa,1964 ValueAndLengths{{0x600, LineTable::ULEB}},1965 "DW_LNS_set_isa",1966 "unable to decode LEB128 at offset 0x00000030: "1967 "malformed uleb128, extends past end"),1968 std::make_tuple(2, 0xd,1969 ValueAndLengths{{0x700, LineTable::ULEB},1970 {0x800, LineTable::ULEB}},1971 "Unrecognized standard opcode",1972 "unable to decode LEB128 at offset 0x00000030: "1973 "malformed uleb128, extends past end"),1974 std::make_tuple(1975 4, 0xd,1976 ValueAndLengths{{0x900, LineTable::ULEB}, {0xa00, LineTable::ULEB}},1977 "Unrecognized standard opcode (operands: 0x0000000000000900)",1978 "unable to decode LEB128 at offset 0x00000032: "1979 "malformed uleb128, extends past end")));1980 1981#ifdef NO_SUPPORT_DEBUG_ADDR1982TEST_F(DebugLineBasicFixture, DISABLED_PrintPathsProperly) {1983#else1984TEST_F(DebugLineBasicFixture, PrintPathsProperly) {1985#endif1986 if (!setupGenerator(5))1987 GTEST_SKIP();1988 1989 LineTable < = Gen->addLineTable();1990 DWARFDebugLine::Prologue P = LT.createBasicPrologue();1991 P.IncludeDirectories.push_back(1992 DWARFFormValue::createFromPValue(DW_FORM_string, "b dir"));1993 P.FileNames.push_back(DWARFDebugLine::FileNameEntry());1994 P.FileNames.back().Name =1995 DWARFFormValue::createFromPValue(DW_FORM_string, "b file");1996 P.FileNames.back().DirIdx = 1;1997 P.TotalLength += 14;1998 P.PrologueLength += 14;1999 LT.setPrologue(P);2000 generate();2001 2002 auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,2003 nullptr, RecordRecoverable);2004 EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());2005 std::string Result;2006 // DWARF 5 stores the compilation directory in two places: the Compilation2007 // Unit and the directory table entry 0, and implementations are free to use2008 // one or the other. This copy serves as the one stored in the CU.2009 StringRef CompDir = "a dir";2010 EXPECT_FALSE(2011 (*ExpectedLineTable)2012 ->Prologue.getFileNameByIndex(2013 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result));2014 EXPECT_TRUE((*ExpectedLineTable)2015 ->Prologue.getFileNameByIndex(2016 1, CompDir,2017 DILineInfoSpecifier::FileLineInfoKind::RawValue, Result));2018 EXPECT_TRUE((*ExpectedLineTable)2019 ->Prologue.getFileNameByIndex(2020 1, CompDir,2021 DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly,2022 Result));2023 EXPECT_STREQ(Result.c_str(), "b file");2024 EXPECT_TRUE((*ExpectedLineTable)2025 ->Prologue.getFileNameByIndex(2026 1, CompDir,2027 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath,2028 Result));2029 EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file"));2030 EXPECT_TRUE((*ExpectedLineTable)2031 ->Prologue.getFileNameByIndex(2032 1, CompDir,2033 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,2034 Result));2035 EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file"));2036}2037 2038/// Test that lookupAddressRange correctly filters rows based on2039/// a statement-sequence offset (simulating DW_AT_LLVM_stmt_sequence).2040///2041/// This test verifies that:2042/// 1. When a statement-sequence offset is provided, lookupAddressRange2043/// only returns rows from the sequence starting at that offset.2044/// 2. When an invalid statement-sequence offset is provided, no rows2045/// are returned.2046/// 3. When no statement-sequence offset is provided, all matching rows2047/// in the table are returned.2048///2049/// We build a line table with two sequences at the same address range2050/// but different line numbers. Then we try lookups with various statement-2051/// sequence offsets to check the filtering logic.2052TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) {2053 if (!setupGenerator())2054 GTEST_SKIP();2055 2056 // Create a line table that has two sequences covering [0x1000, 0x1004).2057 // Each sequence has two rows: addresses at 0x1000 and 0x1004, but2058 // they differ by line numbers (100 vs. 200, etc.).2059 //2060 // We'll pretend the first sequence starts at offset 0x2e in the line table,2061 // the second at 0x42, and we'll also test an invalid offset 0x66.2062 2063 LineTable < = Gen->addLineTable();2064 2065 // First sequence at offset 0x2e: addresses 0x1000(Ln=100), 0x1004(Ln=101)2066 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}});2067 LT.addStandardOpcode(DW_LNS_set_prologue_end, {});2068 // Advance the line register by 99 (so line=100) and copy.2069 LT.addStandardOpcode(DW_LNS_advance_line, {{99, LineTable::SLEB}});2070 LT.addStandardOpcode(DW_LNS_copy, {});2071 // 0x4b is a special opcode: address += 4, line += 1 (so line=101).2072 LT.addByte(0x4b);2073 // End this sequence.2074 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});2075 2076 // Second sequence at offset 0x42: addresses 0x1000(Ln=200), 0x1004(Ln=201)2077 LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}});2078 LT.addStandardOpcode(DW_LNS_set_prologue_end, {});2079 LT.addStandardOpcode(DW_LNS_advance_line, {{199, LineTable::SLEB}});2080 LT.addStandardOpcode(DW_LNS_copy, {});2081 // 0x4b again: address += 4, line += 1 (so line=201).2082 LT.addByte(0x4b);2083 // End this second sequence.2084 LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});2085 2086 // Generate the DWARF data.2087 generate();2088 2089 // Parse the line table.2090 auto ExpectedLineTable =2091 Line.getOrParseLineTable(LineData, /*Offset=*/0, *Context,2092 /*DwarfUnit=*/nullptr, RecordRecoverable);2093 ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());2094 const auto *Table = *ExpectedLineTable;2095 2096 // The table should have two sequences, each starting at our chosen offsets.2097 ASSERT_EQ(Table->Sequences.size(), 2u);2098 2099 // 1) Try looking up with an invalid offset (simulating an invalid2100 // DW_AT_LLVM_stmt_sequence). We expect no rows.2101 {2102 std::vector<uint32_t> Rows;2103 bool Found = Table->lookupAddressRange(2104 {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,2105 /*StmtSequenceOffset=*/0x66); // invalid offset2106 EXPECT_FALSE(Found);2107 EXPECT_TRUE(Rows.empty());2108 }2109 2110 // 2) Look up using the offset 0x2e (our first sequence). We expect2111 // to get the rows from that sequence only (which for 0x1000 is row #0).2112 {2113 std::vector<uint32_t> Rows;2114 bool Found = Table->lookupAddressRange(2115 {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,2116 /*StmtSequenceOffset=*/0x2e);2117 EXPECT_TRUE(Found);2118 ASSERT_EQ(Rows.size(), 1u);2119 // The first sequence's first row is index 0.2120 EXPECT_EQ(Rows[0], 0u);2121 }2122 2123 // 3) Look up using the offset 0x42 (second sequence). For address 0x10002124 // in that second sequence, we should see row #2.2125 {2126 std::vector<uint32_t> Rows;2127 bool Found = Table->lookupAddressRange(2128 {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,2129 /*StmtSequenceOffset=*/0x42);2130 EXPECT_TRUE(Found);2131 ASSERT_EQ(Rows.size(), 1u);2132 // The second sequence's first row is index 2 in the table.2133 EXPECT_EQ(Rows[0], 3u);2134 }2135 2136 // 4) Look up with no statement-sequence offset specified.2137 // We should get rows from both sequences for address 0x1000.2138 {2139 std::vector<uint32_t> Rows;2140 bool Found = Table->lookupAddressRange(2141 {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,2142 std::nullopt /* no filter */);2143 EXPECT_TRUE(Found);2144 // The first sequence's row is #0, second's row is #2, so both should2145 // appear.2146 ASSERT_EQ(Rows.size(), 2u);2147 EXPECT_EQ(Rows[0], 0u);2148 EXPECT_EQ(Rows[1], 3u);2149 }2150}2151} // end anonymous namespace2152