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 39*5fc05a0aSIgor Kudrin // Note: ASSERT_THAT_EXPECTED cannot be used in a non-void function, so 40*5fc05a0aSIgor Kudrin // setupGenerator() is split into two. 41*5fc05a0aSIgor Kudrin void setupGeneratorImpl(uint16_t Version, uint8_t AddrSize) { 4207804f75SJames Henderson AddressSize = AddrSize; 43*5fc05a0aSIgor Kudrin Triple T = getDefaultTargetTripleForAddrSize(AddressSize ? AddressSize : 8); 4466702629SJames Henderson if (!isConfigurationSupported(T)) 45*5fc05a0aSIgor Kudrin return; 46a3acf99eSJames Henderson auto ExpectedGenerator = Generator::create(T, Version); 47*5fc05a0aSIgor Kudrin ASSERT_THAT_EXPECTED(ExpectedGenerator, Succeeded()); 48*5fc05a0aSIgor Kudrin Gen = std::move(*ExpectedGenerator); 49*5fc05a0aSIgor Kudrin } 50*5fc05a0aSIgor Kudrin 51*5fc05a0aSIgor Kudrin bool setupGenerator(uint16_t Version = 4, uint8_t AddrSize = 8) { 52*5fc05a0aSIgor Kudrin setupGeneratorImpl(Version, AddrSize); 53*5fc05a0aSIgor Kudrin return Gen != nullptr; 5466702629SJames Henderson } 5566702629SJames Henderson 56a3acf99eSJames Henderson void generate() { 57a3acf99eSJames Henderson Context = createContext(); 58a3acf99eSJames Henderson assert(Context != nullptr && "test state is not valid"); 59a3acf99eSJames Henderson const DWARFObject &Obj = Context->getDWARFObj(); 6007804f75SJames Henderson uint8_t TargetAddrSize = AddressSize == 0 ? 8 : AddressSize; 61552fda83SJason Liu LineData = DWARFDataExtractor( 62552fda83SJason Liu Obj, Obj.getLineSection(), 6307804f75SJames Henderson getDefaultTargetTripleForAddrSize(TargetAddrSize).isLittleEndian(), 6407804f75SJames Henderson AddressSize); 65a3acf99eSJames Henderson } 66a3acf99eSJames Henderson 6766702629SJames Henderson std::unique_ptr<DWARFContext> createContext() { 68*5fc05a0aSIgor Kudrin assert(Gen != nullptr && "Generator is not set up"); 69a3acf99eSJames Henderson StringRef FileBytes = Gen->generate(); 7066702629SJames Henderson MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 7166702629SJames Henderson auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 7266702629SJames Henderson if (Obj) 7366702629SJames Henderson return DWARFContext::create(**Obj); 7466702629SJames Henderson return nullptr; 7566702629SJames Henderson } 7666702629SJames Henderson 77a3acf99eSJames Henderson DWARFDebugLine::SectionParser setupParser() { 78a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 79a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 80a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 81a3acf99eSJames Henderson LT.addByte(0xaa); 82a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 83a3acf99eSJames Henderson 84a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF64); 85a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 86a3acf99eSJames Henderson {{0x11223344, LineTable::Quad}}); 87a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 88a3acf99eSJames Henderson LT2.addByte(0xbb); 89a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 90a3acf99eSJames Henderson 91a3acf99eSJames Henderson generate(); 92a3acf99eSJames Henderson 9351a50534SDavid Blaikie return DWARFDebugLine::SectionParser(LineData, *Context, Units); 94a3acf99eSJames Henderson } 95a3acf99eSJames Henderson 96004b729eSJames Henderson void recordRecoverable(Error Err) { 97004b729eSJames Henderson Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); 98004b729eSJames Henderson } 99004b729eSJames Henderson void recordUnrecoverable(Error Err) { 100004b729eSJames Henderson Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); 101a3acf99eSJames Henderson } 102a3acf99eSJames Henderson 1039b23024cSPavel Labath Expected<const DWARFDebugLine::LineTable *> 1049b23024cSPavel Labath getOrParseLineTableFatalErrors(uint64_t Offset = 0) { 105a3acf99eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable( 106004b729eSJames Henderson LineData, Offset, *Context, nullptr, RecordRecoverable); 1079b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1089b23024cSPavel Labath return ExpectedLineTable; 1090e7ba06eSJonas Devlieghere } 1100e7ba06eSJonas Devlieghere 11107804f75SJames Henderson uint8_t AddressSize; 112a3acf99eSJames Henderson std::unique_ptr<Generator> Gen; 113a3acf99eSJames Henderson std::unique_ptr<DWARFContext> Context; 114a3acf99eSJames Henderson DWARFDataExtractor LineData; 115a3acf99eSJames Henderson DWARFDebugLine Line; 116004b729eSJames Henderson Error Recoverable; 117004b729eSJames Henderson std::function<void(Error)> RecordRecoverable; 118004b729eSJames Henderson Error Unrecoverable; 119004b729eSJames Henderson std::function<void(Error)> RecordUnrecoverable; 120a3acf99eSJames Henderson 12151a50534SDavid Blaikie SmallVector<std::unique_ptr<DWARFUnit>, 2> Units; 12266702629SJames Henderson }; 12366702629SJames Henderson 124a3acf99eSJames Henderson // Fixtures must derive from "Test", but parameterised fixtures from 125a3acf99eSJames Henderson // "TestWithParam". It does not seem possible to inherit from both, so we share 126a3acf99eSJames Henderson // the common state in a separate class, inherited by the two fixture classes. 127a3acf99eSJames Henderson struct DebugLineBasicFixture : public Test, public CommonFixture {}; 128a3acf99eSJames Henderson 129a3acf99eSJames Henderson struct DebugLineParameterisedFixture 130a3acf99eSJames Henderson : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 131a3acf99eSJames Henderson public CommonFixture { 13231eb8349SLogan Smith void SetUp() override { std::tie(Version, Format) = GetParam(); } 133a3acf99eSJames Henderson 134a3acf99eSJames Henderson uint16_t Version; 135a3acf99eSJames Henderson DwarfFormat Format; 136a3acf99eSJames Henderson }; 137a3acf99eSJames Henderson 138a3acf99eSJames Henderson void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 139a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue, 140a3acf99eSJames Henderson uint64_t BodyLength) { 141a3acf99eSJames Henderson // Check version specific fields and values. 142a3acf99eSJames Henderson uint64_t UnitLength; 143a3acf99eSJames Henderson uint64_t PrologueLength; 144a3acf99eSJames Henderson switch (Version) { 145a3acf99eSJames Henderson case 4: 146a3acf99eSJames Henderson PrologueLength = 36; 147a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 14811a9de74SJames Henderson EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 149a3acf99eSJames Henderson break; 150a3acf99eSJames Henderson case 2: 151a3acf99eSJames Henderson case 3: 152a3acf99eSJames Henderson PrologueLength = 35; 153a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 154a3acf99eSJames Henderson break; 155a3acf99eSJames Henderson case 5: 1560bd48c3dSSterling Augustine PrologueLength = 42; 157a3acf99eSJames Henderson UnitLength = PrologueLength + 4; 15811a9de74SJames Henderson EXPECT_EQ(Prologue.getAddressSize(), 8u); 15911a9de74SJames Henderson EXPECT_EQ(Prologue.SegSelectorSize, 0u); 160a3acf99eSJames Henderson break; 161a3acf99eSJames Henderson default: 162a3acf99eSJames Henderson llvm_unreachable("unsupported DWARF version"); 163a3acf99eSJames Henderson } 164a3acf99eSJames Henderson UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 165a3acf99eSJames Henderson 166a3acf99eSJames Henderson EXPECT_EQ(Prologue.TotalLength, UnitLength); 167a3acf99eSJames Henderson EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 16811a9de74SJames Henderson EXPECT_EQ(Prologue.MinInstLength, 1u); 16911a9de74SJames Henderson EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 170a3acf99eSJames Henderson EXPECT_EQ(Prologue.LineBase, -5); 17111a9de74SJames Henderson EXPECT_EQ(Prologue.LineRange, 14u); 17211a9de74SJames Henderson EXPECT_EQ(Prologue.OpcodeBase, 13u); 173a3acf99eSJames Henderson std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 174a3acf99eSJames Henderson EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 17511a9de74SJames Henderson ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 176a3acf99eSJames Henderson ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 17771e5488aSDavid Blaikie EXPECT_STREQ(*toString(Prologue.IncludeDirectories[0]), "a dir"); 17811a9de74SJames Henderson ASSERT_EQ(Prologue.FileNames.size(), 1u); 179a3acf99eSJames Henderson ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 1800bd48c3dSSterling Augustine ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u); 18171e5488aSDavid Blaikie EXPECT_STREQ(*toString(Prologue.FileNames[0].Name), "a file"); 182a3acf99eSJames Henderson } 183a3acf99eSJames Henderson 184d24e721dSJake Egan #ifdef _AIX 185d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_GetOrParseLineTableAtInvalidOffset) { 186d24e721dSJake Egan #else 187a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 188d24e721dSJake Egan #endif 189a3acf99eSJames Henderson if (!setupGenerator()) 190a3acf99eSJames Henderson return; 191a3acf99eSJames Henderson generate(); 192a3acf99eSJames Henderson 1939b23024cSPavel Labath EXPECT_THAT_EXPECTED( 1949b23024cSPavel Labath getOrParseLineTableFatalErrors(0), 1959b23024cSPavel Labath FailedWithMessage( 1969b23024cSPavel Labath "offset 0x00000000 is not a valid debug line section offset")); 197a3acf99eSJames Henderson // Repeat to show that an error is reported each time. 1989b23024cSPavel Labath EXPECT_THAT_EXPECTED( 1999b23024cSPavel Labath getOrParseLineTableFatalErrors(0), 2009b23024cSPavel Labath FailedWithMessage( 2019b23024cSPavel Labath "offset 0x00000000 is not a valid debug line section offset")); 2029b23024cSPavel Labath 203a3acf99eSJames Henderson // Show that an error is reported for later offsets too. 2049b23024cSPavel Labath EXPECT_THAT_EXPECTED( 2059b23024cSPavel Labath getOrParseLineTableFatalErrors(1), 2069b23024cSPavel Labath FailedWithMessage( 2079b23024cSPavel Labath "offset 0x00000001 is not a valid debug line section offset")); 208a3acf99eSJames Henderson } 209a3acf99eSJames Henderson 210d24e721dSJake Egan #ifdef _AIX 211d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 212d24e721dSJake Egan DISABLED_GetOrParseLineTableAtInvalidOffsetAfterData) { 213d24e721dSJake Egan #else 214a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 215d24e721dSJake Egan #endif 216a3acf99eSJames Henderson if (!setupGenerator()) 21766702629SJames Henderson return; 21866702629SJames Henderson 219a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 220a3acf99eSJames Henderson LT.setCustomPrologue({{0, LineTable::Byte}}); 22166702629SJames Henderson 222a3acf99eSJames Henderson generate(); 223a3acf99eSJames Henderson 2249b23024cSPavel Labath EXPECT_THAT_EXPECTED( 225d978656fSPavel Labath getOrParseLineTableFatalErrors(0), 22604aea769SPavel Labath FailedWithMessage( 22704aea769SPavel Labath "parsing line table prologue at offset 0x00000000: " 22804aea769SPavel Labath "unexpected end of data at offset 0x1 while reading [0x0, 0x4)")); 229d978656fSPavel Labath 230d978656fSPavel Labath EXPECT_THAT_EXPECTED( 2319b23024cSPavel Labath getOrParseLineTableFatalErrors(1), 2329b23024cSPavel Labath FailedWithMessage( 2339b23024cSPavel Labath "offset 0x00000001 is not a valid debug line section offset")); 234a3acf99eSJames Henderson } 235a3acf99eSJames Henderson 236d24e721dSJake Egan #ifdef _AIX 237d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_PrologueGetLength) { 238d24e721dSJake Egan #else 239021f5317SJames Henderson TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 240d24e721dSJake Egan #endif 241021f5317SJames Henderson if (!setupGenerator(Version)) 242021f5317SJames Henderson return; 243021f5317SJames Henderson LineTable < = Gen->addLineTable(Format); 244021f5317SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 245021f5317SJames Henderson LT.setPrologue(Prologue); 246021f5317SJames Henderson generate(); 247021f5317SJames Henderson 248021f5317SJames Henderson // + 10 for sizes of DWARF-32 unit length, version, prologue length. 249021f5317SJames Henderson uint64_t ExpectedLength = Prologue.PrologueLength + 10; 250021f5317SJames Henderson if (Version == 5) 251021f5317SJames Henderson // Add address and segment selector size fields. 252021f5317SJames Henderson ExpectedLength += 2; 253021f5317SJames Henderson if (Format == DWARF64) 254021f5317SJames Henderson // Unit length grows by 8, prologue length by 4. 255021f5317SJames Henderson ExpectedLength += 12; 256021f5317SJames Henderson 257021f5317SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 258021f5317SJames Henderson nullptr, RecordRecoverable); 259021f5317SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 260021f5317SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 261021f5317SJames Henderson } 262021f5317SJames Henderson 263d24e721dSJake Egan #ifdef _AIX 264d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_GetOrParseLineTableValidTable) { 265d24e721dSJake Egan #else 266a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 267d24e721dSJake Egan #endif 268a3acf99eSJames Henderson if (!setupGenerator(Version)) 269a3acf99eSJames Henderson return; 270a3acf99eSJames Henderson 271a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 272a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 273a3acf99eSJames Henderson 274a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 275a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 276a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 277a3acf99eSJames Henderson LT.addByte(0xaa); 278a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 279a3acf99eSJames Henderson 280a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(Format); 281a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 282a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 283a3acf99eSJames Henderson LT2.addByte(0xbb); 284a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 285a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 286a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 287a3acf99eSJames Henderson LT2.addByte(0xcc); 288a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 289a3acf99eSJames Henderson 290a3acf99eSJames Henderson generate(); 291a3acf99eSJames Henderson 292004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 293004b729eSJames Henderson nullptr, RecordRecoverable); 294a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable.operator bool()); 295004b729eSJames Henderson EXPECT_FALSE(Recoverable); 296a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 297a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 298a68aee07SRoman Lebedev EXPECT_EQ(Expected->Sequences.size(), 1u); 299a3acf99eSJames Henderson 300a3acf99eSJames Henderson uint64_t SecondOffset = 301a3acf99eSJames Henderson Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 302004b729eSJames Henderson Recoverable = Error::success(); 303a3acf99eSJames Henderson auto ExpectedLineTable2 = Line.getOrParseLineTable( 304004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 305a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable2.operator bool()); 306004b729eSJames Henderson EXPECT_FALSE(Recoverable); 307a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 308a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 30911a9de74SJames Henderson EXPECT_EQ(Expected2->Sequences.size(), 2u); 310a3acf99eSJames Henderson 311a3acf99eSJames Henderson EXPECT_NE(Expected, Expected2); 312a3acf99eSJames Henderson 313a3acf99eSJames Henderson // Check that if the same offset is requested, the exact same pointer is 314a3acf99eSJames Henderson // returned. 315004b729eSJames Henderson Recoverable = Error::success(); 316004b729eSJames Henderson auto ExpectedLineTable3 = Line.getOrParseLineTable( 317004b729eSJames Henderson LineData, 0, *Context, nullptr, RecordRecoverable); 318a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable3.operator bool()); 319004b729eSJames Henderson EXPECT_FALSE(Recoverable); 320a3acf99eSJames Henderson EXPECT_EQ(Expected, *ExpectedLineTable3); 321a3acf99eSJames Henderson 322004b729eSJames Henderson Recoverable = Error::success(); 323a3acf99eSJames Henderson auto ExpectedLineTable4 = Line.getOrParseLineTable( 324004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 325a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable4.operator bool()); 326004b729eSJames Henderson EXPECT_FALSE(Recoverable); 327a3acf99eSJames Henderson EXPECT_EQ(Expected2, *ExpectedLineTable4); 328a3acf99eSJames Henderson 329a3acf99eSJames Henderson // TODO: Add tests that show that the body of the programs have been read 330a3acf99eSJames Henderson // correctly. 331a3acf99eSJames Henderson } 332a3acf99eSJames Henderson 333d24e721dSJake Egan #ifdef _AIX 334d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForReservedLength) { 335d24e721dSJake Egan #else 336a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 337d24e721dSJake Egan #endif 338a3acf99eSJames Henderson if (!setupGenerator()) 339a3acf99eSJames Henderson return; 340a3acf99eSJames Henderson 341a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 342f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 343a3acf99eSJames Henderson 344a3acf99eSJames Henderson generate(); 345a3acf99eSJames Henderson 3469b23024cSPavel Labath EXPECT_THAT_EXPECTED( 3479b23024cSPavel Labath getOrParseLineTableFatalErrors(), 3489b23024cSPavel Labath FailedWithMessage( 349d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 350d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 351a3acf99eSJames Henderson } 352a3acf99eSJames Henderson 3531da62b51SJames Henderson struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>, 3541da62b51SJames Henderson public CommonFixture { 35531eb8349SLogan Smith void SetUp() override { Version = GetParam(); } 3561da62b51SJames Henderson 3571da62b51SJames Henderson uint16_t Version; 3581da62b51SJames Henderson }; 3591da62b51SJames Henderson 360d24e721dSJake Egan #ifdef _AIX 361d24e721dSJake Egan TEST_P(DebugLineUnsupportedVersionFixture, 362d24e721dSJake Egan DISABLED_ErrorForUnsupportedVersion) { 363d24e721dSJake Egan #else 3641da62b51SJames Henderson TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) { 365d24e721dSJake Egan #endif 366a3acf99eSJames Henderson if (!setupGenerator()) 367a3acf99eSJames Henderson return; 368a3acf99eSJames Henderson 369a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 370a3acf99eSJames Henderson LT.setCustomPrologue( 3711da62b51SJames Henderson {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}}); 372b1c7bfe6SJames Henderson 373b1c7bfe6SJames Henderson generate(); 374b1c7bfe6SJames Henderson 3759b23024cSPavel Labath EXPECT_THAT_EXPECTED( 3769b23024cSPavel Labath getOrParseLineTableFatalErrors(), 377d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 378d978656fSPavel Labath "unsupported version " + 3799b23024cSPavel Labath std::to_string(Version))); 380b1c7bfe6SJames Henderson } 381b1c7bfe6SJames Henderson 382d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(UnsupportedVersionTestParams, 3831da62b51SJames Henderson DebugLineUnsupportedVersionFixture, 3841da62b51SJames Henderson Values(/*1 below min */ 1, /* 1 above max */ 6, 385d4d80a29SBenjamin Kramer /* Maximum possible */ 0xffff)); 3861da62b51SJames Henderson 387d24e721dSJake Egan #ifdef _AIX 388d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForInvalidV5IncludeDirTable) { 389d24e721dSJake Egan #else 390a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 391d24e721dSJake Egan #endif 392a3acf99eSJames Henderson if (!setupGenerator(5)) 393a3acf99eSJames Henderson return; 394a3acf99eSJames Henderson 395a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 396a3acf99eSJames Henderson LT.setCustomPrologue({ 397a3acf99eSJames Henderson {19, LineTable::Long}, // unit length 398a3acf99eSJames Henderson {5, LineTable::Half}, // version 399a3acf99eSJames Henderson {8, LineTable::Byte}, // addr size 400a3acf99eSJames Henderson {0, LineTable::Byte}, // segment selector size 401a3acf99eSJames Henderson {11, LineTable::Long}, // prologue length 402a3acf99eSJames Henderson {1, LineTable::Byte}, // min instruction length 403a3acf99eSJames Henderson {1, LineTable::Byte}, // max ops per instruction 404a3acf99eSJames Henderson {1, LineTable::Byte}, // default is_stmt 405a3acf99eSJames Henderson {0, LineTable::Byte}, // line base 406a3acf99eSJames Henderson {14, LineTable::Byte}, // line range 407a3acf99eSJames Henderson {2, LineTable::Byte}, // opcode base (small to reduce the amount of 408a3acf99eSJames Henderson // setup required). 409a3acf99eSJames Henderson {0, LineTable::Byte}, // standard opcode lengths 410a3acf99eSJames Henderson {0, LineTable::Byte}, // directory entry format count (should not be 411a3acf99eSJames Henderson // zero). 412a3acf99eSJames Henderson {0, LineTable::ULEB}, // directories count 413a3acf99eSJames Henderson {0, LineTable::Byte}, // file name entry format count 414a3acf99eSJames Henderson {0, LineTable::ULEB} // file name entry count 415a3acf99eSJames Henderson }); 416a3acf99eSJames Henderson 417a3acf99eSJames Henderson generate(); 418a3acf99eSJames Henderson 4197116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4207116e431SJames Henderson nullptr, RecordRecoverable); 4217116e431SJames Henderson EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4227116e431SJames Henderson 4239b23024cSPavel Labath EXPECT_THAT_ERROR( 4249b23024cSPavel Labath std::move(Recoverable), 4259b23024cSPavel Labath FailedWithMessage( 4269b23024cSPavel Labath "parsing line table prologue at 0x00000000 found an invalid " 4279b23024cSPavel Labath "directory or file table description at 0x00000014", 4289b23024cSPavel Labath "failed to parse entry content descriptions because no path was " 4299b23024cSPavel Labath "found")); 430a3acf99eSJames Henderson } 431a3acf99eSJames Henderson 432d24e721dSJake Egan #ifdef _AIX 433d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooLargePrologueLength) { 434d24e721dSJake Egan #else 435a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 436d24e721dSJake Egan #endif 437a3acf99eSJames Henderson if (!setupGenerator(Version)) 438a3acf99eSJames Henderson return; 439a3acf99eSJames Henderson 440a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 441a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 442a3acf99eSJames Henderson 443a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 444a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 445a3acf99eSJames Henderson ++Prologue.PrologueLength; 446a3acf99eSJames Henderson LT.setPrologue(Prologue); 447a3acf99eSJames Henderson 448a3acf99eSJames Henderson generate(); 449a3acf99eSJames Henderson 4507116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4517116e431SJames Henderson nullptr, RecordRecoverable); 4527116e431SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4537116e431SJames Henderson DWARFDebugLine::LineTable Result(**ExpectedLineTable); 4547116e431SJames Henderson // Undo the earlier modification so that it can be compared against a 4557116e431SJames Henderson // "default" prologue. 4567116e431SJames Henderson --Result.Prologue.PrologueLength; 4577116e431SJames Henderson checkDefaultPrologue(Version, Format, Result.Prologue, 0); 4587116e431SJames Henderson 459a3acf99eSJames Henderson uint64_t ExpectedEnd = 460a3acf99eSJames Henderson Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 4619b23024cSPavel Labath EXPECT_THAT_ERROR( 4629b23024cSPavel Labath std::move(Recoverable), 4636f55b5a1SPavel Labath FailedWithMessage( 4646f55b5a1SPavel Labath ("unknown data in line table prologue at offset 0x00000000: " 4656f55b5a1SPavel Labath "parsing ended (at offset 0x000000" + 4666f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd - 1) + 467fccaa89eSPavel Labath ") before reaching the prologue end at offset 0x000000" + 4686f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd)) 4699b23024cSPavel Labath .str())); 470a3acf99eSJames Henderson } 471a3acf99eSJames Henderson 472d24e721dSJake Egan #ifdef _AIX 473d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooShortPrologueLength) { 474d24e721dSJake Egan #else 475a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 476d24e721dSJake Egan #endif 477a3acf99eSJames Henderson if (!setupGenerator(Version)) 478a3acf99eSJames Henderson return; 479a3acf99eSJames Henderson 480a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 481a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 482a3acf99eSJames Henderson 483a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 484a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 485a3acf99eSJames Henderson Prologue.PrologueLength -= 2; 486a3acf99eSJames Henderson LT.setPrologue(Prologue); 487a3acf99eSJames Henderson 488a3acf99eSJames Henderson generate(); 489a3acf99eSJames Henderson 4907116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4917116e431SJames Henderson nullptr, RecordRecoverable); 4927116e431SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4937116e431SJames Henderson DWARFDebugLine::LineTable Result(**ExpectedLineTable); 494c475856dSPavel Labath 495c475856dSPavel Labath // Parsing will stop before reading a complete file entry. 496c475856dSPavel Labath ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); 497c475856dSPavel Labath EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); 498c475856dSPavel Labath EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); 4997116e431SJames Henderson 5006f55b5a1SPavel Labath // The exact place where the parsing will stop depends on the structure of the 5016f55b5a1SPavel Labath // prologue and the last complete field we are able to read. Before V5 we stop 5026f55b5a1SPavel Labath // before reading the file length. In V5, we stop before the filename. 5036f55b5a1SPavel Labath uint64_t ExpectedEnd = Prologue.TotalLength + Prologue.sizeofTotalLength() - 5046f55b5a1SPavel Labath (Version < 5 ? 2 : 8); 505bf4d8f29SJames Henderson std::vector<std::string> Errs; 506bf4d8f29SJames Henderson Errs.emplace_back( 507bf4d8f29SJames Henderson (Twine("parsing line table prologue at 0x00000000 found an invalid " 508bf4d8f29SJames Henderson "directory or file table description at 0x000000") + 5096f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd)) 510bf4d8f29SJames Henderson .str()); 5116f55b5a1SPavel Labath if (Version < 5) { 512bf4d8f29SJames Henderson Errs.emplace_back("file names table was not null terminated before the end " 513bf4d8f29SJames Henderson "of the prologue"); 514c475856dSPavel Labath } else { 515bf4d8f29SJames Henderson Errs.emplace_back( 5169ed452f3SPavel Labath "failed to parse file entry because extracting the form value failed"); 517c475856dSPavel Labath } 5189b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5199b23024cSPavel Labath FailedWithMessageArray(testing::ElementsAreArray(Errs))); 520a3acf99eSJames Henderson } 521a3acf99eSJames Henderson 522d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 523a3acf99eSJames Henderson LineTableTestParams, DebugLineParameterisedFixture, 524a3acf99eSJames Henderson Values(std::make_pair( 525a3acf99eSJames Henderson 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 526a3acf99eSJames Henderson std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 527a3acf99eSJames Henderson std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 528d4d80a29SBenjamin Kramer std::make_pair(5, DWARF32), std::make_pair(5, DWARF64))); 529a3acf99eSJames Henderson 530d24e721dSJake Egan #ifdef _AIX 531d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 532d24e721dSJake Egan DISABLED_ErrorForExtendedOpcodeLengthSmallerThanExpected) { 533d24e721dSJake Egan #else 534f1be770fSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 535d24e721dSJake Egan #endif 536a3acf99eSJames Henderson if (!setupGenerator()) 537a3acf99eSJames Henderson return; 538a3acf99eSJames Henderson 539a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 540f1be770fSJames Henderson LT.addByte(0xaa); 541f1be770fSJames Henderson // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 542f1be770fSJames Henderson // The operand will be read for both the discriminator opcode and then parsed 543f1be770fSJames Henderson // again as DW_LNS_negate_stmt, to respect the claimed length. 544f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 545f1be770fSJames Henderson {{DW_LNS_negate_stmt, LineTable::ULEB}}); 546f1be770fSJames Henderson LT.addByte(0xbb); 547f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 548f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 549a3acf99eSJames Henderson 550a3acf99eSJames Henderson generate(); 551a3acf99eSJames Henderson 552f1be770fSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 553f1be770fSJames Henderson nullptr, RecordRecoverable); 5549b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5559b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 5569b23024cSPavel Labath "0x00000031 expected 0x01 found 0x02")); 557f1be770fSJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 558f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 559f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 560f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 561f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 562f1be770fSJames Henderson } 563f1be770fSJames Henderson 564d24e721dSJake Egan #ifdef _AIX 565d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 566d24e721dSJake Egan DISABLED_ErrorForExtendedOpcodeLengthLargerThanExpected) { 567d24e721dSJake Egan #else 568f1be770fSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 569d24e721dSJake Egan #endif 570f1be770fSJames Henderson if (!setupGenerator()) 571f1be770fSJames Henderson return; 572f1be770fSJames Henderson 573f1be770fSJames Henderson LineTable < = Gen->addLineTable(); 574f1be770fSJames Henderson LT.addByte(0xaa); 575f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 576f1be770fSJames Henderson // The Length should be 1 for an end sequence opcode. 577f1be770fSJames Henderson LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 578f1be770fSJames Henderson // The negate statement opcode will be skipped. 579f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 580f1be770fSJames Henderson LT.addByte(0xbb); 581f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 582f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 583f1be770fSJames Henderson 584f1be770fSJames Henderson generate(); 585f1be770fSJames Henderson 586f1be770fSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 587f1be770fSJames Henderson nullptr, RecordRecoverable); 5889b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5899b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 5909b23024cSPavel Labath "0x00000032 expected 0x02 found 0x01")); 591f1be770fSJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 592f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 593f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 594f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 595f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 596a3acf99eSJames Henderson } 597a3acf99eSJames Henderson 598d24e721dSJake Egan #ifdef _AIX 599d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForUnitLengthTooLarge) { 600d24e721dSJake Egan #else 601216796f2SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 602d24e721dSJake Egan #endif 603216796f2SJames Henderson if (!setupGenerator()) 604216796f2SJames Henderson return; 605216796f2SJames Henderson 606216796f2SJames Henderson LineTable &Padding = Gen->addLineTable(); 607216796f2SJames Henderson // Add some padding to show that a non-zero offset is handled correctly. 608216796f2SJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 609216796f2SJames Henderson LineTable < = Gen->addLineTable(); 610216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 611216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 612216796f2SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 613216796f2SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 6141271cde4SJames Henderson // Set the total length to 1 higher than the actual length. 6151271cde4SJames Henderson ++Prologue.TotalLength; 616216796f2SJames Henderson LT.setPrologue(Prologue); 617216796f2SJames Henderson 618216796f2SJames Henderson generate(); 619216796f2SJames Henderson 620216796f2SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 621216796f2SJames Henderson nullptr, RecordRecoverable); 6229b23024cSPavel Labath EXPECT_THAT_ERROR( 6239b23024cSPavel Labath std::move(Recoverable), 6249b23024cSPavel Labath FailedWithMessage("line table program with offset 0x00000001 has length " 6259b23024cSPavel Labath "0x00000034 but only 0x00000033 bytes are available")); 626216796f2SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 627216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 628216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 629216796f2SJames Henderson } 630216796f2SJames Henderson 631d24e721dSJake Egan #ifdef _AIX 632d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForMismatchedAddressSize) { 633d24e721dSJake Egan #else 634a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 635d24e721dSJake Egan #endif 63607804f75SJames Henderson if (!setupGenerator(4, 8)) 637a3acf99eSJames Henderson return; 638a3acf99eSJames Henderson 639a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 640a3acf99eSJames Henderson // The line data extractor expects size 8 (Quad) addresses. 64107804f75SJames Henderson uint64_t Addr1 = 0x11223344; 64207804f75SJames Henderson LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 643a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 64407804f75SJames Henderson // Show that the expected address size is unchanged, so later valid lines 64507804f75SJames Henderson // don't cause a problem. 64607804f75SJames Henderson uint64_t Addr2 = 0x1122334455667788; 64707804f75SJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 648a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 649a3acf99eSJames Henderson 650a3acf99eSJames Henderson generate(); 651a3acf99eSJames Henderson 65207804f75SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 65307804f75SJames Henderson nullptr, RecordRecoverable); 6549b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 6559b23024cSPavel Labath FailedWithMessage("mismatching address size at offset " 6569b23024cSPavel Labath "0x00000030 expected 0x08 found 0x04")); 65707804f75SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 65807804f75SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 65907804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 66007804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 66107804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 66207804f75SJames Henderson } 66307804f75SJames Henderson 664d24e721dSJake Egan #ifdef _AIX 665d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 666d24e721dSJake Egan DISABLED_ErrorForMismatchedAddressSizeUnsetInitialAddress) { 667d24e721dSJake Egan #else 66807804f75SJames Henderson TEST_F(DebugLineBasicFixture, 66907804f75SJames Henderson ErrorForMismatchedAddressSizeUnsetInitialAddress) { 670d24e721dSJake Egan #endif 67107804f75SJames Henderson if (!setupGenerator(4, 0)) 67207804f75SJames Henderson return; 67307804f75SJames Henderson 67407804f75SJames Henderson LineTable < = Gen->addLineTable(); 67507804f75SJames Henderson uint64_t Addr1 = 0x11223344; 67607804f75SJames Henderson LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 67707804f75SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 67807804f75SJames Henderson uint64_t Addr2 = 0x1122334455667788; 67907804f75SJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 68007804f75SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 68107804f75SJames Henderson 68207804f75SJames Henderson generate(); 68307804f75SJames Henderson 68407804f75SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 68507804f75SJames Henderson nullptr, RecordRecoverable); 6869b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 6879b23024cSPavel Labath FailedWithMessage("mismatching address size at offset " 6889b23024cSPavel Labath "0x00000038 expected 0x04 found 0x08")); 68907804f75SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 69007804f75SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 69107804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 69207804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 69307804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 694a3acf99eSJames Henderson } 695a3acf99eSJames Henderson 696d24e721dSJake Egan #ifdef _AIX 697d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 698d24e721dSJake Egan DISABLED_ErrorForUnsupportedAddressSizeInSetAddressLength) { 699d24e721dSJake Egan #else 700fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, 701fe6983a7SJames Henderson ErrorForUnsupportedAddressSizeInSetAddressLength) { 702d24e721dSJake Egan #endif 703fe6983a7SJames Henderson // Use DWARF v4, and 0 for data extractor address size so that the address 704fe6983a7SJames Henderson // size is derived from the opcode length. 705fe6983a7SJames Henderson if (!setupGenerator(4, 0)) 706fe6983a7SJames Henderson return; 707fe6983a7SJames Henderson 708fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 709fe6983a7SJames Henderson // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for 710fe6983a7SJames Henderson // the Half (2) + Byte (1) operand, representing the unsupported address size. 711fe6983a7SJames Henderson LT.addExtendedOpcode(4, DW_LNE_set_address, 712fe6983a7SJames Henderson {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}}); 713fe6983a7SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 714fe6983a7SJames Henderson // Special opcode to ensure the address has changed between the first and last 715fe6983a7SJames Henderson // row in the sequence. Without this, the sequence will not be recorded. 716fe6983a7SJames Henderson LT.addByte(0xaa); 717fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 718fe6983a7SJames Henderson 719fe6983a7SJames Henderson generate(); 720fe6983a7SJames Henderson 721fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 722fe6983a7SJames Henderson nullptr, RecordRecoverable); 7239b23024cSPavel Labath EXPECT_THAT_ERROR( 7249b23024cSPavel Labath std::move(Recoverable), 7259b23024cSPavel Labath FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at " 7269b23024cSPavel Labath "offset 0x00000030 is unsupported")); 727fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 728fe6983a7SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 729fe6983a7SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 730fe6983a7SJames Henderson // Show that the set address opcode is ignored in this case. 731a55dec7dSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 732fe6983a7SJames Henderson } 733fe6983a7SJames Henderson 734d24e721dSJake Egan #ifdef _AIX 735d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForAddressSizeGreaterThanByteSize) { 736d24e721dSJake Egan #else 737fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) { 738d24e721dSJake Egan #endif 739fe6983a7SJames Henderson // Use DWARF v4, and 0 for data extractor address size so that the address 740fe6983a7SJames Henderson // size is derived from the opcode length. 741fe6983a7SJames Henderson if (!setupGenerator(4, 0)) 742fe6983a7SJames Henderson return; 743fe6983a7SJames Henderson 744fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 745fe6983a7SJames Henderson // Specifically use an operand size that has a trailing byte of a supported 746fe6983a7SJames Henderson // size (8), so that any potential truncation would result in a valid size. 747fe6983a7SJames Henderson std::vector<LineTable::ValueAndLength> Operands(0x108); 748fe6983a7SJames Henderson LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands); 749fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 750fe6983a7SJames Henderson 751fe6983a7SJames Henderson generate(); 752fe6983a7SJames Henderson 753fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 754fe6983a7SJames Henderson nullptr, RecordRecoverable); 7559b23024cSPavel Labath EXPECT_THAT_ERROR( 7569b23024cSPavel Labath std::move(Recoverable), 7579b23024cSPavel Labath FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at " 7589b23024cSPavel Labath "offset 0x00000031 is unsupported")); 759fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 760fe6983a7SJames Henderson } 761fe6983a7SJames Henderson 762d24e721dSJake Egan #ifdef _AIX 763d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 764d24e721dSJake Egan DISABLED_ErrorForUnsupportedAddressSizeDefinedInHeader) { 765d24e721dSJake Egan #else 766fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) { 767d24e721dSJake Egan #endif 768fe6983a7SJames Henderson // Use 0 for data extractor address size so that it does not clash with the 769fe6983a7SJames Henderson // header address size. 770fe6983a7SJames Henderson if (!setupGenerator(5, 0)) 771fe6983a7SJames Henderson return; 772fe6983a7SJames Henderson 773fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 774fe6983a7SJames Henderson // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode 775fe6983a7SJames Henderson // itself and 9 for the Quad (8) + Byte (1) operand representing the 776fe6983a7SJames Henderson // unsupported address size. 777fe6983a7SJames Henderson uint8_t AddressSize = 9; 778fe6983a7SJames Henderson LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address, 779fe6983a7SJames Henderson {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}}); 780fe6983a7SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 781fe6983a7SJames Henderson // Special opcode to ensure the address has changed between the first and last 782fe6983a7SJames Henderson // row in the sequence. Without this, the sequence will not be recorded. 783fe6983a7SJames Henderson LT.addByte(0xaa); 784fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 785fe6983a7SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 786fe6983a7SJames Henderson Prologue.FormParams.AddrSize = AddressSize; 787fe6983a7SJames Henderson LT.setPrologue(Prologue); 788fe6983a7SJames Henderson 789fe6983a7SJames Henderson generate(); 790fe6983a7SJames Henderson 791fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 792fe6983a7SJames Henderson nullptr, RecordRecoverable); 7939b23024cSPavel Labath EXPECT_THAT_ERROR( 7949b23024cSPavel Labath std::move(Recoverable), 7959b23024cSPavel Labath FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at " 7969b23024cSPavel Labath "offset 0x00000038 is unsupported")); 797fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 798fe6983a7SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 799fe6983a7SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 800fe6983a7SJames Henderson // Show that the set address opcode is ignored in this case. 801a55dec7dSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 802fe6983a7SJames Henderson } 803fe6983a7SJames Henderson 804d24e721dSJake Egan #ifdef _AIX 805d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_CallbackUsedForUnterminatedSequence) { 806d24e721dSJake Egan #else 807a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 808d24e721dSJake Egan #endif 809a3acf99eSJames Henderson if (!setupGenerator()) 810a3acf99eSJames Henderson return; 811a3acf99eSJames Henderson 812a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 813a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 814a3acf99eSJames Henderson {{0x1122334455667788, LineTable::Quad}}); 815a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 816a3acf99eSJames Henderson LT.addByte(0xaa); 817a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 818a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 819a3acf99eSJames Henderson {{0x99aabbccddeeff00, LineTable::Quad}}); 820a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 821a3acf99eSJames Henderson LT.addByte(0xbb); 822a3acf99eSJames Henderson LT.addByte(0xcc); 823a3acf99eSJames Henderson 824a3acf99eSJames Henderson generate(); 825a3acf99eSJames Henderson 826004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 827004b729eSJames Henderson nullptr, RecordRecoverable); 8289b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 8299b23024cSPavel Labath FailedWithMessage("last sequence in debug line table at " 8309b23024cSPavel Labath "offset 0x00000000 is not terminated")); 8319b23024cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 832a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 833a3acf99eSJames Henderson // The unterminated sequence is not added to the sequence list. 834a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 835a3acf99eSJames Henderson } 836a3acf99eSJames Henderson 8378732192bSJames Henderson struct AdjustAddressFixtureBase : public CommonFixture { 8388732192bSJames Henderson virtual ~AdjustAddressFixtureBase() {} 8398732192bSJames Henderson 8408732192bSJames Henderson // Create and update the prologue as specified by the subclass, then return 8418732192bSJames Henderson // the length of the table. 8428732192bSJames Henderson virtual uint64_t editPrologue(LineTable <) = 0; 8438732192bSJames Henderson 8448732192bSJames Henderson virtual uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncrs, 8458732192bSJames Henderson uint64_t SpecialIncrs, 8468732192bSJames Henderson uint64_t AdvanceIncrs) { 8478732192bSJames Henderson return Base + ConstIncrs + SpecialIncrs + AdvanceIncrs; 8488732192bSJames Henderson } 8498732192bSJames Henderson 8508732192bSJames Henderson virtual uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) { 8518732192bSJames Henderson return Base + Incr; 8528732192bSJames Henderson } 8538732192bSJames Henderson 8548732192bSJames Henderson uint64_t setupNoProblemTable() { 8558732192bSJames Henderson LineTable &NoProblem = Gen->addLineTable(); 8568732192bSJames Henderson NoProblem.addExtendedOpcode(9, DW_LNE_set_address, 8578732192bSJames Henderson {{0xabcd, LineTable::Quad}}); 8588732192bSJames Henderson NoProblem.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8598732192bSJames Henderson return editPrologue(NoProblem); 8608732192bSJames Henderson } 8618732192bSJames Henderson 8628732192bSJames Henderson uint64_t setupConstAddPcFirstTable() { 8638732192bSJames Henderson LineTable &ConstAddPCFirst = Gen->addLineTable(); 8648732192bSJames Henderson ConstAddPCFirst.addExtendedOpcode(9, DW_LNE_set_address, 8658732192bSJames Henderson {{ConstAddPCAddr, LineTable::Quad}}); 8668732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8678732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8688732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_advance_pc, 8698732192bSJames Henderson {{0x10, LineTable::ULEB}}); 8708732192bSJames Henderson ConstAddPCFirst.addByte(0x21); // Special opcode, +1 op, +1 line. 8718732192bSJames Henderson ConstAddPCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8728732192bSJames Henderson return editPrologue(ConstAddPCFirst); 8738732192bSJames Henderson } 8748732192bSJames Henderson 8758732192bSJames Henderson uint64_t setupSpecialFirstTable() { 8768732192bSJames Henderson LineTable &SpecialFirst = Gen->addLineTable(); 8778732192bSJames Henderson SpecialFirst.addExtendedOpcode(9, DW_LNE_set_address, 8788732192bSJames Henderson {{SpecialAddr, LineTable::Quad}}); 8798732192bSJames Henderson SpecialFirst.addByte(0x22); // Special opcode, +1 op, +2 line. 8808732192bSJames Henderson SpecialFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8818732192bSJames Henderson SpecialFirst.addStandardOpcode(DW_LNS_advance_pc, 8828732192bSJames Henderson {{0x20, LineTable::ULEB}}); 8838732192bSJames Henderson SpecialFirst.addByte(0x23); // Special opcode, +1 op, +3 line. 8848732192bSJames Henderson SpecialFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8858732192bSJames Henderson return editPrologue(SpecialFirst); 8868732192bSJames Henderson } 8878732192bSJames Henderson 8888732192bSJames Henderson uint64_t setupAdvancePcFirstTable() { 8898732192bSJames Henderson LineTable &AdvancePCFirst = Gen->addLineTable(); 8908732192bSJames Henderson AdvancePCFirst.addExtendedOpcode(9, DW_LNE_set_address, 8918732192bSJames Henderson {{AdvancePCAddr, LineTable::Quad}}); 8928732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 8938732192bSJames Henderson {{0x30, LineTable::ULEB}}); 8948732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8958732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 8968732192bSJames Henderson {{0x40, LineTable::ULEB}}); 8978732192bSJames Henderson AdvancePCFirst.addByte(0x24); // Special opcode, +1 op, +4 line. 8988732192bSJames Henderson AdvancePCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8998732192bSJames Henderson return editPrologue(AdvancePCFirst); 9008732192bSJames Henderson } 9018732192bSJames Henderson 9028732192bSJames Henderson void setupTables(bool AddAdvancePCFirstTable) { 9038732192bSJames Henderson LineTable &Padding = Gen->addLineTable(); 9048732192bSJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 9058732192bSJames Henderson NoProblemOffset = 1; 9068732192bSJames Henderson 9078732192bSJames Henderson // Show that no warning is generated for the case where no 9088732192bSJames Henderson // DW_LNS_const_add_pc or special opcode is used. 9098732192bSJames Henderson ConstAddPCOffset = setupNoProblemTable() + NoProblemOffset; 9108732192bSJames Henderson 9118732192bSJames Henderson // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode 9128732192bSJames Henderson // and then not again. 9138732192bSJames Henderson SpecialOffset = setupConstAddPcFirstTable() + ConstAddPCOffset; 9148732192bSJames Henderson 9158732192bSJames Henderson // Show that the warning is emitted for the first special opcode and then 9168732192bSJames Henderson // not again. 9178732192bSJames Henderson AdvancePCOffset = setupSpecialFirstTable() + SpecialOffset; 9188732192bSJames Henderson 9198732192bSJames Henderson // Show that the warning is emitted for the first DW_LNS_advance_pc opcode 9208732192bSJames Henderson // (if requested) and then not again. 9218732192bSJames Henderson if (AddAdvancePCFirstTable) 9228732192bSJames Henderson setupAdvancePcFirstTable(); 9238732192bSJames Henderson } 9248732192bSJames Henderson 9258732192bSJames Henderson Expected<const DWARFDebugLine::LineTable *> 9268732192bSJames Henderson checkTable(uint64_t Offset, StringRef OpcodeType, const Twine &MsgSuffix) { 9278732192bSJames Henderson auto ExpectedTable = Line.getOrParseLineTable(LineData, Offset, *Context, 9288732192bSJames Henderson nullptr, RecordRecoverable); 9298732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9308732192bSJames Henderson if (!IsErrorExpected) { 9318732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 9328732192bSJames Henderson } else { 9338732192bSJames Henderson if (!ExpectedTable) 9348732192bSJames Henderson return ExpectedTable; 9358732192bSJames Henderson uint64_t ExpectedOffset = Offset + 9368732192bSJames Henderson (*ExpectedTable)->Prologue.getLength() + 9378732192bSJames Henderson 11; // 11 == size of DW_LNE_set_address. 9388732192bSJames Henderson std::string OffsetHex = Twine::utohexstr(Offset).str(); 9398732192bSJames Henderson std::string OffsetZeroes = std::string(8 - OffsetHex.size(), '0'); 9408732192bSJames Henderson std::string ExpectedHex = Twine::utohexstr(ExpectedOffset).str(); 9418732192bSJames Henderson std::string ExpectedZeroes = std::string(8 - ExpectedHex.size(), '0'); 9428732192bSJames Henderson EXPECT_THAT_ERROR( 9438732192bSJames Henderson std::move(Recoverable), 9448732192bSJames Henderson FailedWithMessage(("line table program at offset 0x" + OffsetZeroes + 9458732192bSJames Henderson OffsetHex + " contains a " + OpcodeType + 9468732192bSJames Henderson " opcode at offset 0x" + ExpectedZeroes + 9478732192bSJames Henderson ExpectedHex + ", " + MsgSuffix) 9488732192bSJames Henderson .str())); 9498732192bSJames Henderson } 9508732192bSJames Henderson return ExpectedTable; 9518732192bSJames Henderson } 9528732192bSJames Henderson 9538732192bSJames Henderson void runTest(bool CheckAdvancePC, Twine MsgSuffix) { 9548732192bSJames Henderson if (!setupGenerator(Version)) 9558732192bSJames Henderson return; 9568732192bSJames Henderson 9578732192bSJames Henderson setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC); 9588732192bSJames Henderson 9598732192bSJames Henderson generate(); 9608732192bSJames Henderson 9618732192bSJames Henderson auto ExpectedNoProblem = Line.getOrParseLineTable( 9628732192bSJames Henderson LineData, NoProblemOffset, *Context, nullptr, RecordRecoverable); 9638732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 9648732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9658732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedNoProblem, Succeeded()); 9668732192bSJames Henderson 9678732192bSJames Henderson auto ExpectedConstAddPC = 9688732192bSJames Henderson checkTable(ConstAddPCOffset, "DW_LNS_const_add_pc", MsgSuffix); 9698732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedConstAddPC, Succeeded()); 9708732192bSJames Henderson ASSERT_EQ((*ExpectedConstAddPC)->Rows.size(), 2u); 9718732192bSJames Henderson EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Address.Address, 9728732192bSJames Henderson getAdjustedAddr(ConstAddPCAddr, ConstIncr * 2, 0x1, 0x10)); 9738732192bSJames Henderson EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Line, getAdjustedLine(1, 1)); 9748732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9758732192bSJames Henderson 9768732192bSJames Henderson auto ExpectedSpecial = checkTable(SpecialOffset, "special", MsgSuffix); 9778732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedSpecial, Succeeded()); 9788732192bSJames Henderson ASSERT_EQ((*ExpectedSpecial)->Rows.size(), 3u); 9798732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[0].Address.Address, 9808732192bSJames Henderson getAdjustedAddr(SpecialAddr, 0, 1, 0)); 9818732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[0].Line, getAdjustedLine(1, 2)); 9828732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[1].Address.Address, 9838732192bSJames Henderson getAdjustedAddr(SpecialAddr, ConstIncr, 0x2, 0x20)); 9848732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[1].Line, getAdjustedLine(1, 5)); 9858732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9868732192bSJames Henderson 9878732192bSJames Henderson if (!CheckAdvancePC) 9888732192bSJames Henderson return; 9898732192bSJames Henderson 9908732192bSJames Henderson auto ExpectedAdvancePC = 9918732192bSJames Henderson checkTable(AdvancePCOffset, "DW_LNS_advance_pc", MsgSuffix); 9928732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedAdvancePC, Succeeded()); 9938732192bSJames Henderson ASSERT_EQ((*ExpectedAdvancePC)->Rows.size(), 2u); 9948732192bSJames Henderson EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Address.Address, 9958732192bSJames Henderson getAdjustedAddr(AdvancePCAddr, ConstIncr, 0x1, 0x70)); 9968732192bSJames Henderson EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Line, getAdjustedLine(1, 4)); 9978732192bSJames Henderson } 9988732192bSJames Henderson 9998732192bSJames Henderson uint64_t ConstIncr = 0x11; 10008732192bSJames Henderson uint64_t ConstAddPCAddr = 0x1234; 10018732192bSJames Henderson uint64_t SpecialAddr = 0x5678; 10028732192bSJames Henderson uint64_t AdvancePCAddr = 0xabcd; 10038732192bSJames Henderson uint64_t NoProblemOffset; 10048732192bSJames Henderson uint64_t ConstAddPCOffset; 10058732192bSJames Henderson uint64_t SpecialOffset; 10068732192bSJames Henderson uint64_t AdvancePCOffset; 10078732192bSJames Henderson 10088732192bSJames Henderson uint16_t Version = 4; 10098732192bSJames Henderson bool IsErrorExpected; 10108732192bSJames Henderson }; 10118732192bSJames Henderson 10128732192bSJames Henderson struct MaxOpsPerInstFixture 10138732192bSJames Henderson : TestWithParam<std::tuple<uint16_t, uint8_t, bool>>, 10148732192bSJames Henderson AdjustAddressFixtureBase { 10158732192bSJames Henderson void SetUp() override { 10168732192bSJames Henderson std::tie(Version, MaxOpsPerInst, IsErrorExpected) = GetParam(); 10178732192bSJames Henderson } 10188732192bSJames Henderson 10198732192bSJames Henderson uint64_t editPrologue(LineTable <) override { 10208732192bSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 10218732192bSJames Henderson Prologue.MaxOpsPerInst = MaxOpsPerInst; 10228732192bSJames Henderson LT.setPrologue(Prologue); 10238732192bSJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 10248732192bSJames Henderson } 10258732192bSJames Henderson 10268732192bSJames Henderson uint8_t MaxOpsPerInst; 10278732192bSJames Henderson }; 10288732192bSJames Henderson 1029d24e721dSJake Egan #ifdef _AIX 1030d24e721dSJake Egan TEST_P(MaxOpsPerInstFixture, DISABLED_MaxOpsPerInstProblemsReportedCorrectly) { 1031d24e721dSJake Egan #else 10328732192bSJames Henderson TEST_P(MaxOpsPerInstFixture, MaxOpsPerInstProblemsReportedCorrectly) { 1033d24e721dSJake Egan #endif 10348732192bSJames Henderson runTest(/*CheckAdvancePC=*/true, 10358732192bSJames Henderson "but the prologue maximum_operations_per_instruction value is " + 10368732192bSJames Henderson Twine(unsigned(MaxOpsPerInst)) + 10378732192bSJames Henderson ", which is unsupported. Assuming a value of 1 instead"); 10388732192bSJames Henderson } 10398732192bSJames Henderson 1040d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 10418732192bSJames Henderson MaxOpsPerInstParams, MaxOpsPerInstFixture, 10428732192bSJames Henderson Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error). 10438732192bSJames Henderson std::make_tuple(4, 0, true), // Test zero value for V4 (error). 10448732192bSJames Henderson std::make_tuple(4, 1, false), // Test good value for V4 (no error). 10458732192bSJames Henderson std::make_tuple( 1046d4d80a29SBenjamin Kramer 4, 2, true))); // Test one higher than permitted V4 (error). 10478732192bSJames Henderson 10486e0c9e46SJames Henderson struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>, 10496e0c9e46SJames Henderson AdjustAddressFixtureBase { 10506e0c9e46SJames Henderson void SetUp() override { std::tie(LineRange, IsErrorExpected) = GetParam(); } 10516e0c9e46SJames Henderson 10526e0c9e46SJames Henderson uint64_t editPrologue(LineTable <) override { 10536e0c9e46SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 10546e0c9e46SJames Henderson Prologue.LineRange = LineRange; 10556e0c9e46SJames Henderson LT.setPrologue(Prologue); 10566e0c9e46SJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 10576e0c9e46SJames Henderson } 10586e0c9e46SJames Henderson 10596e0c9e46SJames Henderson uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 10606e0c9e46SJames Henderson uint64_t SpecialIncr, 10616e0c9e46SJames Henderson uint64_t AdvanceIncr) override { 10626e0c9e46SJames Henderson if (LineRange == 0) 10636e0c9e46SJames Henderson return Base + AdvanceIncr; 10646e0c9e46SJames Henderson return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr, 10656e0c9e46SJames Henderson SpecialIncr, AdvanceIncr); 10666e0c9e46SJames Henderson } 10676e0c9e46SJames Henderson 10686e0c9e46SJames Henderson uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override { 10696e0c9e46SJames Henderson return LineRange != 0 10706e0c9e46SJames Henderson ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr) 10716e0c9e46SJames Henderson : Base; 10726e0c9e46SJames Henderson } 10736e0c9e46SJames Henderson 10746e0c9e46SJames Henderson uint8_t LineRange; 10756e0c9e46SJames Henderson }; 10766e0c9e46SJames Henderson 1077d24e721dSJake Egan #ifdef _AIX 1078d24e721dSJake Egan TEST_P(LineRangeFixture, DISABLED_LineRangeProblemsReportedCorrectly) { 1079d24e721dSJake Egan #else 10806e0c9e46SJames Henderson TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) { 1081d24e721dSJake Egan #endif 10826e0c9e46SJames Henderson runTest(/*CheckAdvancePC=*/false, 10836e0c9e46SJames Henderson "but the prologue line_range value is 0. The address and line will " 10846e0c9e46SJames Henderson "not be adjusted"); 10856e0c9e46SJames Henderson } 10866e0c9e46SJames Henderson 1087d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 10886e0c9e46SJames Henderson LineRangeParams, LineRangeFixture, 10896e0c9e46SJames Henderson Values(std::make_tuple(0, true), // Test zero value (error). 1090d4d80a29SBenjamin Kramer std::make_tuple(14, false))); // Test non-zero value (no error). 10916e0c9e46SJames Henderson 1092684d6fdeSJames Henderson struct BadMinInstLenFixture : TestWithParam<std::tuple<uint8_t, bool>>, 1093684d6fdeSJames Henderson AdjustAddressFixtureBase { 1094684d6fdeSJames Henderson void SetUp() override { 1095684d6fdeSJames Henderson std::tie(MinInstLength, IsErrorExpected) = GetParam(); 1096684d6fdeSJames Henderson } 1097684d6fdeSJames Henderson 1098684d6fdeSJames Henderson uint64_t editPrologue(LineTable <) override { 1099684d6fdeSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1100684d6fdeSJames Henderson Prologue.MinInstLength = MinInstLength; 1101684d6fdeSJames Henderson LT.setPrologue(Prologue); 1102684d6fdeSJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1103684d6fdeSJames Henderson } 1104684d6fdeSJames Henderson 1105684d6fdeSJames Henderson uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 1106684d6fdeSJames Henderson uint64_t SpecialIncr, 1107684d6fdeSJames Henderson uint64_t AdvanceIncr) override { 1108684d6fdeSJames Henderson return MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( 1109684d6fdeSJames Henderson Base, ConstIncr, SpecialIncr, AdvanceIncr) 1110684d6fdeSJames Henderson : Base; 1111684d6fdeSJames Henderson } 1112684d6fdeSJames Henderson 1113684d6fdeSJames Henderson uint8_t MinInstLength; 1114684d6fdeSJames Henderson }; 1115684d6fdeSJames Henderson 1116d24e721dSJake Egan #ifdef _AIX 1117d24e721dSJake Egan TEST_P(BadMinInstLenFixture, DISABLED_MinInstLengthProblemsReportedCorrectly) { 1118d24e721dSJake Egan #else 1119684d6fdeSJames Henderson TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) { 1120d24e721dSJake Egan #endif 1121684d6fdeSJames Henderson runTest(/*CheckAdvancePC=*/true, 1122684d6fdeSJames Henderson "but the prologue minimum_instruction_length value is 0, which " 1123684d6fdeSJames Henderson "prevents any address advancing"); 1124684d6fdeSJames Henderson } 1125684d6fdeSJames Henderson 1126d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 1127684d6fdeSJames Henderson BadMinInstLenParams, BadMinInstLenFixture, 1128684d6fdeSJames Henderson Values(std::make_tuple(0, true), // Test zero value (error). 1129d4d80a29SBenjamin Kramer std::make_tuple(1, false))); // Test non-zero value (no error). 1130684d6fdeSJames Henderson 1131d24e721dSJake Egan #ifdef _AIX 1132d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserParsesCorrectly) { 1133d24e721dSJake Egan #else 1134a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 1135d24e721dSJake Egan #endif 1136a3acf99eSJames Henderson if (!setupGenerator()) 1137a3acf99eSJames Henderson return; 1138a3acf99eSJames Henderson 1139a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 1140a3acf99eSJames Henderson 114111a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 1142a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1143a3acf99eSJames Henderson 1144004b729eSJames Henderson DWARFDebugLine::LineTable Parsed = 1145004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1146a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 114711a9de74SJames Henderson EXPECT_EQ(Parsed.Sequences.size(), 1u); 114811a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 1149a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1150a3acf99eSJames Henderson 1151a3acf99eSJames Henderson DWARFDebugLine::LineTable Parsed2 = 1152004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1153a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 115411a9de74SJames Henderson EXPECT_EQ(Parsed2.Sequences.size(), 1u); 115511a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 1156a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1157a3acf99eSJames Henderson 1158004b729eSJames Henderson EXPECT_FALSE(Recoverable); 1159004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1160a3acf99eSJames Henderson } 1161a3acf99eSJames Henderson 1162d24e721dSJake Egan #ifdef _AIX 1163d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserSkipsCorrectly) { 1164d24e721dSJake Egan #else 1165a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 1166d24e721dSJake Egan #endif 1167a3acf99eSJames Henderson if (!setupGenerator()) 1168a3acf99eSJames Henderson return; 1169a3acf99eSJames Henderson 1170a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 1171a3acf99eSJames Henderson 117211a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 1173a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1174a3acf99eSJames Henderson 11757116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 117611a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 1177a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1178a3acf99eSJames Henderson 11797116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 118011a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 1181a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1182a3acf99eSJames Henderson 11837116e431SJames Henderson EXPECT_FALSE(Recoverable); 1184004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1185a3acf99eSJames Henderson } 1186a3acf99eSJames Henderson 1187d24e721dSJake Egan #ifdef _AIX 1188d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserAlwaysDoneForEmptySection) { 1189d24e721dSJake Egan #else 1190a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 1191d24e721dSJake Egan #endif 1192a3acf99eSJames Henderson if (!setupGenerator()) 1193a3acf99eSJames Henderson return; 1194a3acf99eSJames Henderson 1195a3acf99eSJames Henderson generate(); 119651a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1197a3acf99eSJames Henderson 1198a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1199a3acf99eSJames Henderson } 1200a3acf99eSJames Henderson 1201d24e721dSJake Egan #ifdef _AIX 1202d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1203d24e721dSJake Egan DISABLED_ParserMarkedAsDoneForBadLengthWhenParsing) { 1204d24e721dSJake Egan #else 1205d978656fSPavel Labath TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) { 1206d24e721dSJake Egan #endif 1207a3acf99eSJames Henderson if (!setupGenerator()) 1208a3acf99eSJames Henderson return; 1209a3acf99eSJames Henderson 1210a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 1211f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1212a3acf99eSJames Henderson Gen->addLineTable(); 1213a3acf99eSJames Henderson generate(); 1214a3acf99eSJames Henderson 121551a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1216004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1217a3acf99eSJames Henderson 1218d978656fSPavel Labath EXPECT_EQ(Parser.getOffset(), 0u); 1219a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1220004b729eSJames Henderson EXPECT_FALSE(Recoverable); 1221a3acf99eSJames Henderson 12229b23024cSPavel Labath EXPECT_THAT_ERROR( 12239b23024cSPavel Labath std::move(Unrecoverable), 12249b23024cSPavel Labath FailedWithMessage( 1225d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 1226d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 1227a3acf99eSJames Henderson } 1228a3acf99eSJames Henderson 1229d24e721dSJake Egan #ifdef _AIX 1230d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1231d24e721dSJake Egan DISABLED_ParserMarkedAsDoneForBadLengthWhenSkipping) { 1232d24e721dSJake Egan #else 1233d978656fSPavel Labath TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) { 1234d24e721dSJake Egan #endif 1235a3acf99eSJames Henderson if (!setupGenerator()) 1236a3acf99eSJames Henderson return; 1237a3acf99eSJames Henderson 1238a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 1239f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1240a3acf99eSJames Henderson Gen->addLineTable(); 1241a3acf99eSJames Henderson generate(); 1242a3acf99eSJames Henderson 124351a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 12447116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1245a3acf99eSJames Henderson 1246d978656fSPavel Labath EXPECT_EQ(Parser.getOffset(), 0u); 1247a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 12487116e431SJames Henderson EXPECT_FALSE(Recoverable); 1249a3acf99eSJames Henderson 12509b23024cSPavel Labath EXPECT_THAT_ERROR( 12519b23024cSPavel Labath std::move(Unrecoverable), 12529b23024cSPavel Labath FailedWithMessage( 1253d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 1254d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 1255a3acf99eSJames Henderson } 1256a3acf99eSJames Henderson 1257d24e721dSJake Egan #ifdef _AIX 1258d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1259d24e721dSJake Egan DISABLED_ParserReportsFirstErrorInEachTableWhenParsing) { 1260d24e721dSJake Egan #else 1261a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 1262d24e721dSJake Egan #endif 1263a3acf99eSJames Henderson if (!setupGenerator()) 1264a3acf99eSJames Henderson return; 1265a3acf99eSJames Henderson 1266a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1267a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1268a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1269a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1270a3acf99eSJames Henderson generate(); 1271a3acf99eSJames Henderson 127251a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1273004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1274a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1275004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1276a3acf99eSJames Henderson 1277a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 12789b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1279a3acf99eSJames Henderson 12809b23024cSPavel Labath EXPECT_THAT_ERROR( 12819b23024cSPavel Labath std::move(Unrecoverable), 1282d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1283d978656fSPavel Labath "unsupported version 0", 1284d978656fSPavel Labath "parsing line table prologue at offset 0x00000006: " 1285d978656fSPavel Labath "unsupported version 1")); 1286a3acf99eSJames Henderson } 1287a3acf99eSJames Henderson 1288d24e721dSJake Egan #ifdef _AIX 1289d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1290d24e721dSJake Egan DISABLED_ParserReportsNonPrologueProblemsWhenParsing) { 1291d24e721dSJake Egan #else 1292a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 1293d24e721dSJake Egan #endif 1294a3acf99eSJames Henderson if (!setupGenerator()) 1295a3acf99eSJames Henderson return; 1296a3acf99eSJames Henderson 1297a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1298a3acf99eSJames Henderson LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 1299a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1300a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 1301a3acf99eSJames Henderson {{0x1234567890abcdef, LineTable::Quad}}); 1302a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 1303a3acf99eSJames Henderson LT2.addByte(0xbb); 1304a3acf99eSJames Henderson generate(); 1305a3acf99eSJames Henderson 130651a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1307004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1308f1be770fSJames Henderson EXPECT_FALSE(Unrecoverable); 1309a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 13109b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 13119b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 13129b23024cSPavel Labath "0x00000030 expected 0x42 found 0x01")); 1313a3acf99eSJames Henderson 1314a3acf99eSJames Henderson // Reset the error state so that it does not confuse the next set of checks. 1315004b729eSJames Henderson Unrecoverable = Error::success(); 1316004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1317a3acf99eSJames Henderson 1318a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13199b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 13209b23024cSPavel Labath FailedWithMessage("last sequence in debug line table at " 13219b23024cSPavel Labath "offset 0x00000031 is not terminated")); 1322004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1323a3acf99eSJames Henderson } 1324a3acf99eSJames Henderson 1325d24e721dSJake Egan #ifdef _AIX 1326d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1327d24e721dSJake Egan DISABLED_ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1328d24e721dSJake Egan #else 1329a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, 1330a3acf99eSJames Henderson ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1331d24e721dSJake Egan #endif 1332a3acf99eSJames Henderson if (!setupGenerator()) 1333a3acf99eSJames Henderson return; 1334a3acf99eSJames Henderson 1335a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1336a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1337a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1338a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1339a3acf99eSJames Henderson generate(); 1340a3acf99eSJames Henderson 134151a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 13427116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1343a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 13447116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1345a3acf99eSJames Henderson 1346a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13477116e431SJames Henderson EXPECT_FALSE(Recoverable); 1348a3acf99eSJames Henderson 13499b23024cSPavel Labath EXPECT_THAT_ERROR( 13509b23024cSPavel Labath std::move(Unrecoverable), 1351d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1352d978656fSPavel Labath "unsupported version 0", 1353d978656fSPavel Labath "parsing line table prologue at offset 0x00000006: " 1354d978656fSPavel Labath "unsupported version 1")); 1355a3acf99eSJames Henderson } 1356a3acf99eSJames Henderson 1357d24e721dSJake Egan #ifdef _AIX 1358d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1359d24e721dSJake Egan DISABLED_ParserIgnoresNonPrologueErrorsWhenSkipping) { 1360d24e721dSJake Egan #else 1361a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 1362d24e721dSJake Egan #endif 1363a3acf99eSJames Henderson if (!setupGenerator()) 1364a3acf99eSJames Henderson return; 1365a3acf99eSJames Henderson 1366a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1367a3acf99eSJames Henderson LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 1368a3acf99eSJames Henderson generate(); 1369a3acf99eSJames Henderson 137051a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 13717116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1372a3acf99eSJames Henderson 1373a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13747116e431SJames Henderson EXPECT_FALSE(Recoverable); 1375004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 137666702629SJames Henderson } 137766702629SJames Henderson 1378d24e721dSJake Egan #ifdef _AIX 1379d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_VerboseOutput) { 1380d24e721dSJake Egan #else 1381e3547adeSJames Henderson TEST_F(DebugLineBasicFixture, VerboseOutput) { 1382d24e721dSJake Egan #endif 1383e3547adeSJames Henderson if (!setupGenerator(5)) 13842f815502SJames Henderson return; 13852f815502SJames Henderson 1386e3547adeSJames Henderson LineTable < = Gen->addLineTable(); 1387e3547adeSJames Henderson LT.addByte(0); // Extended opcode with zero length. 1388e3547adeSJames Henderson LT.addByte(0); 1389e3547adeSJames Henderson // Zero-value extended opcode. 1390e3547adeSJames Henderson LT.addExtendedOpcode(2, 0, {{1, LineTable::Byte}}); 1391e3547adeSJames Henderson // Unknown extended opcode. 1392e3547adeSJames Henderson LT.addExtendedOpcode(2, 0x42, {{1, LineTable::Byte}}); 1393e3547adeSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 1394e3547adeSJames Henderson {{0x123456789abcdef, LineTable::Quad}}); 1395e3547adeSJames Henderson LT.addExtendedOpcode(6, DW_LNE_define_file, 1396e3547adeSJames Henderson {{'a', LineTable::Byte}, 1397e3547adeSJames Henderson {'\0', LineTable::Byte}, 1398e3547adeSJames Henderson {2, LineTable::ULEB}, 1399e3547adeSJames Henderson {3, LineTable::ULEB}, 1400e3547adeSJames Henderson {4, LineTable::ULEB}}); 1401e3547adeSJames Henderson LT.addExtendedOpcode(2, DW_LNE_set_discriminator, {{0x7f, LineTable::ULEB}}); 14022f815502SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 1403e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_advance_pc, {{11, LineTable::ULEB}}); 1404e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_advance_line, {{22, LineTable::SLEB}}); 1405e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_file, {{33, LineTable::ULEB}}); 1406e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_column, {{44, LineTable::ULEB}}); 14072f815502SJames Henderson LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 14082f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 14092f815502SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 1410e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{55, LineTable::Half}}); 14112f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 14122f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 1413e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_isa, {{66, LineTable::ULEB}}); 14143b7ec64dSJames Henderson // Add unknown standard opcode with operands. 1415e3547adeSJames Henderson LT.addStandardOpcode( 1416e3547adeSJames Henderson 0xd, {{1, LineTable::ULEB}, {0x123456789abcdef, LineTable::ULEB}}); 14173b7ec64dSJames Henderson // Add unknown standard opcode without operands. 14183b7ec64dSJames Henderson LT.addStandardOpcode(0xe, {}); 1419e3547adeSJames Henderson LT.addByte(0xff); // Special opcode. 14202f815502SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 1421e3547adeSJames Henderson 1422e3547adeSJames Henderson // Adjust the prologue to account for the extra standard opcode. 1423e3547adeSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 14243b7ec64dSJames Henderson Prologue.TotalLength += 2; 14253b7ec64dSJames Henderson Prologue.PrologueLength += 2; 14263b7ec64dSJames Henderson Prologue.OpcodeBase += 2; 1427e3547adeSJames Henderson Prologue.StandardOpcodeLengths.push_back(2); 14283b7ec64dSJames Henderson Prologue.StandardOpcodeLengths.push_back(0); 1429e3547adeSJames Henderson LT.setPrologue(Prologue); 1430e3547adeSJames Henderson 14312f815502SJames Henderson generate(); 14322f815502SJames Henderson 143351a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 14342f815502SJames Henderson std::string Output; 14352f815502SJames Henderson raw_string_ostream OS(Output); 1436dbd26fe0SJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1437dbd26fe0SJames Henderson /*Verbose=*/true); 14382f815502SJames Henderson OS.flush(); 1439e3547adeSJames Henderson StringRef OutputRef(Output); 14402f815502SJames Henderson 1441e3547adeSJames Henderson size_t Pos = 0; 1442e3547adeSJames Henderson auto NextLine = [&Pos, &OutputRef]() { 1443e3547adeSJames Henderson size_t EOL = OutputRef.find_first_of('\n', Pos); 1444e3547adeSJames Henderson StringRef Line = OutputRef.substr(Pos, EOL - Pos); 1445e3547adeSJames Henderson Pos = EOL + 1; 1446e3547adeSJames Henderson return Line; 14472f815502SJames Henderson }; 1448e3547adeSJames Henderson EXPECT_EQ(NextLine(), "Line table prologue:"); 14493b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " total_length: 0x00000078"); 1450e3547adeSJames Henderson EXPECT_EQ(NextLine(), " format: DWARF32"); 1451e3547adeSJames Henderson EXPECT_EQ(NextLine(), " version: 5"); 1452e3547adeSJames Henderson EXPECT_EQ(NextLine(), " address_size: 8"); 1453e3547adeSJames Henderson EXPECT_EQ(NextLine(), " seg_select_size: 0"); 14543b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " prologue_length: 0x0000002c"); 1455e3547adeSJames Henderson EXPECT_EQ(NextLine(), " min_inst_length: 1"); 1456e3547adeSJames Henderson EXPECT_EQ(NextLine(), "max_ops_per_inst: 1"); 1457e3547adeSJames Henderson EXPECT_EQ(NextLine(), " default_is_stmt: 1"); 1458e3547adeSJames Henderson EXPECT_EQ(NextLine(), " line_base: -5"); 1459e3547adeSJames Henderson EXPECT_EQ(NextLine(), " line_range: 14"); 14603b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " opcode_base: 15"); 1461e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_copy] = 0"); 1462e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_pc] = 1"); 1463e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_line] = 1"); 1464e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_file] = 1"); 1465e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_column] = 1"); 1466e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_negate_stmt] = 0"); 1467e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_basic_block] = 0"); 1468e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_const_add_pc] = 0"); 1469e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1"); 1470e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_prologue_end] = 0"); 1471e3547adeSJames Henderson EXPECT_EQ(NextLine(), 1472e3547adeSJames Henderson "standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0"); 1473e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_isa] = 1"); 1474e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_d] = 2"); 14753b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_e] = 0"); 1476e3547adeSJames Henderson EXPECT_EQ(NextLine(), "include_directories[ 0] = \"a dir\""); 1477e3547adeSJames Henderson EXPECT_EQ(NextLine(), "file_names[ 0]:"); 1478e3547adeSJames Henderson EXPECT_EQ(NextLine(), " name: \"a file\""); 1479e3547adeSJames Henderson EXPECT_EQ(NextLine(), " dir_index: 0"); 1480e3547adeSJames Henderson EXPECT_EQ(NextLine(), ""); 1481e3547adeSJames Henderson EXPECT_EQ(NextLine(), " Address Line Column File ISA Discriminator Flags"); 1482e3547adeSJames Henderson EXPECT_EQ(NextLine(), " ------------------ ------ ------ ------ --- ------------- -------------"); 1483e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14843b7ec64dSJames Henderson "0x00000038: 00 Badly formed extended line op (length 0)"); 1485e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14863b7ec64dSJames Henderson "0x0000003a: 00 Unrecognized extended op 0x00 length 2"); 1487e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14883b7ec64dSJames Henderson "0x0000003e: 00 Unrecognized extended op 0x42 length 2"); 1489e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14903b7ec64dSJames Henderson "0x00000042: 00 DW_LNE_set_address (0x0123456789abcdef)"); 14913b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000004d: 00 DW_LNE_define_file (a, dir=2, " 1492e3547adeSJames Henderson "mod_time=(0x0000000000000003), length=4)"); 14933b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000055: 00 DW_LNE_set_discriminator (127)"); 14943b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy"); 1495e3547adeSJames Henderson EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 " 1496e3547adeSJames Henderson "0 127 is_stmt"); 14973b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (11)"); 14983b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)"); 14993b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)"); 15003b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)"); 15013b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt"); 15023b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block"); 1503e3547adeSJames Henderson EXPECT_EQ(NextLine(), 15043b7ec64dSJames Henderson "0x00000064: 08 DW_LNS_const_add_pc (0x0000000000000011)"); 15053b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (0x0037)"); 15063b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end"); 15073b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin"); 15083b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)"); 15093b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode " 15103b7ec64dSJames Henderson "(operands: 0x0000000000000001, 0x0123456789abcdef)"); 15113b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode"); 15123b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3"); 1513e3547adeSJames Henderson EXPECT_EQ(NextLine(), 15143b7ec64dSJames Henderson " 0x0123456789abce53 20 44 33 66 " 1515e3547adeSJames Henderson " 0 basic_block prologue_end epilogue_begin"); 15163b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000079: 00 DW_LNE_end_sequence"); 15173b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " 0x0123456789abce53 20 44 33 " 1518e3547adeSJames Henderson "66 0 end_sequence"); 1519e3547adeSJames Henderson EXPECT_EQ(NextLine(), ""); 1520e3547adeSJames Henderson EXPECT_EQ(Output.size(), Pos); 15212f815502SJames Henderson } 15222f815502SJames Henderson 15239e09a54cSJames Henderson struct TruncatedPrologueFixture 15249e09a54cSJames Henderson : public TestWithParam< 15259e09a54cSJames Henderson std::tuple<uint64_t, uint64_t, uint16_t, DwarfFormat, StringRef>>, 15269e09a54cSJames Henderson public CommonFixture { 152731eb8349SLogan Smith void SetUp() override { 15289e09a54cSJames Henderson std::tie(Length, ExpectedOffset, Version, Format, ExpectedErr) = GetParam(); 15299e09a54cSJames Henderson } 15309e09a54cSJames Henderson 15319e09a54cSJames Henderson uint64_t Length; 15329e09a54cSJames Henderson uint64_t ExpectedOffset; 15339e09a54cSJames Henderson uint16_t Version; 15349e09a54cSJames Henderson DwarfFormat Format; 15359e09a54cSJames Henderson StringRef ExpectedErr; 15369e09a54cSJames Henderson }; 15379e09a54cSJames Henderson 1538d24e721dSJake Egan #ifdef _AIX 1539d24e721dSJake Egan TEST_P(TruncatedPrologueFixture, DISABLED_ErrorForTruncatedPrologue) { 1540d24e721dSJake Egan #else 15419e09a54cSJames Henderson TEST_P(TruncatedPrologueFixture, ErrorForTruncatedPrologue) { 1542d24e721dSJake Egan #endif 15439e09a54cSJames Henderson if (!setupGenerator(Version)) 15449e09a54cSJames Henderson return; 15459e09a54cSJames Henderson 15469e09a54cSJames Henderson LineTable &Padding = Gen->addLineTable(); 15479e09a54cSJames Henderson // Add some padding to show that a non-zero offset is handled correctly. 15489e09a54cSJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 15499e09a54cSJames Henderson 15509e09a54cSJames Henderson // Add a table with only two standard opcodes - we don't need to test the full 15519e09a54cSJames Henderson // set. 15529e09a54cSJames Henderson LineTable &Table = Gen->addLineTable(Format); 15539e09a54cSJames Henderson DWARFDebugLine::Prologue InputPrologue = Table.createBasicPrologue(); 15549e09a54cSJames Henderson InputPrologue.OpcodeBase = 3; 15559e09a54cSJames Henderson InputPrologue.StandardOpcodeLengths.resize(2); 15569e09a54cSJames Henderson Table.setPrologue(InputPrologue); 15579e09a54cSJames Henderson 15589e09a54cSJames Henderson generate(); 15599e09a54cSJames Henderson // Truncate the data extractor to the specified length. 15609e09a54cSJames Henderson LineData = DWARFDataExtractor(LineData, Length); 15619e09a54cSJames Henderson 15629e09a54cSJames Henderson DWARFDebugLine::Prologue Prologue; 15639e09a54cSJames Henderson uint64_t Offset = 1; 15649e09a54cSJames Henderson Error Err = Prologue.parse(LineData, &Offset, RecordRecoverable, *Context); 15659e09a54cSJames Henderson 15669e09a54cSJames Henderson EXPECT_THAT_ERROR(std::move(Err), FailedWithMessage(ExpectedErr.str())); 15679e09a54cSJames Henderson EXPECT_EQ(Offset, ExpectedOffset); 15689e09a54cSJames Henderson } 15699e09a54cSJames Henderson 1570d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 15719e09a54cSJames Henderson TruncatedPrologueParams, TruncatedPrologueFixture, 15729e09a54cSJames Henderson Values( 15739e09a54cSJames Henderson // Truncated length: 15749e09a54cSJames Henderson std::make_tuple( 15759e09a54cSJames Henderson 4, 1, 4, DWARF32, 15769e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15779e09a54cSJames Henderson "of data at offset 0x4 while reading [0x1, 0x5)"), 15789e09a54cSJames Henderson std::make_tuple( 15799e09a54cSJames Henderson 4, 1, 4, DWARF64, 15809e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15819e09a54cSJames Henderson "of data at offset 0x4 while reading [0x1, 0x5)"), 15829e09a54cSJames Henderson std::make_tuple( 15839e09a54cSJames Henderson 0xc, 1, 4, DWARF64, 15849e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15859e09a54cSJames Henderson "of data at offset 0xc while reading [0x5, 0xd)"), 15869e09a54cSJames Henderson // Truncated version: 15879e09a54cSJames Henderson std::make_tuple( 15889e09a54cSJames Henderson 6, 5, 4, DWARF32, 15899e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15909e09a54cSJames Henderson "of data at offset 0x6 while reading [0x5, 0x7)"), 15919e09a54cSJames Henderson // Truncated address size: 15929e09a54cSJames Henderson std::make_tuple( 15939e09a54cSJames Henderson 7, 7, 5, DWARF32, 15949e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15959e09a54cSJames Henderson "of data at offset 0x7 while reading [0x7, 0x8)"), 15969e09a54cSJames Henderson // Truncated segment selector size: 15979e09a54cSJames Henderson std::make_tuple( 15989e09a54cSJames Henderson 8, 8, 5, DWARF32, 15999e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16009e09a54cSJames Henderson "of data at offset 0x8 while reading [0x8, 0x9)"), 16019e09a54cSJames Henderson // Truncated prologue length: 16029e09a54cSJames Henderson std::make_tuple( 16039e09a54cSJames Henderson 0xa, 7, 4, DWARF32, 16049e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16059e09a54cSJames Henderson "of data at offset 0xa while reading [0x7, 0xb)"), 16069e09a54cSJames Henderson std::make_tuple( 16079e09a54cSJames Henderson 0x16, 0xf, 4, DWARF64, 16089e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16099e09a54cSJames Henderson "of data at offset 0x16 while reading [0xf, 0x17)"), 16109e09a54cSJames Henderson // Truncated min instruction length: 16119e09a54cSJames Henderson std::make_tuple( 16129e09a54cSJames Henderson 0xb, 0xb, 4, DWARF32, 16139e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16149e09a54cSJames Henderson "of data at offset 0xb while reading [0xb, 0xc)"), 16159e09a54cSJames Henderson // Truncated max ops per inst: 16169e09a54cSJames Henderson std::make_tuple( 16179e09a54cSJames Henderson 0xc, 0xc, 4, DWARF32, 16189e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16199e09a54cSJames Henderson "of data at offset 0xc while reading [0xc, 0xd)"), 16209e09a54cSJames Henderson // Truncated default is stmt: 16219e09a54cSJames Henderson std::make_tuple( 16229e09a54cSJames Henderson 0xd, 0xd, 4, DWARF32, 16239e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16249e09a54cSJames Henderson "of data at offset 0xd while reading [0xd, 0xe)"), 16259e09a54cSJames Henderson // Truncated line base: 16269e09a54cSJames Henderson std::make_tuple( 16279e09a54cSJames Henderson 0xe, 0xe, 4, DWARF32, 16289e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16299e09a54cSJames Henderson "of data at offset 0xe while reading [0xe, 0xf)"), 16309e09a54cSJames Henderson // Truncated line range: 16319e09a54cSJames Henderson std::make_tuple( 16329e09a54cSJames Henderson 0xf, 0xf, 4, DWARF32, 16339e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16349e09a54cSJames Henderson "of data at offset 0xf while reading [0xf, 0x10)"), 16359e09a54cSJames Henderson // Truncated opcode base: 16369e09a54cSJames Henderson std::make_tuple( 16379e09a54cSJames Henderson 0x10, 0x10, 4, DWARF32, 16389e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16399e09a54cSJames Henderson "of data at offset 0x10 while reading [0x10, 0x11)"), 16409e09a54cSJames Henderson // Truncated first standard opcode: 16419e09a54cSJames Henderson std::make_tuple( 16429e09a54cSJames Henderson 0x11, 0x11, 4, DWARF32, 16439e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16449e09a54cSJames Henderson "of data at offset 0x11 while reading [0x11, 0x12)"), 16459e09a54cSJames Henderson // Truncated second standard opcode: 16469e09a54cSJames Henderson std::make_tuple( 16479e09a54cSJames Henderson 0x12, 0x12, 4, DWARF32, 16489e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 1649d4d80a29SBenjamin Kramer "of data at offset 0x12 while reading [0x12, 0x13)"))); 16509e09a54cSJames Henderson 16515777570dSJames Henderson using ValueAndLengths = std::vector<LineTable::ValueAndLength>; 16525777570dSJames Henderson 16531a789047SJames Henderson struct TruncatedOpcodeFixtureBase : public CommonFixture { 16541a789047SJames Henderson LineTable &setupTable() { 16555777570dSJames Henderson LineTable < = Gen->addLineTable(); 16561a789047SJames Henderson 16571a789047SJames Henderson // Creating the prologue before adding any opcodes ensures that the unit 16585777570dSJames Henderson // length does not include the table body. 16595777570dSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 16605777570dSJames Henderson 16611a789047SJames Henderson // Add an unrecognised standard opcode, and adjust prologue properties 16621a789047SJames Henderson // accordingly. 16631a789047SJames Henderson Prologue.TotalLength += BodyLength + 1; 16641a789047SJames Henderson ++Prologue.PrologueLength; 16651a789047SJames Henderson ++Prologue.OpcodeBase; 16661a789047SJames Henderson Prologue.StandardOpcodeLengths.push_back(2); 16671a789047SJames Henderson LT.setPrologue(Prologue); 16681a789047SJames Henderson 16691a789047SJames Henderson return LT; 16701a789047SJames Henderson } 16711a789047SJames Henderson 16721a789047SJames Henderson void runTest(uint8_t OpcodeValue) { 16731a789047SJames Henderson generate(); 167451a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 16755777570dSJames Henderson std::string Output; 16765777570dSJames Henderson raw_string_ostream OS(Output); 1677dbd26fe0SJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1678dbd26fe0SJames Henderson /*Verbose=*/true); 16795777570dSJames Henderson OS.flush(); 16805777570dSJames Henderson 16811a789047SJames Henderson std::string LinePrefix = 16821a789047SJames Henderson ("0x0000002f: 0" + Twine::utohexstr(OpcodeValue) + " ").str(); 16835777570dSJames Henderson StringRef OutputRef(Output); 16845777570dSJames Henderson StringRef OutputToCheck = OutputRef.split(LinePrefix).second; 1685dbd26fe0SJames Henderson // Each extended opcode ends with a new line and then the table ends with an 1686dbd26fe0SJames Henderson // additional blank line. 1687dbd26fe0SJames Henderson EXPECT_EQ((ExpectedOutput + "\n\n").str(), OutputToCheck); 16885777570dSJames Henderson } 16895777570dSJames Henderson 16905777570dSJames Henderson uint64_t BodyLength; 16915777570dSJames Henderson uint8_t Opcode; 16925777570dSJames Henderson ValueAndLengths Operands; 16935777570dSJames Henderson StringRef ExpectedOutput; 16945777570dSJames Henderson StringRef ExpectedErr; 16955777570dSJames Henderson }; 16965777570dSJames Henderson 16971a789047SJames Henderson struct TruncatedStandardOpcodeFixture 16981a789047SJames Henderson : public TestWithParam< 16991a789047SJames Henderson std::tuple<uint64_t, uint8_t, ValueAndLengths, StringRef, StringRef>>, 17001a789047SJames Henderson public TruncatedOpcodeFixtureBase { 170131eb8349SLogan Smith void SetUp() override { 17021a789047SJames Henderson std::tie(BodyLength, Opcode, Operands, ExpectedOutput, ExpectedErr) = 17031a789047SJames Henderson GetParam(); 17041a789047SJames Henderson } 17051a789047SJames Henderson }; 17061a789047SJames Henderson 17071a789047SJames Henderson struct TruncatedExtendedOpcodeFixture 17081a789047SJames Henderson : public TestWithParam<std::tuple<uint64_t, uint64_t, uint8_t, 17091a789047SJames Henderson ValueAndLengths, StringRef, StringRef>>, 17101a789047SJames Henderson public TruncatedOpcodeFixtureBase { 171131eb8349SLogan Smith void SetUp() override { 17121a789047SJames Henderson std::tie(BodyLength, OpcodeLength, Opcode, Operands, ExpectedOutput, 17131a789047SJames Henderson ExpectedErr) = GetParam(); 17141a789047SJames Henderson } 17151a789047SJames Henderson 17161a789047SJames Henderson uint64_t OpcodeLength; 17171a789047SJames Henderson }; 17181a789047SJames Henderson 1719d24e721dSJake Egan #ifdef _AIX 1720d24e721dSJake Egan TEST_P(TruncatedExtendedOpcodeFixture, 1721d24e721dSJake Egan DISABLED_ErrorForTruncatedExtendedOpcode) { 1722d24e721dSJake Egan #else 17235777570dSJames Henderson TEST_P(TruncatedExtendedOpcodeFixture, ErrorForTruncatedExtendedOpcode) { 1724d24e721dSJake Egan #endif 17255777570dSJames Henderson if (!setupGenerator()) 17265777570dSJames Henderson return; 17271a789047SJames Henderson LineTable < = setupTable(); 17281a789047SJames Henderson LT.addExtendedOpcode(OpcodeLength, Opcode, Operands); 17291a789047SJames Henderson runTest(0); 17301a789047SJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), 17311a789047SJames Henderson FailedWithMessage(ExpectedErr.str())); 17325777570dSJames Henderson } 17335777570dSJames Henderson 1734d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 17355777570dSJames Henderson TruncatedExtendedOpcodeParams, TruncatedExtendedOpcodeFixture, 17365777570dSJames Henderson Values( 17379782c922SJames Henderson // Truncated length: 17389782c922SJames Henderson std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 17391a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 17405777570dSJames Henderson "malformed uleb128, extends past end"), 17419782c922SJames Henderson // Truncated opcode: 17425777570dSJames Henderson std::make_tuple( 17439782c922SJames Henderson 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 17441a789047SJames Henderson "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"), 17459782c922SJames Henderson // Truncated operands: 17465777570dSJames Henderson std::make_tuple( 17475777570dSJames Henderson 3, 9, DW_LNE_set_address, 17489782c922SJames Henderson ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}}, 17499782c922SJames Henderson "DW_LNE_set_address", 17501a789047SJames Henderson "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"), 17519782c922SJames Henderson std::make_tuple( 17529782c922SJames Henderson 10, 9, DW_LNE_set_address, 1753670dbad4SDavid Tenty ValueAndLengths{{0x1234567878563412, LineTable::Quad}}, 1754670dbad4SDavid Tenty "DW_LNE_set_address (<parsing error> 12 34 56 78 78 56 34)", 17559782c922SJames Henderson "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"), 17569782c922SJames Henderson std::make_tuple(3, 6, DW_LNE_define_file, 17575777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17585777570dSJames Henderson {'\0', LineTable::Byte}, 17595777570dSJames Henderson {1, LineTable::ULEB}, 17605777570dSJames Henderson {1, LineTable::ULEB}, 17615777570dSJames Henderson {1, LineTable::ULEB}}, 17629782c922SJames Henderson "DW_LNE_define_file", 17631a789047SJames Henderson "no null terminated string at offset 0x32"), 17649782c922SJames Henderson std::make_tuple(5, 6, DW_LNE_define_file, 17655777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17665777570dSJames Henderson {'\0', LineTable::Byte}, 17675777570dSJames Henderson {1, LineTable::ULEB}, 17685777570dSJames Henderson {1, LineTable::ULEB}, 17695777570dSJames Henderson {1, LineTable::ULEB}}, 17709782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00)", 17711a789047SJames Henderson "unable to decode LEB128 at offset 0x00000034: " 17725777570dSJames Henderson "malformed uleb128, extends past end"), 17739782c922SJames Henderson std::make_tuple(6, 6, DW_LNE_define_file, 17745777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17755777570dSJames Henderson {'\0', LineTable::Byte}, 17765777570dSJames Henderson {1, LineTable::ULEB}, 17775777570dSJames Henderson {1, LineTable::ULEB}, 17785777570dSJames Henderson {1, LineTable::ULEB}}, 17799782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00 01)", 17801a789047SJames Henderson "unable to decode LEB128 at offset 0x00000035: " 17815777570dSJames Henderson "malformed uleb128, extends past end"), 17829782c922SJames Henderson std::make_tuple(7, 6, DW_LNE_define_file, 17835777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17845777570dSJames Henderson {'\0', LineTable::Byte}, 17855777570dSJames Henderson {1, LineTable::ULEB}, 17865777570dSJames Henderson {1, LineTable::ULEB}, 17875777570dSJames Henderson {1, LineTable::ULEB}}, 17889782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00 01 01)", 17891a789047SJames Henderson "unable to decode LEB128 at offset 0x00000036: " 17905777570dSJames Henderson "malformed uleb128, extends past end"), 17915777570dSJames Henderson std::make_tuple(3, 2, DW_LNE_set_discriminator, 17925777570dSJames Henderson ValueAndLengths{{1, LineTable::ULEB}}, 17939782c922SJames Henderson "DW_LNE_set_discriminator", 17941a789047SJames Henderson "unable to decode LEB128 at offset 0x00000032: " 17959782c922SJames Henderson "malformed uleb128, extends past end"), 17969782c922SJames Henderson std::make_tuple( 17979782c922SJames Henderson 6, 5, /*Unknown=*/0x7f, 1798670dbad4SDavid Tenty ValueAndLengths{{0x12343412, LineTable::Long}}, 1799670dbad4SDavid Tenty "Unrecognized extended op 0x7f length 5 (<parsing error> 12 34 34)", 18009782c922SJames Henderson "unexpected end of data at offset 0x35 while reading [0x32, " 1801d4d80a29SBenjamin Kramer "0x36)"))); 18021a789047SJames Henderson 1803d24e721dSJake Egan #ifdef _AIX 1804d24e721dSJake Egan TEST_P(TruncatedStandardOpcodeFixture, 1805d24e721dSJake Egan DISABLED_ErrorForTruncatedStandardOpcode) { 1806d24e721dSJake Egan #else 18071a789047SJames Henderson TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) { 1808d24e721dSJake Egan #endif 18091a789047SJames Henderson if (!setupGenerator()) 18101a789047SJames Henderson return; 18111a789047SJames Henderson LineTable < = setupTable(); 18121a789047SJames Henderson LT.addStandardOpcode(Opcode, Operands); 18131a789047SJames Henderson runTest(Opcode); 18141a789047SJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), 18151a789047SJames Henderson FailedWithMessage(ExpectedErr.str())); 18161a789047SJames Henderson } 18171a789047SJames Henderson 1818d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 18191a789047SJames Henderson TruncatedStandardOpcodeParams, TruncatedStandardOpcodeFixture, 18201a789047SJames Henderson Values( 18211a789047SJames Henderson std::make_tuple(2, DW_LNS_advance_pc, 18221a789047SJames Henderson ValueAndLengths{{0x100, LineTable::ULEB}}, 18231a789047SJames Henderson "DW_LNS_advance_pc", 18241a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18251a789047SJames Henderson "malformed uleb128, extends past end"), 18261a789047SJames Henderson std::make_tuple(2, DW_LNS_advance_line, 18271a789047SJames Henderson ValueAndLengths{{0x200, LineTable::SLEB}}, 18281a789047SJames Henderson "DW_LNS_advance_line", 18291a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18301a789047SJames Henderson "malformed sleb128, extends past end"), 18311a789047SJames Henderson std::make_tuple(2, DW_LNS_set_file, 18321a789047SJames Henderson ValueAndLengths{{0x300, LineTable::ULEB}}, 18331a789047SJames Henderson "DW_LNS_set_file", 18341a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18351a789047SJames Henderson "malformed uleb128, extends past end"), 18361a789047SJames Henderson std::make_tuple(2, DW_LNS_set_column, 18371a789047SJames Henderson ValueAndLengths{{0x400, LineTable::ULEB}}, 18381a789047SJames Henderson "DW_LNS_set_column", 18391a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18401a789047SJames Henderson "malformed uleb128, extends past end"), 18411a789047SJames Henderson std::make_tuple( 18421a789047SJames Henderson 2, DW_LNS_fixed_advance_pc, 18431a789047SJames Henderson ValueAndLengths{{0x500, LineTable::Half}}, 18441a789047SJames Henderson "DW_LNS_fixed_advance_pc", 18451a789047SJames Henderson "unexpected end of data at offset 0x31 while reading [0x30, 0x32)"), 18461a789047SJames Henderson std::make_tuple(2, DW_LNS_set_isa, 18471a789047SJames Henderson ValueAndLengths{{0x600, LineTable::ULEB}}, 18481a789047SJames Henderson "DW_LNS_set_isa", 18491a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18501a789047SJames Henderson "malformed uleb128, extends past end"), 18511a789047SJames Henderson std::make_tuple(2, 0xd, 18521a789047SJames Henderson ValueAndLengths{{0x700, LineTable::ULEB}, 18531a789047SJames Henderson {0x800, LineTable::ULEB}}, 18541a789047SJames Henderson "Unrecognized standard opcode", 18551a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18561a789047SJames Henderson "malformed uleb128, extends past end"), 18571a789047SJames Henderson std::make_tuple( 18581a789047SJames Henderson 4, 0xd, 18591a789047SJames Henderson ValueAndLengths{{0x900, LineTable::ULEB}, {0xa00, LineTable::ULEB}}, 18601a789047SJames Henderson "Unrecognized standard opcode (operands: 0x0000000000000900)", 18611a789047SJames Henderson "unable to decode LEB128 at offset 0x00000032: " 1862d4d80a29SBenjamin Kramer "malformed uleb128, extends past end"))); 18635777570dSJames Henderson 1864d24e721dSJake Egan #ifdef _AIX 1865d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_PrintPathsProperly) { 1866d24e721dSJake Egan #else 1867417375d7SSterling Augustine TEST_F(DebugLineBasicFixture, PrintPathsProperly) { 1868d24e721dSJake Egan #endif 1869417375d7SSterling Augustine if (!setupGenerator(5)) 1870417375d7SSterling Augustine return; 1871417375d7SSterling Augustine 1872417375d7SSterling Augustine LineTable < = Gen->addLineTable(); 1873417375d7SSterling Augustine DWARFDebugLine::Prologue P = LT.createBasicPrologue(); 1874417375d7SSterling Augustine P.IncludeDirectories.push_back( 1875417375d7SSterling Augustine DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); 1876417375d7SSterling Augustine P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); 1877417375d7SSterling Augustine P.FileNames.back().Name = 1878417375d7SSterling Augustine DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); 1879417375d7SSterling Augustine P.FileNames.back().DirIdx = 1; 18806f55b5a1SPavel Labath P.TotalLength += 14; 1881417375d7SSterling Augustine P.PrologueLength += 14; 1882417375d7SSterling Augustine LT.setPrologue(P); 1883417375d7SSterling Augustine generate(); 1884417375d7SSterling Augustine 1885417375d7SSterling Augustine auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 1886417375d7SSterling Augustine nullptr, RecordRecoverable); 1887417375d7SSterling Augustine EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 1888417375d7SSterling Augustine std::string Result; 1889417375d7SSterling Augustine // DWARF 5 stores the compilation directory in two places: the Compilation 1890417375d7SSterling Augustine // Unit and the directory table entry 0, and implementations are free to use 1891417375d7SSterling Augustine // one or the other. This copy serves as the one stored in the CU. 1892417375d7SSterling Augustine StringRef CompDir = "a dir"; 1893417375d7SSterling Augustine EXPECT_FALSE( 1894417375d7SSterling Augustine (*ExpectedLineTable) 1895417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1896417375d7SSterling Augustine 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); 1897417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1898417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1899417375d7SSterling Augustine 1, CompDir, 19005de4ba17SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::RawValue, Result)); 19015de4ba17SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 19025de4ba17SSterling Augustine ->Prologue.getFileNameByIndex( 19035de4ba17SSterling Augustine 1, CompDir, 19045de4ba17SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly, 19055de4ba17SSterling Augustine Result)); 1906417375d7SSterling Augustine EXPECT_STREQ(Result.c_str(), "b file"); 1907417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1908417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1909417375d7SSterling Augustine 1, CompDir, 1910417375d7SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, 1911417375d7SSterling Augustine Result)); 1912257e4127SSterling Augustine EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file")); 1913417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1914417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1915417375d7SSterling Augustine 1, CompDir, 1916417375d7SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 1917417375d7SSterling Augustine Result)); 1918257e4127SSterling Augustine EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file")); 1919417375d7SSterling Augustine } 1920417375d7SSterling Augustine 192166702629SJames Henderson } // end anonymous namespace 1922