166702629SJames Henderson //===- DWARFDebugLineTest.cpp ---------------------------------------------===// 266702629SJames Henderson // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 666702629SJames Henderson // 766702629SJames Henderson //===----------------------------------------------------------------------===// 866702629SJames Henderson 966702629SJames Henderson #include "DwarfGenerator.h" 1066702629SJames Henderson #include "DwarfUtils.h" 1166702629SJames Henderson #include "llvm/DebugInfo/DWARF/DWARFContext.h" 1266702629SJames Henderson #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 1366702629SJames Henderson #include "llvm/Object/ObjectFile.h" 1466702629SJames Henderson #include "llvm/Testing/Support/Error.h" 1566702629SJames Henderson #include "gtest/gtest.h" 1666702629SJames Henderson 1766702629SJames Henderson using namespace llvm; 1866702629SJames Henderson using namespace dwarf; 19a3acf99eSJames Henderson using namespace dwarfgen; 2066702629SJames Henderson using namespace object; 2166702629SJames Henderson using namespace utils; 22a3acf99eSJames Henderson using namespace testing; 2366702629SJames Henderson 2466702629SJames Henderson namespace { 25a3acf99eSJames Henderson struct CommonFixture { 26a3acf99eSJames Henderson CommonFixture() 27004b729eSJames Henderson : LineData("", true, 0), Recoverable(Error::success()), 28004b729eSJames Henderson RecordRecoverable(std::bind(&CommonFixture::recordRecoverable, this, 29a3acf99eSJames Henderson std::placeholders::_1)), 30004b729eSJames Henderson Unrecoverable(Error::success()), 31004b729eSJames Henderson RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this, 32a3acf99eSJames Henderson std::placeholders::_1)){}; 3366702629SJames Henderson 34004b729eSJames Henderson ~CommonFixture() { 35004b729eSJames Henderson EXPECT_FALSE(Recoverable); 36004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 37004b729eSJames Henderson } 38a3acf99eSJames Henderson 39a3acf99eSJames Henderson bool setupGenerator(uint16_t Version = 4) { 40552fda83SJason Liu Triple T = getDefaultTargetTripleForAddrSize(8); 4166702629SJames Henderson if (!isConfigurationSupported(T)) 4266702629SJames Henderson return false; 43a3acf99eSJames Henderson auto ExpectedGenerator = Generator::create(T, Version); 4466702629SJames Henderson if (ExpectedGenerator) 45a3acf99eSJames Henderson Gen.reset(ExpectedGenerator->release()); 4666702629SJames Henderson return true; 4766702629SJames Henderson } 4866702629SJames Henderson 49a3acf99eSJames Henderson void generate() { 50a3acf99eSJames Henderson Context = createContext(); 51a3acf99eSJames Henderson assert(Context != nullptr && "test state is not valid"); 52a3acf99eSJames Henderson const DWARFObject &Obj = Context->getDWARFObj(); 53552fda83SJason Liu LineData = DWARFDataExtractor( 54552fda83SJason Liu Obj, Obj.getLineSection(), 55552fda83SJason Liu getDefaultTargetTripleForAddrSize(8).isLittleEndian(), 8); 56a3acf99eSJames Henderson } 57a3acf99eSJames Henderson 5866702629SJames Henderson std::unique_ptr<DWARFContext> createContext() { 59a3acf99eSJames Henderson if (!Gen) 6066702629SJames Henderson return nullptr; 61a3acf99eSJames Henderson StringRef FileBytes = Gen->generate(); 6266702629SJames Henderson MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 6366702629SJames Henderson auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 6466702629SJames Henderson if (Obj) 6566702629SJames Henderson return DWARFContext::create(**Obj); 6666702629SJames Henderson return nullptr; 6766702629SJames Henderson } 6866702629SJames Henderson 69a3acf99eSJames Henderson DWARFDebugLine::SectionParser setupParser() { 70a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 71a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 72a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 73a3acf99eSJames Henderson LT.addByte(0xaa); 74a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 75a3acf99eSJames Henderson 76a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF64); 77a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 78a3acf99eSJames Henderson {{0x11223344, LineTable::Quad}}); 79a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 80a3acf99eSJames Henderson LT2.addByte(0xbb); 81a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 82a3acf99eSJames Henderson 83a3acf99eSJames Henderson generate(); 84a3acf99eSJames Henderson 85a3acf99eSJames Henderson return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs); 86a3acf99eSJames Henderson } 87a3acf99eSJames Henderson 88004b729eSJames Henderson void recordRecoverable(Error Err) { 89004b729eSJames Henderson Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); 90004b729eSJames Henderson } 91004b729eSJames Henderson void recordUnrecoverable(Error Err) { 92004b729eSJames Henderson Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); 93a3acf99eSJames Henderson } 94a3acf99eSJames Henderson 95a3acf99eSJames Henderson void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) { 96a3acf99eSJames Henderson ASSERT_TRUE(Err.operator bool()); 97a3acf99eSJames Henderson size_t WhichMsg = 0; 98a3acf99eSJames Henderson Error Remaining = 99a3acf99eSJames Henderson handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) { 100a3acf99eSJames Henderson ASSERT_LT(WhichMsg, ExpectedMsgs.size()); 101a3acf99eSJames Henderson // Use .str(), because googletest doesn't visualise a StringRef 102a3acf99eSJames Henderson // properly. 103a3acf99eSJames Henderson EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str()); 104a3acf99eSJames Henderson }); 105a3acf99eSJames Henderson EXPECT_EQ(WhichMsg, ExpectedMsgs.size()); 106a3acf99eSJames Henderson EXPECT_FALSE(Remaining); 107a3acf99eSJames Henderson } 108a3acf99eSJames Henderson 109a3acf99eSJames Henderson void checkError(StringRef ExpectedMsg, Error Err) { 110a3acf99eSJames Henderson checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err)); 111a3acf99eSJames Henderson } 112a3acf99eSJames Henderson 11389b11843SJames Henderson void checkGetOrParseLineTableEmitsFatalError(StringRef ExpectedMsg, 114a3acf99eSJames Henderson uint64_t Offset = 0) { 115a3acf99eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable( 116004b729eSJames Henderson LineData, Offset, *Context, nullptr, RecordRecoverable); 117a3acf99eSJames Henderson EXPECT_FALSE(ExpectedLineTable); 118004b729eSJames Henderson EXPECT_FALSE(Recoverable); 119a3acf99eSJames Henderson 120a3acf99eSJames Henderson checkError(ExpectedMsg, ExpectedLineTable.takeError()); 121a3acf99eSJames Henderson } 122a3acf99eSJames Henderson 12389b11843SJames Henderson void checkGetOrParseLineTableEmitsFatalError(ArrayRef<StringRef> ExpectedMsgs, 1240e7ba06eSJonas Devlieghere uint64_t Offset = 0) { 1250e7ba06eSJonas Devlieghere auto ExpectedLineTable = Line.getOrParseLineTable( 1260e7ba06eSJonas Devlieghere LineData, Offset, *Context, nullptr, RecordRecoverable); 1270e7ba06eSJonas Devlieghere EXPECT_FALSE(ExpectedLineTable); 1280e7ba06eSJonas Devlieghere EXPECT_FALSE(Recoverable); 1290e7ba06eSJonas Devlieghere 1300e7ba06eSJonas Devlieghere checkError(ExpectedMsgs, ExpectedLineTable.takeError()); 1310e7ba06eSJonas Devlieghere } 1320e7ba06eSJonas Devlieghere 133a3acf99eSJames Henderson std::unique_ptr<Generator> Gen; 134a3acf99eSJames Henderson std::unique_ptr<DWARFContext> Context; 135a3acf99eSJames Henderson DWARFDataExtractor LineData; 136a3acf99eSJames Henderson DWARFDebugLine Line; 137004b729eSJames Henderson Error Recoverable; 138004b729eSJames Henderson std::function<void(Error)> RecordRecoverable; 139004b729eSJames Henderson Error Unrecoverable; 140004b729eSJames Henderson std::function<void(Error)> RecordUnrecoverable; 141a3acf99eSJames Henderson 142143eaeabSPaul Robinson SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs; 1437f330944SPaul Robinson SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs; 14466702629SJames Henderson }; 14566702629SJames Henderson 146a3acf99eSJames Henderson // Fixtures must derive from "Test", but parameterised fixtures from 147a3acf99eSJames Henderson // "TestWithParam". It does not seem possible to inherit from both, so we share 148a3acf99eSJames Henderson // the common state in a separate class, inherited by the two fixture classes. 149a3acf99eSJames Henderson struct DebugLineBasicFixture : public Test, public CommonFixture {}; 150a3acf99eSJames Henderson 151a3acf99eSJames Henderson struct DebugLineParameterisedFixture 152a3acf99eSJames Henderson : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 153a3acf99eSJames Henderson public CommonFixture { 154a3acf99eSJames Henderson void SetUp() { std::tie(Version, Format) = GetParam(); } 155a3acf99eSJames Henderson 156a3acf99eSJames Henderson uint16_t Version; 157a3acf99eSJames Henderson DwarfFormat Format; 158a3acf99eSJames Henderson }; 159a3acf99eSJames Henderson 160a3acf99eSJames Henderson void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 161a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue, 162a3acf99eSJames Henderson uint64_t BodyLength) { 163a3acf99eSJames Henderson // Check version specific fields and values. 164a3acf99eSJames Henderson uint64_t UnitLength; 165a3acf99eSJames Henderson uint64_t PrologueLength; 166a3acf99eSJames Henderson switch (Version) { 167a3acf99eSJames Henderson case 4: 168a3acf99eSJames Henderson PrologueLength = 36; 169a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 17011a9de74SJames Henderson EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 171a3acf99eSJames Henderson break; 172a3acf99eSJames Henderson case 2: 173a3acf99eSJames Henderson case 3: 174a3acf99eSJames Henderson PrologueLength = 35; 175a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 176a3acf99eSJames Henderson break; 177a3acf99eSJames Henderson case 5: 178a3acf99eSJames Henderson PrologueLength = 39; 179a3acf99eSJames Henderson UnitLength = PrologueLength + 4; 18011a9de74SJames Henderson EXPECT_EQ(Prologue.getAddressSize(), 8u); 18111a9de74SJames Henderson EXPECT_EQ(Prologue.SegSelectorSize, 0u); 182a3acf99eSJames Henderson break; 183a3acf99eSJames Henderson default: 184a3acf99eSJames Henderson llvm_unreachable("unsupported DWARF version"); 185a3acf99eSJames Henderson } 186a3acf99eSJames Henderson UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 187a3acf99eSJames Henderson 188a3acf99eSJames Henderson EXPECT_EQ(Prologue.TotalLength, UnitLength); 189a3acf99eSJames Henderson EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 19011a9de74SJames Henderson EXPECT_EQ(Prologue.MinInstLength, 1u); 19111a9de74SJames Henderson EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 192a3acf99eSJames Henderson EXPECT_EQ(Prologue.LineBase, -5); 19311a9de74SJames Henderson EXPECT_EQ(Prologue.LineRange, 14u); 19411a9de74SJames Henderson EXPECT_EQ(Prologue.OpcodeBase, 13u); 195a3acf99eSJames Henderson std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 196a3acf99eSJames Henderson EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 19711a9de74SJames Henderson ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 198a3acf99eSJames Henderson ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 199a3acf99eSJames Henderson EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 20011a9de74SJames Henderson ASSERT_EQ(Prologue.FileNames.size(), 1u); 201a3acf99eSJames Henderson ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 202a3acf99eSJames Henderson EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 203a3acf99eSJames Henderson } 204a3acf99eSJames Henderson 205a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 206a3acf99eSJames Henderson if (!setupGenerator()) 207a3acf99eSJames Henderson return; 208a3acf99eSJames Henderson generate(); 209a3acf99eSJames Henderson 21089b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 211a3acf99eSJames Henderson "offset 0x00000000 is not a valid debug line section offset", 0); 212a3acf99eSJames Henderson // Repeat to show that an error is reported each time. 21389b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 214a3acf99eSJames Henderson "offset 0x00000000 is not a valid debug line section offset", 0); 215a3acf99eSJames Henderson // Show that an error is reported for later offsets too. 21689b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 217a3acf99eSJames Henderson "offset 0x00000001 is not a valid debug line section offset", 1); 218a3acf99eSJames Henderson } 219a3acf99eSJames Henderson 220a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 221a3acf99eSJames Henderson if (!setupGenerator()) 22266702629SJames Henderson return; 22366702629SJames Henderson 224a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 225a3acf99eSJames Henderson LT.setCustomPrologue({{0, LineTable::Byte}}); 22666702629SJames Henderson 227a3acf99eSJames Henderson generate(); 228a3acf99eSJames Henderson 22989b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 230a3acf99eSJames Henderson "offset 0x00000001 is not a valid debug line section offset", 1); 231a3acf99eSJames Henderson } 232a3acf99eSJames Henderson 233a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 234a3acf99eSJames Henderson if (!setupGenerator(Version)) 235a3acf99eSJames Henderson return; 236a3acf99eSJames Henderson 237a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 238a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 239a3acf99eSJames Henderson 240a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 241a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 242a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 243a3acf99eSJames Henderson LT.addByte(0xaa); 244a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 245a3acf99eSJames Henderson 246a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(Format); 247a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 248a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 249a3acf99eSJames Henderson LT2.addByte(0xbb); 250a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 251a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 252a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 253a3acf99eSJames Henderson LT2.addByte(0xcc); 254a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 255a3acf99eSJames Henderson 256a3acf99eSJames Henderson generate(); 257a3acf99eSJames Henderson 258004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 259004b729eSJames Henderson nullptr, RecordRecoverable); 260a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable.operator bool()); 261004b729eSJames Henderson EXPECT_FALSE(Recoverable); 262a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 263a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 264a68aee07SRoman Lebedev EXPECT_EQ(Expected->Sequences.size(), 1u); 265a3acf99eSJames Henderson 266a3acf99eSJames Henderson uint64_t SecondOffset = 267a3acf99eSJames Henderson Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 268004b729eSJames Henderson Recoverable = Error::success(); 269a3acf99eSJames Henderson auto ExpectedLineTable2 = Line.getOrParseLineTable( 270004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 271a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable2.operator bool()); 272004b729eSJames Henderson EXPECT_FALSE(Recoverable); 273a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 274a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 27511a9de74SJames Henderson EXPECT_EQ(Expected2->Sequences.size(), 2u); 276a3acf99eSJames Henderson 277a3acf99eSJames Henderson EXPECT_NE(Expected, Expected2); 278a3acf99eSJames Henderson 279a3acf99eSJames Henderson // Check that if the same offset is requested, the exact same pointer is 280a3acf99eSJames Henderson // returned. 281004b729eSJames Henderson Recoverable = Error::success(); 282004b729eSJames Henderson auto ExpectedLineTable3 = Line.getOrParseLineTable( 283004b729eSJames Henderson LineData, 0, *Context, nullptr, RecordRecoverable); 284a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable3.operator bool()); 285004b729eSJames Henderson EXPECT_FALSE(Recoverable); 286a3acf99eSJames Henderson EXPECT_EQ(Expected, *ExpectedLineTable3); 287a3acf99eSJames Henderson 288004b729eSJames Henderson Recoverable = Error::success(); 289a3acf99eSJames Henderson auto ExpectedLineTable4 = Line.getOrParseLineTable( 290004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 291a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable4.operator bool()); 292004b729eSJames Henderson EXPECT_FALSE(Recoverable); 293a3acf99eSJames Henderson EXPECT_EQ(Expected2, *ExpectedLineTable4); 294a3acf99eSJames Henderson 295a3acf99eSJames Henderson // TODO: Add tests that show that the body of the programs have been read 296a3acf99eSJames Henderson // correctly. 297a3acf99eSJames Henderson } 298a3acf99eSJames Henderson 299a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 300a3acf99eSJames Henderson if (!setupGenerator()) 301a3acf99eSJames Henderson return; 302a3acf99eSJames Henderson 303a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 304f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 305a3acf99eSJames Henderson 306a3acf99eSJames Henderson generate(); 307a3acf99eSJames Henderson 30889b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 309a3acf99eSJames Henderson "parsing line table prologue at offset 0x00000000 unsupported reserved " 310f48bc018SIgor Kudrin "unit length found of value 0xfffffff0"); 311a3acf99eSJames Henderson } 312a3acf99eSJames Henderson 313a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForLowVersion) { 314a3acf99eSJames Henderson if (!setupGenerator()) 315a3acf99eSJames Henderson return; 316a3acf99eSJames Henderson 317a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 318a3acf99eSJames Henderson LT.setCustomPrologue( 319a3acf99eSJames Henderson {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}}); 320a3acf99eSJames Henderson 321a3acf99eSJames Henderson generate(); 322a3acf99eSJames Henderson 32389b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 32489b11843SJames Henderson "parsing line table prologue at offset " 325a3acf99eSJames Henderson "0x00000000 found unsupported version " 326a3acf99eSJames Henderson "0x01"); 327a3acf99eSJames Henderson } 328a3acf99eSJames Henderson 329a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 330a3acf99eSJames Henderson if (!setupGenerator(5)) 331a3acf99eSJames Henderson return; 332a3acf99eSJames Henderson 333a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 334a3acf99eSJames Henderson LT.setCustomPrologue({ 335a3acf99eSJames Henderson {19, LineTable::Long}, // unit length 336a3acf99eSJames Henderson {5, LineTable::Half}, // version 337a3acf99eSJames Henderson {8, LineTable::Byte}, // addr size 338a3acf99eSJames Henderson {0, LineTable::Byte}, // segment selector size 339a3acf99eSJames Henderson {11, LineTable::Long}, // prologue length 340a3acf99eSJames Henderson {1, LineTable::Byte}, // min instruction length 341a3acf99eSJames Henderson {1, LineTable::Byte}, // max ops per instruction 342a3acf99eSJames Henderson {1, LineTable::Byte}, // default is_stmt 343a3acf99eSJames Henderson {0, LineTable::Byte}, // line base 344a3acf99eSJames Henderson {14, LineTable::Byte}, // line range 345a3acf99eSJames Henderson {2, LineTable::Byte}, // opcode base (small to reduce the amount of 346a3acf99eSJames Henderson // setup required). 347a3acf99eSJames Henderson {0, LineTable::Byte}, // standard opcode lengths 348a3acf99eSJames Henderson {0, LineTable::Byte}, // directory entry format count (should not be 349a3acf99eSJames Henderson // zero). 350a3acf99eSJames Henderson {0, LineTable::ULEB}, // directories count 351a3acf99eSJames Henderson {0, LineTable::Byte}, // file name entry format count 352a3acf99eSJames Henderson {0, LineTable::ULEB} // file name entry count 353a3acf99eSJames Henderson }); 354a3acf99eSJames Henderson 355a3acf99eSJames Henderson generate(); 356a3acf99eSJames Henderson 35789b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 3580e7ba06eSJonas Devlieghere {"parsing line table prologue at 0x00000000 found an invalid directory " 3590e7ba06eSJonas Devlieghere "or file table description at 0x00000014", 3600e7ba06eSJonas Devlieghere "failed to parse entry content descriptions because no path was found"}); 361a3acf99eSJames Henderson } 362a3acf99eSJames Henderson 363a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 364a3acf99eSJames Henderson if (!setupGenerator(Version)) 365a3acf99eSJames Henderson return; 366a3acf99eSJames Henderson 367a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 368a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 369a3acf99eSJames Henderson 370a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 371a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 372a3acf99eSJames Henderson ++Prologue.PrologueLength; 373a3acf99eSJames Henderson LT.setPrologue(Prologue); 374a3acf99eSJames Henderson 375a3acf99eSJames Henderson generate(); 376a3acf99eSJames Henderson 377a3acf99eSJames Henderson uint64_t ExpectedEnd = 378a3acf99eSJames Henderson Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 37989b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 380a3acf99eSJames Henderson (Twine("parsing line table prologue at 0x00000000 should have ended at " 381a3acf99eSJames Henderson "0x000000") + 382a3acf99eSJames Henderson Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 383a3acf99eSJames Henderson Twine::utohexstr(ExpectedEnd - 1)) 384a3acf99eSJames Henderson .str()); 385a3acf99eSJames Henderson } 386a3acf99eSJames Henderson 387a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 388a3acf99eSJames Henderson if (!setupGenerator(Version)) 389a3acf99eSJames Henderson return; 390a3acf99eSJames Henderson 391a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 392a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 393a3acf99eSJames Henderson 394a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 395a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 396a3acf99eSJames Henderson // FIXME: Ideally, we'd test for 1 less than expected, but the code does not 397a3acf99eSJames Henderson // currently fail if missing only the terminator of a v2-4 file table. 398a3acf99eSJames Henderson if (Version < 5) 399a3acf99eSJames Henderson Prologue.PrologueLength -= 2; 400a3acf99eSJames Henderson else 401a3acf99eSJames Henderson Prologue.PrologueLength -= 1; 402a3acf99eSJames Henderson LT.setPrologue(Prologue); 403a3acf99eSJames Henderson 404a3acf99eSJames Henderson generate(); 405a3acf99eSJames Henderson 406a3acf99eSJames Henderson uint64_t ExpectedEnd = 407a3acf99eSJames Henderson Prologue.TotalLength - 1 + Prologue.sizeofTotalLength(); 408a3acf99eSJames Henderson if (Version < 5) 409a3acf99eSJames Henderson --ExpectedEnd; 41089b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 411a3acf99eSJames Henderson (Twine("parsing line table prologue at 0x00000000 should have ended at " 412a3acf99eSJames Henderson "0x000000") + 413a3acf99eSJames Henderson Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + 414a3acf99eSJames Henderson Twine::utohexstr(ExpectedEnd + 1)) 415a3acf99eSJames Henderson .str()); 416a3acf99eSJames Henderson } 417a3acf99eSJames Henderson 418a3acf99eSJames Henderson INSTANTIATE_TEST_CASE_P( 419a3acf99eSJames Henderson LineTableTestParams, DebugLineParameterisedFixture, 420a3acf99eSJames Henderson Values(std::make_pair( 421a3acf99eSJames Henderson 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 422a3acf99eSJames Henderson std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 423a3acf99eSJames Henderson std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 424a3acf99eSJames Henderson std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), ); 425a3acf99eSJames Henderson 426a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) { 427a3acf99eSJames Henderson if (!setupGenerator()) 428a3acf99eSJames Henderson return; 429a3acf99eSJames Henderson 430a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 431a3acf99eSJames Henderson // The Length should be 1 for an end sequence opcode. 432a3acf99eSJames Henderson LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 433a3acf99eSJames Henderson 434a3acf99eSJames Henderson generate(); 435a3acf99eSJames Henderson 43689b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 43789b11843SJames Henderson "unexpected line op length at offset " 438a3acf99eSJames Henderson "0x00000030 expected 0x02 found 0x01"); 439a3acf99eSJames Henderson } 440a3acf99eSJames Henderson 441*216796f2SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 442*216796f2SJames Henderson if (!setupGenerator()) 443*216796f2SJames Henderson return; 444*216796f2SJames Henderson 445*216796f2SJames Henderson LineTable &Padding = Gen->addLineTable(); 446*216796f2SJames Henderson // Add some padding to show that a non-zero offset is handled correctly. 447*216796f2SJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 448*216796f2SJames Henderson LineTable < = Gen->addLineTable(); 449*216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 450*216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 451*216796f2SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 452*216796f2SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 453*216796f2SJames Henderson // Set the total length to 1 higher than the actual length. The program body 454*216796f2SJames Henderson // has size 5. 455*216796f2SJames Henderson Prologue.TotalLength += 6; 456*216796f2SJames Henderson LT.setPrologue(Prologue); 457*216796f2SJames Henderson 458*216796f2SJames Henderson generate(); 459*216796f2SJames Henderson 460*216796f2SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 461*216796f2SJames Henderson nullptr, RecordRecoverable); 462*216796f2SJames Henderson checkError("line table program with offset 0x00000001 has length 0x00000034 " 463*216796f2SJames Henderson "but only 0x00000033 bytes are available", 464*216796f2SJames Henderson std::move(Recoverable)); 465*216796f2SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 466*216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 467*216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 468*216796f2SJames Henderson } 469*216796f2SJames Henderson 470a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 471a3acf99eSJames Henderson if (!setupGenerator()) 472a3acf99eSJames Henderson return; 473a3acf99eSJames Henderson 474a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 475a3acf99eSJames Henderson // The line data extractor expects size 8 (Quad) addresses. 476a3acf99eSJames Henderson LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x11223344, LineTable::Long}}); 477a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 478a3acf99eSJames Henderson LT.addByte(0xaa); 479a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 480a3acf99eSJames Henderson 481a3acf99eSJames Henderson generate(); 482a3acf99eSJames Henderson 48389b11843SJames Henderson checkGetOrParseLineTableEmitsFatalError( 484a3acf99eSJames Henderson "mismatching address size at offset 0x00000030 expected 0x08 found 0x04"); 485a3acf99eSJames Henderson } 486a3acf99eSJames Henderson 487a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 488a3acf99eSJames Henderson if (!setupGenerator()) 489a3acf99eSJames Henderson return; 490a3acf99eSJames Henderson 491a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 492a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 493a3acf99eSJames Henderson {{0x1122334455667788, LineTable::Quad}}); 494a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 495a3acf99eSJames Henderson LT.addByte(0xaa); 496a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 497a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 498a3acf99eSJames Henderson {{0x99aabbccddeeff00, LineTable::Quad}}); 499a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 500a3acf99eSJames Henderson LT.addByte(0xbb); 501a3acf99eSJames Henderson LT.addByte(0xcc); 502a3acf99eSJames Henderson 503a3acf99eSJames Henderson generate(); 504a3acf99eSJames Henderson 505004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 506004b729eSJames Henderson nullptr, RecordRecoverable); 507004b729eSJames Henderson checkError("last sequence in debug line table is not terminated!", 508004b729eSJames Henderson std::move(Recoverable)); 509a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable.operator bool()); 510a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 511a3acf99eSJames Henderson // The unterminated sequence is not added to the sequence list. 512a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 513a3acf99eSJames Henderson } 514a3acf99eSJames Henderson 515a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 516a3acf99eSJames Henderson if (!setupGenerator()) 517a3acf99eSJames Henderson return; 518a3acf99eSJames Henderson 519a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 520a3acf99eSJames Henderson 52111a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 522a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 523a3acf99eSJames Henderson 524004b729eSJames Henderson DWARFDebugLine::LineTable Parsed = 525004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 526a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 52711a9de74SJames Henderson EXPECT_EQ(Parsed.Sequences.size(), 1u); 52811a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 529a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 530a3acf99eSJames Henderson 531a3acf99eSJames Henderson DWARFDebugLine::LineTable Parsed2 = 532004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 533a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 53411a9de74SJames Henderson EXPECT_EQ(Parsed2.Sequences.size(), 1u); 53511a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 536a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 537a3acf99eSJames Henderson 538004b729eSJames Henderson EXPECT_FALSE(Recoverable); 539004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 540a3acf99eSJames Henderson } 541a3acf99eSJames Henderson 542a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 543a3acf99eSJames Henderson if (!setupGenerator()) 544a3acf99eSJames Henderson return; 545a3acf99eSJames Henderson 546a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 547a3acf99eSJames Henderson 54811a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 549a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 550a3acf99eSJames Henderson 551004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 55211a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 553a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 554a3acf99eSJames Henderson 555004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 55611a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 557a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 558a3acf99eSJames Henderson 559004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 560a3acf99eSJames Henderson } 561a3acf99eSJames Henderson 562a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 563a3acf99eSJames Henderson if (!setupGenerator()) 564a3acf99eSJames Henderson return; 565a3acf99eSJames Henderson 566a3acf99eSJames Henderson generate(); 567a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 568a3acf99eSJames Henderson 569a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 570a3acf99eSJames Henderson } 571a3acf99eSJames Henderson 572a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { 573a3acf99eSJames Henderson if (!setupGenerator()) 574a3acf99eSJames Henderson return; 575a3acf99eSJames Henderson 576a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 577f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 578a3acf99eSJames Henderson Gen->addLineTable(); 579a3acf99eSJames Henderson generate(); 580a3acf99eSJames Henderson 581a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 582004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 583a3acf99eSJames Henderson 58411a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 4u); 585a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 586004b729eSJames Henderson EXPECT_FALSE(Recoverable); 587a3acf99eSJames Henderson 588a3acf99eSJames Henderson checkError("parsing line table prologue at offset 0x00000000 unsupported " 589f48bc018SIgor Kudrin "reserved unit length found of value 0xfffffff0", 590004b729eSJames Henderson std::move(Unrecoverable)); 591a3acf99eSJames Henderson } 592a3acf99eSJames Henderson 593a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { 594a3acf99eSJames Henderson if (!setupGenerator()) 595a3acf99eSJames Henderson return; 596a3acf99eSJames Henderson 597a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 598f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 599a3acf99eSJames Henderson Gen->addLineTable(); 600a3acf99eSJames Henderson generate(); 601a3acf99eSJames Henderson 602a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 603004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 604a3acf99eSJames Henderson 60511a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 4u); 606a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 607a3acf99eSJames Henderson 608a3acf99eSJames Henderson checkError("parsing line table prologue at offset 0x00000000 unsupported " 609f48bc018SIgor Kudrin "reserved unit length found of value 0xfffffff0", 610004b729eSJames Henderson std::move(Unrecoverable)); 611a3acf99eSJames Henderson } 612a3acf99eSJames Henderson 613a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 614a3acf99eSJames Henderson if (!setupGenerator()) 615a3acf99eSJames Henderson return; 616a3acf99eSJames Henderson 617a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 618a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 619a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 620a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 621a3acf99eSJames Henderson generate(); 622a3acf99eSJames Henderson 623a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 624004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 625a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 626004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 627a3acf99eSJames Henderson 628a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 629004b729eSJames Henderson EXPECT_FALSE(Recoverable); 630a3acf99eSJames Henderson 631a3acf99eSJames Henderson checkError({"parsing line table prologue at offset 0x00000000 found " 632a3acf99eSJames Henderson "unsupported version 0x00", 633a3acf99eSJames Henderson "parsing line table prologue at offset 0x00000006 found " 634a3acf99eSJames Henderson "unsupported version 0x01"}, 635004b729eSJames Henderson std::move(Unrecoverable)); 636a3acf99eSJames Henderson } 637a3acf99eSJames Henderson 638a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 639a3acf99eSJames Henderson if (!setupGenerator()) 640a3acf99eSJames Henderson return; 641a3acf99eSJames Henderson 642a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 643a3acf99eSJames Henderson LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 644a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 645a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 646a3acf99eSJames Henderson {{0x1234567890abcdef, LineTable::Quad}}); 647a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 648a3acf99eSJames Henderson LT2.addByte(0xbb); 649a3acf99eSJames Henderson generate(); 650a3acf99eSJames Henderson 651a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 652004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 653004b729eSJames Henderson EXPECT_FALSE(Recoverable); 654a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 655a3acf99eSJames Henderson checkError( 656a3acf99eSJames Henderson "unexpected line op length at offset 0x00000030 expected 0x42 found 0x01", 657004b729eSJames Henderson std::move(Unrecoverable)); 658a3acf99eSJames Henderson 659a3acf99eSJames Henderson // Reset the error state so that it does not confuse the next set of checks. 660004b729eSJames Henderson Unrecoverable = Error::success(); 661004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 662a3acf99eSJames Henderson 663a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 664004b729eSJames Henderson checkError("last sequence in debug line table is not terminated!", 665004b729eSJames Henderson std::move(Recoverable)); 666004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 667a3acf99eSJames Henderson } 668a3acf99eSJames Henderson 669a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, 670a3acf99eSJames Henderson ParserReportsPrologueErrorsInEachTableWhenSkipping) { 671a3acf99eSJames Henderson if (!setupGenerator()) 672a3acf99eSJames Henderson return; 673a3acf99eSJames Henderson 674a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 675a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 676a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 677a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 678a3acf99eSJames Henderson generate(); 679a3acf99eSJames Henderson 680a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 681004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 682a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 683004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 684a3acf99eSJames Henderson 685a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 686a3acf99eSJames Henderson 687a3acf99eSJames Henderson checkError({"parsing line table prologue at offset 0x00000000 found " 688a3acf99eSJames Henderson "unsupported version 0x00", 689a3acf99eSJames Henderson "parsing line table prologue at offset 0x00000006 found " 690a3acf99eSJames Henderson "unsupported version 0x01"}, 691004b729eSJames Henderson std::move(Unrecoverable)); 692a3acf99eSJames Henderson } 693a3acf99eSJames Henderson 694a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 695a3acf99eSJames Henderson if (!setupGenerator()) 696a3acf99eSJames Henderson return; 697a3acf99eSJames Henderson 698a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 699a3acf99eSJames Henderson LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 700a3acf99eSJames Henderson generate(); 701a3acf99eSJames Henderson 702a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 703004b729eSJames Henderson Parser.skip(RecordUnrecoverable); 704a3acf99eSJames Henderson 705a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 706004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 70766702629SJames Henderson } 70866702629SJames Henderson 7092f815502SJames Henderson TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) { 7102f815502SJames Henderson if (!setupGenerator()) 7112f815502SJames Henderson return; 7122f815502SJames Henderson 7132f815502SJames Henderson using ValLen = dwarfgen::LineTable::ValueAndLength; 7142f815502SJames Henderson LineTable < = Gen->addLineTable(DWARF32); 7152f815502SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 7162f815502SJames Henderson LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}}); 7172f815502SJames Henderson LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22, LineTable::SLEB}}); 7182f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}}); 7192f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}}); 7202f815502SJames Henderson LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 7212f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 7222f815502SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 7232f815502SJames Henderson LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55, LineTable::Half}}); 7242f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 7252f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 7262f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}}); 7272f815502SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 7282f815502SJames Henderson generate(); 7292f815502SJames Henderson 7302f815502SJames Henderson DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); 7312f815502SJames Henderson std::string Output; 7322f815502SJames Henderson raw_string_ostream OS(Output); 7332f815502SJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS); 7342f815502SJames Henderson OS.flush(); 7352f815502SJames Henderson 7362f815502SJames Henderson EXPECT_FALSE(Recoverable); 7372f815502SJames Henderson EXPECT_FALSE(Unrecoverable); 7382f815502SJames Henderson auto InOutput = [&Output](char const *Str) { 7392f815502SJames Henderson return Output.find(Str) != std::string::npos; 7402f815502SJames Henderson }; 7412f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output; 7422f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) << Output; 7432f815502SJames Henderson // FIXME: The value printed after DW_LNS_advance_line is currently the result 7442f815502SJames Henderson // of the advance, but it should be the value being advanced by. See 7452f815502SJames Henderson // https://bugs.llvm.org/show_bug.cgi?id=44261 for details. 7462f815502SJames Henderson EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) << Output; 7472f815502SJames Henderson EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) << Output; 7482f815502SJames Henderson EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) << Output; 7492f815502SJames Henderson EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output; 7502f815502SJames Henderson EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) << Output; 7512f815502SJames Henderson EXPECT_TRUE( 7522f815502SJames Henderson InOutput("0x00000039: 08 DW_LNS_const_add_pc (0x0000000000000011)\n")) 7532f815502SJames Henderson << Output; 7542f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc (0x0037)\n")) 7552f815502SJames Henderson << Output; 7562f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) << Output; 7572f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) << Output; 7582f815502SJames Henderson EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; 7592f815502SJames Henderson } 7602f815502SJames Henderson 76166702629SJames Henderson } // end anonymous namespace 762