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 3907804f75SJames Henderson bool setupGenerator(uint16_t Version = 4, uint8_t AddrSize = 8) { 4007804f75SJames Henderson AddressSize = AddrSize; 4107804f75SJames Henderson Triple T = 4207804f75SJames Henderson getDefaultTargetTripleForAddrSize(AddressSize == 0 ? 8 : AddressSize); 4366702629SJames Henderson if (!isConfigurationSupported(T)) 4466702629SJames Henderson return false; 45a3acf99eSJames Henderson auto ExpectedGenerator = Generator::create(T, Version); 4666702629SJames Henderson if (ExpectedGenerator) 47a3acf99eSJames Henderson Gen.reset(ExpectedGenerator->release()); 4866702629SJames Henderson return true; 4966702629SJames Henderson } 5066702629SJames Henderson 51a3acf99eSJames Henderson void generate() { 52a3acf99eSJames Henderson Context = createContext(); 53a3acf99eSJames Henderson assert(Context != nullptr && "test state is not valid"); 54a3acf99eSJames Henderson const DWARFObject &Obj = Context->getDWARFObj(); 5507804f75SJames Henderson uint8_t TargetAddrSize = AddressSize == 0 ? 8 : AddressSize; 56552fda83SJason Liu LineData = DWARFDataExtractor( 57552fda83SJason Liu Obj, Obj.getLineSection(), 5807804f75SJames Henderson getDefaultTargetTripleForAddrSize(TargetAddrSize).isLittleEndian(), 5907804f75SJames Henderson AddressSize); 60a3acf99eSJames Henderson } 61a3acf99eSJames Henderson 6266702629SJames Henderson std::unique_ptr<DWARFContext> createContext() { 63a3acf99eSJames Henderson if (!Gen) 6466702629SJames Henderson return nullptr; 65a3acf99eSJames Henderson StringRef FileBytes = Gen->generate(); 6666702629SJames Henderson MemoryBufferRef FileBuffer(FileBytes, "dwarf"); 6766702629SJames Henderson auto Obj = object::ObjectFile::createObjectFile(FileBuffer); 6866702629SJames Henderson if (Obj) 6966702629SJames Henderson return DWARFContext::create(**Obj); 7066702629SJames Henderson return nullptr; 7166702629SJames Henderson } 7266702629SJames Henderson 73a3acf99eSJames Henderson DWARFDebugLine::SectionParser setupParser() { 74a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 75a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 76a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 77a3acf99eSJames Henderson LT.addByte(0xaa); 78a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 79a3acf99eSJames Henderson 80a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF64); 81a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 82a3acf99eSJames Henderson {{0x11223344, LineTable::Quad}}); 83a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 84a3acf99eSJames Henderson LT2.addByte(0xbb); 85a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 86a3acf99eSJames Henderson 87a3acf99eSJames Henderson generate(); 88a3acf99eSJames Henderson 8951a50534SDavid Blaikie return DWARFDebugLine::SectionParser(LineData, *Context, Units); 90a3acf99eSJames Henderson } 91a3acf99eSJames Henderson 92004b729eSJames Henderson void recordRecoverable(Error Err) { 93004b729eSJames Henderson Recoverable = joinErrors(std::move(Recoverable), std::move(Err)); 94004b729eSJames Henderson } 95004b729eSJames Henderson void recordUnrecoverable(Error Err) { 96004b729eSJames Henderson Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err)); 97a3acf99eSJames Henderson } 98a3acf99eSJames Henderson 999b23024cSPavel Labath Expected<const DWARFDebugLine::LineTable *> 1009b23024cSPavel Labath getOrParseLineTableFatalErrors(uint64_t Offset = 0) { 101a3acf99eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable( 102004b729eSJames Henderson LineData, Offset, *Context, nullptr, RecordRecoverable); 1039b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1049b23024cSPavel Labath return ExpectedLineTable; 1050e7ba06eSJonas Devlieghere } 1060e7ba06eSJonas Devlieghere 10707804f75SJames Henderson uint8_t AddressSize; 108a3acf99eSJames Henderson std::unique_ptr<Generator> Gen; 109a3acf99eSJames Henderson std::unique_ptr<DWARFContext> Context; 110a3acf99eSJames Henderson DWARFDataExtractor LineData; 111a3acf99eSJames Henderson DWARFDebugLine Line; 112004b729eSJames Henderson Error Recoverable; 113004b729eSJames Henderson std::function<void(Error)> RecordRecoverable; 114004b729eSJames Henderson Error Unrecoverable; 115004b729eSJames Henderson std::function<void(Error)> RecordUnrecoverable; 116a3acf99eSJames Henderson 11751a50534SDavid Blaikie SmallVector<std::unique_ptr<DWARFUnit>, 2> Units; 11866702629SJames Henderson }; 11966702629SJames Henderson 120a3acf99eSJames Henderson // Fixtures must derive from "Test", but parameterised fixtures from 121a3acf99eSJames Henderson // "TestWithParam". It does not seem possible to inherit from both, so we share 122a3acf99eSJames Henderson // the common state in a separate class, inherited by the two fixture classes. 123a3acf99eSJames Henderson struct DebugLineBasicFixture : public Test, public CommonFixture {}; 124a3acf99eSJames Henderson 125a3acf99eSJames Henderson struct DebugLineParameterisedFixture 126a3acf99eSJames Henderson : public TestWithParam<std::pair<uint16_t, DwarfFormat>>, 127a3acf99eSJames Henderson public CommonFixture { 12831eb8349SLogan Smith void SetUp() override { std::tie(Version, Format) = GetParam(); } 129a3acf99eSJames Henderson 130a3acf99eSJames Henderson uint16_t Version; 131a3acf99eSJames Henderson DwarfFormat Format; 132a3acf99eSJames Henderson }; 133a3acf99eSJames Henderson 134a3acf99eSJames Henderson void checkDefaultPrologue(uint16_t Version, DwarfFormat Format, 135a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue, 136a3acf99eSJames Henderson uint64_t BodyLength) { 137a3acf99eSJames Henderson // Check version specific fields and values. 138a3acf99eSJames Henderson uint64_t UnitLength; 139a3acf99eSJames Henderson uint64_t PrologueLength; 140a3acf99eSJames Henderson switch (Version) { 141a3acf99eSJames Henderson case 4: 142a3acf99eSJames Henderson PrologueLength = 36; 143a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 14411a9de74SJames Henderson EXPECT_EQ(Prologue.MaxOpsPerInst, 1u); 145a3acf99eSJames Henderson break; 146a3acf99eSJames Henderson case 2: 147a3acf99eSJames Henderson case 3: 148a3acf99eSJames Henderson PrologueLength = 35; 149a3acf99eSJames Henderson UnitLength = PrologueLength + 2; 150a3acf99eSJames Henderson break; 151a3acf99eSJames Henderson case 5: 1520bd48c3dSSterling Augustine PrologueLength = 42; 153a3acf99eSJames Henderson UnitLength = PrologueLength + 4; 15411a9de74SJames Henderson EXPECT_EQ(Prologue.getAddressSize(), 8u); 15511a9de74SJames Henderson EXPECT_EQ(Prologue.SegSelectorSize, 0u); 156a3acf99eSJames Henderson break; 157a3acf99eSJames Henderson default: 158a3acf99eSJames Henderson llvm_unreachable("unsupported DWARF version"); 159a3acf99eSJames Henderson } 160a3acf99eSJames Henderson UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8); 161a3acf99eSJames Henderson 162a3acf99eSJames Henderson EXPECT_EQ(Prologue.TotalLength, UnitLength); 163a3acf99eSJames Henderson EXPECT_EQ(Prologue.PrologueLength, PrologueLength); 16411a9de74SJames Henderson EXPECT_EQ(Prologue.MinInstLength, 1u); 16511a9de74SJames Henderson EXPECT_EQ(Prologue.DefaultIsStmt, 1u); 166a3acf99eSJames Henderson EXPECT_EQ(Prologue.LineBase, -5); 16711a9de74SJames Henderson EXPECT_EQ(Prologue.LineRange, 14u); 16811a9de74SJames Henderson EXPECT_EQ(Prologue.OpcodeBase, 13u); 169a3acf99eSJames Henderson std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}; 170a3acf99eSJames Henderson EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths); 17111a9de74SJames Henderson ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u); 172a3acf99eSJames Henderson ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string); 173a3acf99eSJames Henderson EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir"); 17411a9de74SJames Henderson ASSERT_EQ(Prologue.FileNames.size(), 1u); 175a3acf99eSJames Henderson ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string); 1760bd48c3dSSterling Augustine ASSERT_EQ(Prologue.FileNames[0].DirIdx, 0u); 177a3acf99eSJames Henderson EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file"); 178a3acf99eSJames Henderson } 179a3acf99eSJames Henderson 180*d24e721dSJake Egan #ifdef _AIX 181*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_GetOrParseLineTableAtInvalidOffset) { 182*d24e721dSJake Egan #else 183a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) { 184*d24e721dSJake Egan #endif 185a3acf99eSJames Henderson if (!setupGenerator()) 186a3acf99eSJames Henderson return; 187a3acf99eSJames Henderson generate(); 188a3acf99eSJames Henderson 1899b23024cSPavel Labath EXPECT_THAT_EXPECTED( 1909b23024cSPavel Labath getOrParseLineTableFatalErrors(0), 1919b23024cSPavel Labath FailedWithMessage( 1929b23024cSPavel Labath "offset 0x00000000 is not a valid debug line section offset")); 193a3acf99eSJames Henderson // Repeat to show that an error is reported each time. 1949b23024cSPavel Labath EXPECT_THAT_EXPECTED( 1959b23024cSPavel Labath getOrParseLineTableFatalErrors(0), 1969b23024cSPavel Labath FailedWithMessage( 1979b23024cSPavel Labath "offset 0x00000000 is not a valid debug line section offset")); 1989b23024cSPavel Labath 199a3acf99eSJames Henderson // Show that an error is reported for later offsets too. 2009b23024cSPavel Labath EXPECT_THAT_EXPECTED( 2019b23024cSPavel Labath getOrParseLineTableFatalErrors(1), 2029b23024cSPavel Labath FailedWithMessage( 2039b23024cSPavel Labath "offset 0x00000001 is not a valid debug line section offset")); 204a3acf99eSJames Henderson } 205a3acf99eSJames Henderson 206*d24e721dSJake Egan #ifdef _AIX 207*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 208*d24e721dSJake Egan DISABLED_GetOrParseLineTableAtInvalidOffsetAfterData) { 209*d24e721dSJake Egan #else 210a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffsetAfterData) { 211*d24e721dSJake Egan #endif 212a3acf99eSJames Henderson if (!setupGenerator()) 21366702629SJames Henderson return; 21466702629SJames Henderson 215a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 216a3acf99eSJames Henderson LT.setCustomPrologue({{0, LineTable::Byte}}); 21766702629SJames Henderson 218a3acf99eSJames Henderson generate(); 219a3acf99eSJames Henderson 2209b23024cSPavel Labath EXPECT_THAT_EXPECTED( 221d978656fSPavel Labath getOrParseLineTableFatalErrors(0), 22204aea769SPavel Labath FailedWithMessage( 22304aea769SPavel Labath "parsing line table prologue at offset 0x00000000: " 22404aea769SPavel Labath "unexpected end of data at offset 0x1 while reading [0x0, 0x4)")); 225d978656fSPavel Labath 226d978656fSPavel Labath EXPECT_THAT_EXPECTED( 2279b23024cSPavel Labath getOrParseLineTableFatalErrors(1), 2289b23024cSPavel Labath FailedWithMessage( 2299b23024cSPavel Labath "offset 0x00000001 is not a valid debug line section offset")); 230a3acf99eSJames Henderson } 231a3acf99eSJames Henderson 232*d24e721dSJake Egan #ifdef _AIX 233*d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_PrologueGetLength) { 234*d24e721dSJake Egan #else 235021f5317SJames Henderson TEST_P(DebugLineParameterisedFixture, PrologueGetLength) { 236*d24e721dSJake Egan #endif 237021f5317SJames Henderson if (!setupGenerator(Version)) 238021f5317SJames Henderson return; 239021f5317SJames Henderson LineTable < = Gen->addLineTable(Format); 240021f5317SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 241021f5317SJames Henderson LT.setPrologue(Prologue); 242021f5317SJames Henderson generate(); 243021f5317SJames Henderson 244021f5317SJames Henderson // + 10 for sizes of DWARF-32 unit length, version, prologue length. 245021f5317SJames Henderson uint64_t ExpectedLength = Prologue.PrologueLength + 10; 246021f5317SJames Henderson if (Version == 5) 247021f5317SJames Henderson // Add address and segment selector size fields. 248021f5317SJames Henderson ExpectedLength += 2; 249021f5317SJames Henderson if (Format == DWARF64) 250021f5317SJames Henderson // Unit length grows by 8, prologue length by 4. 251021f5317SJames Henderson ExpectedLength += 12; 252021f5317SJames Henderson 253021f5317SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 254021f5317SJames Henderson nullptr, RecordRecoverable); 255021f5317SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 256021f5317SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Prologue.getLength(), ExpectedLength); 257021f5317SJames Henderson } 258021f5317SJames Henderson 259*d24e721dSJake Egan #ifdef _AIX 260*d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_GetOrParseLineTableValidTable) { 261*d24e721dSJake Egan #else 262a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) { 263*d24e721dSJake Egan #endif 264a3acf99eSJames Henderson if (!setupGenerator(Version)) 265a3acf99eSJames Henderson return; 266a3acf99eSJames Henderson 267a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 268a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 269a3acf99eSJames Henderson 270a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 271a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55, LineTable::Quad}}); 272a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 273a3acf99eSJames Henderson LT.addByte(0xaa); 274a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 275a3acf99eSJames Henderson 276a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(Format); 277a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344, LineTable::Quad}}); 278a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 279a3acf99eSJames Henderson LT2.addByte(0xbb); 280a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 281a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788, LineTable::Quad}}); 282a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 283a3acf99eSJames Henderson LT2.addByte(0xcc); 284a3acf99eSJames Henderson LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 285a3acf99eSJames Henderson 286a3acf99eSJames Henderson generate(); 287a3acf99eSJames Henderson 288004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 289004b729eSJames Henderson nullptr, RecordRecoverable); 290a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable.operator bool()); 291004b729eSJames Henderson EXPECT_FALSE(Recoverable); 292a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable; 293a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected->Prologue, 16); 294a68aee07SRoman Lebedev EXPECT_EQ(Expected->Sequences.size(), 1u); 295a3acf99eSJames Henderson 296a3acf99eSJames Henderson uint64_t SecondOffset = 297a3acf99eSJames Henderson Expected->Prologue.sizeofTotalLength() + Expected->Prologue.TotalLength; 298004b729eSJames Henderson Recoverable = Error::success(); 299a3acf99eSJames Henderson auto ExpectedLineTable2 = Line.getOrParseLineTable( 300004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 301a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable2.operator bool()); 302004b729eSJames Henderson EXPECT_FALSE(Recoverable); 303a3acf99eSJames Henderson const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2; 304a3acf99eSJames Henderson checkDefaultPrologue(Version, Format, Expected2->Prologue, 32); 30511a9de74SJames Henderson EXPECT_EQ(Expected2->Sequences.size(), 2u); 306a3acf99eSJames Henderson 307a3acf99eSJames Henderson EXPECT_NE(Expected, Expected2); 308a3acf99eSJames Henderson 309a3acf99eSJames Henderson // Check that if the same offset is requested, the exact same pointer is 310a3acf99eSJames Henderson // returned. 311004b729eSJames Henderson Recoverable = Error::success(); 312004b729eSJames Henderson auto ExpectedLineTable3 = Line.getOrParseLineTable( 313004b729eSJames Henderson LineData, 0, *Context, nullptr, RecordRecoverable); 314a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable3.operator bool()); 315004b729eSJames Henderson EXPECT_FALSE(Recoverable); 316a3acf99eSJames Henderson EXPECT_EQ(Expected, *ExpectedLineTable3); 317a3acf99eSJames Henderson 318004b729eSJames Henderson Recoverable = Error::success(); 319a3acf99eSJames Henderson auto ExpectedLineTable4 = Line.getOrParseLineTable( 320004b729eSJames Henderson LineData, SecondOffset, *Context, nullptr, RecordRecoverable); 321a3acf99eSJames Henderson ASSERT_TRUE(ExpectedLineTable4.operator bool()); 322004b729eSJames Henderson EXPECT_FALSE(Recoverable); 323a3acf99eSJames Henderson EXPECT_EQ(Expected2, *ExpectedLineTable4); 324a3acf99eSJames Henderson 325a3acf99eSJames Henderson // TODO: Add tests that show that the body of the programs have been read 326a3acf99eSJames Henderson // correctly. 327a3acf99eSJames Henderson } 328a3acf99eSJames Henderson 329*d24e721dSJake Egan #ifdef _AIX 330*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForReservedLength) { 331*d24e721dSJake Egan #else 332a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { 333*d24e721dSJake Egan #endif 334a3acf99eSJames Henderson if (!setupGenerator()) 335a3acf99eSJames Henderson return; 336a3acf99eSJames Henderson 337a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 338f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 339a3acf99eSJames Henderson 340a3acf99eSJames Henderson generate(); 341a3acf99eSJames Henderson 3429b23024cSPavel Labath EXPECT_THAT_EXPECTED( 3439b23024cSPavel Labath getOrParseLineTableFatalErrors(), 3449b23024cSPavel Labath FailedWithMessage( 345d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 346d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 347a3acf99eSJames Henderson } 348a3acf99eSJames Henderson 3491da62b51SJames Henderson struct DebugLineUnsupportedVersionFixture : public TestWithParam<uint16_t>, 3501da62b51SJames Henderson public CommonFixture { 35131eb8349SLogan Smith void SetUp() override { Version = GetParam(); } 3521da62b51SJames Henderson 3531da62b51SJames Henderson uint16_t Version; 3541da62b51SJames Henderson }; 3551da62b51SJames Henderson 356*d24e721dSJake Egan #ifdef _AIX 357*d24e721dSJake Egan TEST_P(DebugLineUnsupportedVersionFixture, 358*d24e721dSJake Egan DISABLED_ErrorForUnsupportedVersion) { 359*d24e721dSJake Egan #else 3601da62b51SJames Henderson TEST_P(DebugLineUnsupportedVersionFixture, ErrorForUnsupportedVersion) { 361*d24e721dSJake Egan #endif 362a3acf99eSJames Henderson if (!setupGenerator()) 363a3acf99eSJames Henderson return; 364a3acf99eSJames Henderson 365a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 366a3acf99eSJames Henderson LT.setCustomPrologue( 3671da62b51SJames Henderson {{LineTable::Half, LineTable::Long}, {Version, LineTable::Half}}); 368b1c7bfe6SJames Henderson 369b1c7bfe6SJames Henderson generate(); 370b1c7bfe6SJames Henderson 3719b23024cSPavel Labath EXPECT_THAT_EXPECTED( 3729b23024cSPavel Labath getOrParseLineTableFatalErrors(), 373d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 374d978656fSPavel Labath "unsupported version " + 3759b23024cSPavel Labath std::to_string(Version))); 376b1c7bfe6SJames Henderson } 377b1c7bfe6SJames Henderson 378d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(UnsupportedVersionTestParams, 3791da62b51SJames Henderson DebugLineUnsupportedVersionFixture, 3801da62b51SJames Henderson Values(/*1 below min */ 1, /* 1 above max */ 6, 381d4d80a29SBenjamin Kramer /* Maximum possible */ 0xffff)); 3821da62b51SJames Henderson 383*d24e721dSJake Egan #ifdef _AIX 384*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForInvalidV5IncludeDirTable) { 385*d24e721dSJake Egan #else 386a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) { 387*d24e721dSJake Egan #endif 388a3acf99eSJames Henderson if (!setupGenerator(5)) 389a3acf99eSJames Henderson return; 390a3acf99eSJames Henderson 391a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 392a3acf99eSJames Henderson LT.setCustomPrologue({ 393a3acf99eSJames Henderson {19, LineTable::Long}, // unit length 394a3acf99eSJames Henderson {5, LineTable::Half}, // version 395a3acf99eSJames Henderson {8, LineTable::Byte}, // addr size 396a3acf99eSJames Henderson {0, LineTable::Byte}, // segment selector size 397a3acf99eSJames Henderson {11, LineTable::Long}, // prologue length 398a3acf99eSJames Henderson {1, LineTable::Byte}, // min instruction length 399a3acf99eSJames Henderson {1, LineTable::Byte}, // max ops per instruction 400a3acf99eSJames Henderson {1, LineTable::Byte}, // default is_stmt 401a3acf99eSJames Henderson {0, LineTable::Byte}, // line base 402a3acf99eSJames Henderson {14, LineTable::Byte}, // line range 403a3acf99eSJames Henderson {2, LineTable::Byte}, // opcode base (small to reduce the amount of 404a3acf99eSJames Henderson // setup required). 405a3acf99eSJames Henderson {0, LineTable::Byte}, // standard opcode lengths 406a3acf99eSJames Henderson {0, LineTable::Byte}, // directory entry format count (should not be 407a3acf99eSJames Henderson // zero). 408a3acf99eSJames Henderson {0, LineTable::ULEB}, // directories count 409a3acf99eSJames Henderson {0, LineTable::Byte}, // file name entry format count 410a3acf99eSJames Henderson {0, LineTable::ULEB} // file name entry count 411a3acf99eSJames Henderson }); 412a3acf99eSJames Henderson 413a3acf99eSJames Henderson generate(); 414a3acf99eSJames Henderson 4157116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4167116e431SJames Henderson nullptr, RecordRecoverable); 4177116e431SJames Henderson EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4187116e431SJames Henderson 4199b23024cSPavel Labath EXPECT_THAT_ERROR( 4209b23024cSPavel Labath std::move(Recoverable), 4219b23024cSPavel Labath FailedWithMessage( 4229b23024cSPavel Labath "parsing line table prologue at 0x00000000 found an invalid " 4239b23024cSPavel Labath "directory or file table description at 0x00000014", 4249b23024cSPavel Labath "failed to parse entry content descriptions because no path was " 4259b23024cSPavel Labath "found")); 426a3acf99eSJames Henderson } 427a3acf99eSJames Henderson 428*d24e721dSJake Egan #ifdef _AIX 429*d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooLargePrologueLength) { 430*d24e721dSJake Egan #else 431a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) { 432*d24e721dSJake Egan #endif 433a3acf99eSJames Henderson if (!setupGenerator(Version)) 434a3acf99eSJames Henderson return; 435a3acf99eSJames Henderson 436a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 437a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 438a3acf99eSJames Henderson 439a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 440a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 441a3acf99eSJames Henderson ++Prologue.PrologueLength; 442a3acf99eSJames Henderson LT.setPrologue(Prologue); 443a3acf99eSJames Henderson 444a3acf99eSJames Henderson generate(); 445a3acf99eSJames Henderson 4467116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4477116e431SJames Henderson nullptr, RecordRecoverable); 4487116e431SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4497116e431SJames Henderson DWARFDebugLine::LineTable Result(**ExpectedLineTable); 4507116e431SJames Henderson // Undo the earlier modification so that it can be compared against a 4517116e431SJames Henderson // "default" prologue. 4527116e431SJames Henderson --Result.Prologue.PrologueLength; 4537116e431SJames Henderson checkDefaultPrologue(Version, Format, Result.Prologue, 0); 4547116e431SJames Henderson 455a3acf99eSJames Henderson uint64_t ExpectedEnd = 456a3acf99eSJames Henderson Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); 4579b23024cSPavel Labath EXPECT_THAT_ERROR( 4589b23024cSPavel Labath std::move(Recoverable), 4596f55b5a1SPavel Labath FailedWithMessage( 4606f55b5a1SPavel Labath ("unknown data in line table prologue at offset 0x00000000: " 4616f55b5a1SPavel Labath "parsing ended (at offset 0x000000" + 4626f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd - 1) + 463fccaa89eSPavel Labath ") before reaching the prologue end at offset 0x000000" + 4646f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd)) 4659b23024cSPavel Labath .str())); 466a3acf99eSJames Henderson } 467a3acf99eSJames Henderson 468*d24e721dSJake Egan #ifdef _AIX 469*d24e721dSJake Egan TEST_P(DebugLineParameterisedFixture, DISABLED_ErrorForTooShortPrologueLength) { 470*d24e721dSJake Egan #else 471a3acf99eSJames Henderson TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { 472*d24e721dSJake Egan #endif 473a3acf99eSJames Henderson if (!setupGenerator(Version)) 474a3acf99eSJames Henderson return; 475a3acf99eSJames Henderson 476a3acf99eSJames Henderson SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format " + 477a3acf99eSJames Henderson (Format == DWARF64 ? "DWARF64" : "DWARF32")); 478a3acf99eSJames Henderson 479a3acf99eSJames Henderson LineTable < = Gen->addLineTable(Format); 480a3acf99eSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 481a3acf99eSJames Henderson Prologue.PrologueLength -= 2; 482a3acf99eSJames Henderson LT.setPrologue(Prologue); 483a3acf99eSJames Henderson 484a3acf99eSJames Henderson generate(); 485a3acf99eSJames Henderson 4867116e431SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 4877116e431SJames Henderson nullptr, RecordRecoverable); 4887116e431SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 4897116e431SJames Henderson DWARFDebugLine::LineTable Result(**ExpectedLineTable); 490c475856dSPavel Labath 491c475856dSPavel Labath // Parsing will stop before reading a complete file entry. 492c475856dSPavel Labath ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); 493c475856dSPavel Labath EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); 494c475856dSPavel Labath EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); 4957116e431SJames Henderson 4966f55b5a1SPavel Labath // The exact place where the parsing will stop depends on the structure of the 4976f55b5a1SPavel Labath // prologue and the last complete field we are able to read. Before V5 we stop 4986f55b5a1SPavel Labath // before reading the file length. In V5, we stop before the filename. 4996f55b5a1SPavel Labath uint64_t ExpectedEnd = Prologue.TotalLength + Prologue.sizeofTotalLength() - 5006f55b5a1SPavel Labath (Version < 5 ? 2 : 8); 501bf4d8f29SJames Henderson std::vector<std::string> Errs; 502bf4d8f29SJames Henderson Errs.emplace_back( 503bf4d8f29SJames Henderson (Twine("parsing line table prologue at 0x00000000 found an invalid " 504bf4d8f29SJames Henderson "directory or file table description at 0x000000") + 5056f55b5a1SPavel Labath Twine::utohexstr(ExpectedEnd)) 506bf4d8f29SJames Henderson .str()); 5076f55b5a1SPavel Labath if (Version < 5) { 508bf4d8f29SJames Henderson Errs.emplace_back("file names table was not null terminated before the end " 509bf4d8f29SJames Henderson "of the prologue"); 510c475856dSPavel Labath } else { 511bf4d8f29SJames Henderson Errs.emplace_back( 5129ed452f3SPavel Labath "failed to parse file entry because extracting the form value failed"); 513c475856dSPavel Labath } 5149b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5159b23024cSPavel Labath FailedWithMessageArray(testing::ElementsAreArray(Errs))); 516a3acf99eSJames Henderson } 517a3acf99eSJames Henderson 518d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 519a3acf99eSJames Henderson LineTableTestParams, DebugLineParameterisedFixture, 520a3acf99eSJames Henderson Values(std::make_pair( 521a3acf99eSJames Henderson 2, DWARF32), // Test lower-bound of v2-3 fields and DWARF32. 522a3acf99eSJames Henderson std::make_pair(3, DWARF32), // Test upper-bound of v2-3 fields. 523a3acf99eSJames Henderson std::make_pair(4, DWARF64), // Test v4 fields and DWARF64. 524d4d80a29SBenjamin Kramer std::make_pair(5, DWARF32), std::make_pair(5, DWARF64))); 525a3acf99eSJames Henderson 526*d24e721dSJake Egan #ifdef _AIX 527*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 528*d24e721dSJake Egan DISABLED_ErrorForExtendedOpcodeLengthSmallerThanExpected) { 529*d24e721dSJake Egan #else 530f1be770fSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthSmallerThanExpected) { 531*d24e721dSJake Egan #endif 532a3acf99eSJames Henderson if (!setupGenerator()) 533a3acf99eSJames Henderson return; 534a3acf99eSJames Henderson 535a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 536f1be770fSJames Henderson LT.addByte(0xaa); 537f1be770fSJames Henderson // The Length should be 1 + sizeof(ULEB) for a set discriminator opcode. 538f1be770fSJames Henderson // The operand will be read for both the discriminator opcode and then parsed 539f1be770fSJames Henderson // again as DW_LNS_negate_stmt, to respect the claimed length. 540f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_set_discriminator, 541f1be770fSJames Henderson {{DW_LNS_negate_stmt, LineTable::ULEB}}); 542f1be770fSJames Henderson LT.addByte(0xbb); 543f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 544f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 545a3acf99eSJames Henderson 546a3acf99eSJames Henderson generate(); 547a3acf99eSJames Henderson 548f1be770fSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 549f1be770fSJames Henderson nullptr, RecordRecoverable); 5509b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5519b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 5529b23024cSPavel Labath "0x00000031 expected 0x01 found 0x02")); 553f1be770fSJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 554f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 555f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 556f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].IsStmt, 0u); 557f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Discriminator, DW_LNS_negate_stmt); 558f1be770fSJames Henderson } 559f1be770fSJames Henderson 560*d24e721dSJake Egan #ifdef _AIX 561*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 562*d24e721dSJake Egan DISABLED_ErrorForExtendedOpcodeLengthLargerThanExpected) { 563*d24e721dSJake Egan #else 564f1be770fSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForExtendedOpcodeLengthLargerThanExpected) { 565*d24e721dSJake Egan #endif 566f1be770fSJames Henderson if (!setupGenerator()) 567f1be770fSJames Henderson return; 568f1be770fSJames Henderson 569f1be770fSJames Henderson LineTable < = Gen->addLineTable(); 570f1be770fSJames Henderson LT.addByte(0xaa); 571f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 572f1be770fSJames Henderson // The Length should be 1 for an end sequence opcode. 573f1be770fSJames Henderson LT.addExtendedOpcode(2, DW_LNE_end_sequence, {}); 574f1be770fSJames Henderson // The negate statement opcode will be skipped. 575f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 576f1be770fSJames Henderson LT.addByte(0xbb); 577f1be770fSJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 578f1be770fSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 579f1be770fSJames Henderson 580f1be770fSJames Henderson generate(); 581f1be770fSJames Henderson 582f1be770fSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 583f1be770fSJames Henderson nullptr, RecordRecoverable); 5849b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 5859b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 5869b23024cSPavel Labath "0x00000032 expected 0x02 found 0x01")); 587f1be770fSJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 588f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 4u); 589f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 2u); 590f1be770fSJames Henderson ASSERT_EQ((*ExpectedLineTable)->Sequences[1].FirstRowIndex, 2u); 591f1be770fSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[2].IsStmt, 1u); 592a3acf99eSJames Henderson } 593a3acf99eSJames Henderson 594*d24e721dSJake Egan #ifdef _AIX 595*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForUnitLengthTooLarge) { 596*d24e721dSJake Egan #else 597216796f2SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) { 598*d24e721dSJake Egan #endif 599216796f2SJames Henderson if (!setupGenerator()) 600216796f2SJames Henderson return; 601216796f2SJames Henderson 602216796f2SJames Henderson LineTable &Padding = Gen->addLineTable(); 603216796f2SJames Henderson // Add some padding to show that a non-zero offset is handled correctly. 604216796f2SJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 605216796f2SJames Henderson LineTable < = Gen->addLineTable(); 606216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 607216796f2SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 608216796f2SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 609216796f2SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 6101271cde4SJames Henderson // Set the total length to 1 higher than the actual length. 6111271cde4SJames Henderson ++Prologue.TotalLength; 612216796f2SJames Henderson LT.setPrologue(Prologue); 613216796f2SJames Henderson 614216796f2SJames Henderson generate(); 615216796f2SJames Henderson 616216796f2SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1, *Context, 617216796f2SJames Henderson nullptr, RecordRecoverable); 6189b23024cSPavel Labath EXPECT_THAT_ERROR( 6199b23024cSPavel Labath std::move(Recoverable), 6209b23024cSPavel Labath FailedWithMessage("line table program with offset 0x00000001 has length " 6219b23024cSPavel Labath "0x00000034 but only 0x00000033 bytes are available")); 622216796f2SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 623216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 624216796f2SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 625216796f2SJames Henderson } 626216796f2SJames Henderson 627*d24e721dSJake Egan #ifdef _AIX 628*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForMismatchedAddressSize) { 629*d24e721dSJake Egan #else 630a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) { 631*d24e721dSJake Egan #endif 63207804f75SJames Henderson if (!setupGenerator(4, 8)) 633a3acf99eSJames Henderson return; 634a3acf99eSJames Henderson 635a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 636a3acf99eSJames Henderson // The line data extractor expects size 8 (Quad) addresses. 63707804f75SJames Henderson uint64_t Addr1 = 0x11223344; 63807804f75SJames Henderson LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 639a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 64007804f75SJames Henderson // Show that the expected address size is unchanged, so later valid lines 64107804f75SJames Henderson // don't cause a problem. 64207804f75SJames Henderson uint64_t Addr2 = 0x1122334455667788; 64307804f75SJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 644a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 645a3acf99eSJames Henderson 646a3acf99eSJames Henderson generate(); 647a3acf99eSJames Henderson 64807804f75SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 64907804f75SJames Henderson nullptr, RecordRecoverable); 6509b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 6519b23024cSPavel Labath FailedWithMessage("mismatching address size at offset " 6529b23024cSPavel Labath "0x00000030 expected 0x08 found 0x04")); 65307804f75SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 65407804f75SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 65507804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 65607804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 65707804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 65807804f75SJames Henderson } 65907804f75SJames Henderson 660*d24e721dSJake Egan #ifdef _AIX 661*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 662*d24e721dSJake Egan DISABLED_ErrorForMismatchedAddressSizeUnsetInitialAddress) { 663*d24e721dSJake Egan #else 66407804f75SJames Henderson TEST_F(DebugLineBasicFixture, 66507804f75SJames Henderson ErrorForMismatchedAddressSizeUnsetInitialAddress) { 666*d24e721dSJake Egan #endif 66707804f75SJames Henderson if (!setupGenerator(4, 0)) 66807804f75SJames Henderson return; 66907804f75SJames Henderson 67007804f75SJames Henderson LineTable < = Gen->addLineTable(); 67107804f75SJames Henderson uint64_t Addr1 = 0x11223344; 67207804f75SJames Henderson LT.addExtendedOpcode(5, DW_LNE_set_address, {{Addr1, LineTable::Long}}); 67307804f75SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 67407804f75SJames Henderson uint64_t Addr2 = 0x1122334455667788; 67507804f75SJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, {{Addr2, LineTable::Quad}}); 67607804f75SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 67707804f75SJames Henderson 67807804f75SJames Henderson generate(); 67907804f75SJames Henderson 68007804f75SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 68107804f75SJames Henderson nullptr, RecordRecoverable); 6829b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 6839b23024cSPavel Labath FailedWithMessage("mismatching address size at offset " 6849b23024cSPavel Labath "0x00000038 expected 0x04 found 0x08")); 68507804f75SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 68607804f75SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 2u); 68707804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 68807804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, Addr1); 68907804f75SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[1].Address.Address, Addr2); 690a3acf99eSJames Henderson } 691a3acf99eSJames Henderson 692*d24e721dSJake Egan #ifdef _AIX 693*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 694*d24e721dSJake Egan DISABLED_ErrorForUnsupportedAddressSizeInSetAddressLength) { 695*d24e721dSJake Egan #else 696fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, 697fe6983a7SJames Henderson ErrorForUnsupportedAddressSizeInSetAddressLength) { 698*d24e721dSJake Egan #endif 699fe6983a7SJames Henderson // Use DWARF v4, and 0 for data extractor address size so that the address 700fe6983a7SJames Henderson // size is derived from the opcode length. 701fe6983a7SJames Henderson if (!setupGenerator(4, 0)) 702fe6983a7SJames Henderson return; 703fe6983a7SJames Henderson 704fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 705fe6983a7SJames Henderson // 4 == length of the extended opcode, i.e. 1 for the opcode itself and 3 for 706fe6983a7SJames Henderson // the Half (2) + Byte (1) operand, representing the unsupported address size. 707fe6983a7SJames Henderson LT.addExtendedOpcode(4, DW_LNE_set_address, 708fe6983a7SJames Henderson {{0x1234, LineTable::Half}, {0x56, LineTable::Byte}}); 709fe6983a7SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 710fe6983a7SJames Henderson // Special opcode to ensure the address has changed between the first and last 711fe6983a7SJames Henderson // row in the sequence. Without this, the sequence will not be recorded. 712fe6983a7SJames Henderson LT.addByte(0xaa); 713fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 714fe6983a7SJames Henderson 715fe6983a7SJames Henderson generate(); 716fe6983a7SJames Henderson 717fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 718fe6983a7SJames Henderson nullptr, RecordRecoverable); 7199b23024cSPavel Labath EXPECT_THAT_ERROR( 7209b23024cSPavel Labath std::move(Recoverable), 7219b23024cSPavel Labath FailedWithMessage("address size 0x03 of DW_LNE_set_address opcode at " 7229b23024cSPavel Labath "offset 0x00000030 is unsupported")); 723fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 724fe6983a7SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 725fe6983a7SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 726fe6983a7SJames Henderson // Show that the set address opcode is ignored in this case. 727a55dec7dSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 728fe6983a7SJames Henderson } 729fe6983a7SJames Henderson 730*d24e721dSJake Egan #ifdef _AIX 731*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ErrorForAddressSizeGreaterThanByteSize) { 732*d24e721dSJake Egan #else 733fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForAddressSizeGreaterThanByteSize) { 734*d24e721dSJake Egan #endif 735fe6983a7SJames Henderson // Use DWARF v4, and 0 for data extractor address size so that the address 736fe6983a7SJames Henderson // size is derived from the opcode length. 737fe6983a7SJames Henderson if (!setupGenerator(4, 0)) 738fe6983a7SJames Henderson return; 739fe6983a7SJames Henderson 740fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 741fe6983a7SJames Henderson // Specifically use an operand size that has a trailing byte of a supported 742fe6983a7SJames Henderson // size (8), so that any potential truncation would result in a valid size. 743fe6983a7SJames Henderson std::vector<LineTable::ValueAndLength> Operands(0x108); 744fe6983a7SJames Henderson LT.addExtendedOpcode(Operands.size() + 1, DW_LNE_set_address, Operands); 745fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 746fe6983a7SJames Henderson 747fe6983a7SJames Henderson generate(); 748fe6983a7SJames Henderson 749fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 750fe6983a7SJames Henderson nullptr, RecordRecoverable); 7519b23024cSPavel Labath EXPECT_THAT_ERROR( 7529b23024cSPavel Labath std::move(Recoverable), 7539b23024cSPavel Labath FailedWithMessage("address size 0x108 of DW_LNE_set_address opcode at " 7549b23024cSPavel Labath "offset 0x00000031 is unsupported")); 755fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 756fe6983a7SJames Henderson } 757fe6983a7SJames Henderson 758*d24e721dSJake Egan #ifdef _AIX 759*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 760*d24e721dSJake Egan DISABLED_ErrorForUnsupportedAddressSizeDefinedInHeader) { 761*d24e721dSJake Egan #else 762fe6983a7SJames Henderson TEST_F(DebugLineBasicFixture, ErrorForUnsupportedAddressSizeDefinedInHeader) { 763*d24e721dSJake Egan #endif 764fe6983a7SJames Henderson // Use 0 for data extractor address size so that it does not clash with the 765fe6983a7SJames Henderson // header address size. 766fe6983a7SJames Henderson if (!setupGenerator(5, 0)) 767fe6983a7SJames Henderson return; 768fe6983a7SJames Henderson 769fe6983a7SJames Henderson LineTable < = Gen->addLineTable(); 770fe6983a7SJames Henderson // AddressSize + 1 == length of the extended opcode, i.e. 1 for the opcode 771fe6983a7SJames Henderson // itself and 9 for the Quad (8) + Byte (1) operand representing the 772fe6983a7SJames Henderson // unsupported address size. 773fe6983a7SJames Henderson uint8_t AddressSize = 9; 774fe6983a7SJames Henderson LT.addExtendedOpcode(AddressSize + 1, DW_LNE_set_address, 775fe6983a7SJames Henderson {{0x12345678, LineTable::Quad}, {0, LineTable::Byte}}); 776fe6983a7SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 777fe6983a7SJames Henderson // Special opcode to ensure the address has changed between the first and last 778fe6983a7SJames Henderson // row in the sequence. Without this, the sequence will not be recorded. 779fe6983a7SJames Henderson LT.addByte(0xaa); 780fe6983a7SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 781fe6983a7SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 782fe6983a7SJames Henderson Prologue.FormParams.AddrSize = AddressSize; 783fe6983a7SJames Henderson LT.setPrologue(Prologue); 784fe6983a7SJames Henderson 785fe6983a7SJames Henderson generate(); 786fe6983a7SJames Henderson 787fe6983a7SJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 788fe6983a7SJames Henderson nullptr, RecordRecoverable); 7899b23024cSPavel Labath EXPECT_THAT_ERROR( 7909b23024cSPavel Labath std::move(Recoverable), 7919b23024cSPavel Labath FailedWithMessage("address size 0x09 of DW_LNE_set_address opcode at " 7929b23024cSPavel Labath "offset 0x00000038 is unsupported")); 793fe6983a7SJames Henderson ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 794fe6983a7SJames Henderson ASSERT_EQ((*ExpectedLineTable)->Rows.size(), 3u); 795fe6983a7SJames Henderson EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 796fe6983a7SJames Henderson // Show that the set address opcode is ignored in this case. 797a55dec7dSJames Henderson EXPECT_EQ((*ExpectedLineTable)->Rows[0].Address.Address, 0u); 798fe6983a7SJames Henderson } 799fe6983a7SJames Henderson 800*d24e721dSJake Egan #ifdef _AIX 801*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_CallbackUsedForUnterminatedSequence) { 802*d24e721dSJake Egan #else 803a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) { 804*d24e721dSJake Egan #endif 805a3acf99eSJames Henderson if (!setupGenerator()) 806a3acf99eSJames Henderson return; 807a3acf99eSJames Henderson 808a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 809a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 810a3acf99eSJames Henderson {{0x1122334455667788, LineTable::Quad}}); 811a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 812a3acf99eSJames Henderson LT.addByte(0xaa); 813a3acf99eSJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 814a3acf99eSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 815a3acf99eSJames Henderson {{0x99aabbccddeeff00, LineTable::Quad}}); 816a3acf99eSJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 817a3acf99eSJames Henderson LT.addByte(0xbb); 818a3acf99eSJames Henderson LT.addByte(0xcc); 819a3acf99eSJames Henderson 820a3acf99eSJames Henderson generate(); 821a3acf99eSJames Henderson 822004b729eSJames Henderson auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 823004b729eSJames Henderson nullptr, RecordRecoverable); 8249b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 8259b23024cSPavel Labath FailedWithMessage("last sequence in debug line table at " 8269b23024cSPavel Labath "offset 0x00000000 is not terminated")); 8279b23024cSPavel Labath ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 828a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u); 829a3acf99eSJames Henderson // The unterminated sequence is not added to the sequence list. 830a68aee07SRoman Lebedev EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u); 831a3acf99eSJames Henderson } 832a3acf99eSJames Henderson 8338732192bSJames Henderson struct AdjustAddressFixtureBase : public CommonFixture { 8348732192bSJames Henderson virtual ~AdjustAddressFixtureBase() {} 8358732192bSJames Henderson 8368732192bSJames Henderson // Create and update the prologue as specified by the subclass, then return 8378732192bSJames Henderson // the length of the table. 8388732192bSJames Henderson virtual uint64_t editPrologue(LineTable <) = 0; 8398732192bSJames Henderson 8408732192bSJames Henderson virtual uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncrs, 8418732192bSJames Henderson uint64_t SpecialIncrs, 8428732192bSJames Henderson uint64_t AdvanceIncrs) { 8438732192bSJames Henderson return Base + ConstIncrs + SpecialIncrs + AdvanceIncrs; 8448732192bSJames Henderson } 8458732192bSJames Henderson 8468732192bSJames Henderson virtual uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) { 8478732192bSJames Henderson return Base + Incr; 8488732192bSJames Henderson } 8498732192bSJames Henderson 8508732192bSJames Henderson uint64_t setupNoProblemTable() { 8518732192bSJames Henderson LineTable &NoProblem = Gen->addLineTable(); 8528732192bSJames Henderson NoProblem.addExtendedOpcode(9, DW_LNE_set_address, 8538732192bSJames Henderson {{0xabcd, LineTable::Quad}}); 8548732192bSJames Henderson NoProblem.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8558732192bSJames Henderson return editPrologue(NoProblem); 8568732192bSJames Henderson } 8578732192bSJames Henderson 8588732192bSJames Henderson uint64_t setupConstAddPcFirstTable() { 8598732192bSJames Henderson LineTable &ConstAddPCFirst = Gen->addLineTable(); 8608732192bSJames Henderson ConstAddPCFirst.addExtendedOpcode(9, DW_LNE_set_address, 8618732192bSJames Henderson {{ConstAddPCAddr, LineTable::Quad}}); 8628732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8638732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8648732192bSJames Henderson ConstAddPCFirst.addStandardOpcode(DW_LNS_advance_pc, 8658732192bSJames Henderson {{0x10, LineTable::ULEB}}); 8668732192bSJames Henderson ConstAddPCFirst.addByte(0x21); // Special opcode, +1 op, +1 line. 8678732192bSJames Henderson ConstAddPCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8688732192bSJames Henderson return editPrologue(ConstAddPCFirst); 8698732192bSJames Henderson } 8708732192bSJames Henderson 8718732192bSJames Henderson uint64_t setupSpecialFirstTable() { 8728732192bSJames Henderson LineTable &SpecialFirst = Gen->addLineTable(); 8738732192bSJames Henderson SpecialFirst.addExtendedOpcode(9, DW_LNE_set_address, 8748732192bSJames Henderson {{SpecialAddr, LineTable::Quad}}); 8758732192bSJames Henderson SpecialFirst.addByte(0x22); // Special opcode, +1 op, +2 line. 8768732192bSJames Henderson SpecialFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8778732192bSJames Henderson SpecialFirst.addStandardOpcode(DW_LNS_advance_pc, 8788732192bSJames Henderson {{0x20, LineTable::ULEB}}); 8798732192bSJames Henderson SpecialFirst.addByte(0x23); // Special opcode, +1 op, +3 line. 8808732192bSJames Henderson SpecialFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8818732192bSJames Henderson return editPrologue(SpecialFirst); 8828732192bSJames Henderson } 8838732192bSJames Henderson 8848732192bSJames Henderson uint64_t setupAdvancePcFirstTable() { 8858732192bSJames Henderson LineTable &AdvancePCFirst = Gen->addLineTable(); 8868732192bSJames Henderson AdvancePCFirst.addExtendedOpcode(9, DW_LNE_set_address, 8878732192bSJames Henderson {{AdvancePCAddr, LineTable::Quad}}); 8888732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 8898732192bSJames Henderson {{0x30, LineTable::ULEB}}); 8908732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_const_add_pc, {}); 8918732192bSJames Henderson AdvancePCFirst.addStandardOpcode(DW_LNS_advance_pc, 8928732192bSJames Henderson {{0x40, LineTable::ULEB}}); 8938732192bSJames Henderson AdvancePCFirst.addByte(0x24); // Special opcode, +1 op, +4 line. 8948732192bSJames Henderson AdvancePCFirst.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 8958732192bSJames Henderson return editPrologue(AdvancePCFirst); 8968732192bSJames Henderson } 8978732192bSJames Henderson 8988732192bSJames Henderson void setupTables(bool AddAdvancePCFirstTable) { 8998732192bSJames Henderson LineTable &Padding = Gen->addLineTable(); 9008732192bSJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 9018732192bSJames Henderson NoProblemOffset = 1; 9028732192bSJames Henderson 9038732192bSJames Henderson // Show that no warning is generated for the case where no 9048732192bSJames Henderson // DW_LNS_const_add_pc or special opcode is used. 9058732192bSJames Henderson ConstAddPCOffset = setupNoProblemTable() + NoProblemOffset; 9068732192bSJames Henderson 9078732192bSJames Henderson // Show that the warning is emitted for the first DW_LNS_const_add_pc opcode 9088732192bSJames Henderson // and then not again. 9098732192bSJames Henderson SpecialOffset = setupConstAddPcFirstTable() + ConstAddPCOffset; 9108732192bSJames Henderson 9118732192bSJames Henderson // Show that the warning is emitted for the first special opcode and then 9128732192bSJames Henderson // not again. 9138732192bSJames Henderson AdvancePCOffset = setupSpecialFirstTable() + SpecialOffset; 9148732192bSJames Henderson 9158732192bSJames Henderson // Show that the warning is emitted for the first DW_LNS_advance_pc opcode 9168732192bSJames Henderson // (if requested) and then not again. 9178732192bSJames Henderson if (AddAdvancePCFirstTable) 9188732192bSJames Henderson setupAdvancePcFirstTable(); 9198732192bSJames Henderson } 9208732192bSJames Henderson 9218732192bSJames Henderson Expected<const DWARFDebugLine::LineTable *> 9228732192bSJames Henderson checkTable(uint64_t Offset, StringRef OpcodeType, const Twine &MsgSuffix) { 9238732192bSJames Henderson auto ExpectedTable = Line.getOrParseLineTable(LineData, Offset, *Context, 9248732192bSJames Henderson nullptr, RecordRecoverable); 9258732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9268732192bSJames Henderson if (!IsErrorExpected) { 9278732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 9288732192bSJames Henderson } else { 9298732192bSJames Henderson if (!ExpectedTable) 9308732192bSJames Henderson return ExpectedTable; 9318732192bSJames Henderson uint64_t ExpectedOffset = Offset + 9328732192bSJames Henderson (*ExpectedTable)->Prologue.getLength() + 9338732192bSJames Henderson 11; // 11 == size of DW_LNE_set_address. 9348732192bSJames Henderson std::string OffsetHex = Twine::utohexstr(Offset).str(); 9358732192bSJames Henderson std::string OffsetZeroes = std::string(8 - OffsetHex.size(), '0'); 9368732192bSJames Henderson std::string ExpectedHex = Twine::utohexstr(ExpectedOffset).str(); 9378732192bSJames Henderson std::string ExpectedZeroes = std::string(8 - ExpectedHex.size(), '0'); 9388732192bSJames Henderson EXPECT_THAT_ERROR( 9398732192bSJames Henderson std::move(Recoverable), 9408732192bSJames Henderson FailedWithMessage(("line table program at offset 0x" + OffsetZeroes + 9418732192bSJames Henderson OffsetHex + " contains a " + OpcodeType + 9428732192bSJames Henderson " opcode at offset 0x" + ExpectedZeroes + 9438732192bSJames Henderson ExpectedHex + ", " + MsgSuffix) 9448732192bSJames Henderson .str())); 9458732192bSJames Henderson } 9468732192bSJames Henderson return ExpectedTable; 9478732192bSJames Henderson } 9488732192bSJames Henderson 9498732192bSJames Henderson void runTest(bool CheckAdvancePC, Twine MsgSuffix) { 9508732192bSJames Henderson if (!setupGenerator(Version)) 9518732192bSJames Henderson return; 9528732192bSJames Henderson 9538732192bSJames Henderson setupTables(/*AddAdvancePCFirstTable=*/CheckAdvancePC); 9548732192bSJames Henderson 9558732192bSJames Henderson generate(); 9568732192bSJames Henderson 9578732192bSJames Henderson auto ExpectedNoProblem = Line.getOrParseLineTable( 9588732192bSJames Henderson LineData, NoProblemOffset, *Context, nullptr, RecordRecoverable); 9598732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 9608732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9618732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedNoProblem, Succeeded()); 9628732192bSJames Henderson 9638732192bSJames Henderson auto ExpectedConstAddPC = 9648732192bSJames Henderson checkTable(ConstAddPCOffset, "DW_LNS_const_add_pc", MsgSuffix); 9658732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedConstAddPC, Succeeded()); 9668732192bSJames Henderson ASSERT_EQ((*ExpectedConstAddPC)->Rows.size(), 2u); 9678732192bSJames Henderson EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Address.Address, 9688732192bSJames Henderson getAdjustedAddr(ConstAddPCAddr, ConstIncr * 2, 0x1, 0x10)); 9698732192bSJames Henderson EXPECT_EQ((*ExpectedConstAddPC)->Rows[0].Line, getAdjustedLine(1, 1)); 9708732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9718732192bSJames Henderson 9728732192bSJames Henderson auto ExpectedSpecial = checkTable(SpecialOffset, "special", MsgSuffix); 9738732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedSpecial, Succeeded()); 9748732192bSJames Henderson ASSERT_EQ((*ExpectedSpecial)->Rows.size(), 3u); 9758732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[0].Address.Address, 9768732192bSJames Henderson getAdjustedAddr(SpecialAddr, 0, 1, 0)); 9778732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[0].Line, getAdjustedLine(1, 2)); 9788732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[1].Address.Address, 9798732192bSJames Henderson getAdjustedAddr(SpecialAddr, ConstIncr, 0x2, 0x20)); 9808732192bSJames Henderson EXPECT_EQ((*ExpectedSpecial)->Rows[1].Line, getAdjustedLine(1, 5)); 9818732192bSJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded()); 9828732192bSJames Henderson 9838732192bSJames Henderson if (!CheckAdvancePC) 9848732192bSJames Henderson return; 9858732192bSJames Henderson 9868732192bSJames Henderson auto ExpectedAdvancePC = 9878732192bSJames Henderson checkTable(AdvancePCOffset, "DW_LNS_advance_pc", MsgSuffix); 9888732192bSJames Henderson ASSERT_THAT_EXPECTED(ExpectedAdvancePC, Succeeded()); 9898732192bSJames Henderson ASSERT_EQ((*ExpectedAdvancePC)->Rows.size(), 2u); 9908732192bSJames Henderson EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Address.Address, 9918732192bSJames Henderson getAdjustedAddr(AdvancePCAddr, ConstIncr, 0x1, 0x70)); 9928732192bSJames Henderson EXPECT_EQ((*ExpectedAdvancePC)->Rows[0].Line, getAdjustedLine(1, 4)); 9938732192bSJames Henderson } 9948732192bSJames Henderson 9958732192bSJames Henderson uint64_t ConstIncr = 0x11; 9968732192bSJames Henderson uint64_t ConstAddPCAddr = 0x1234; 9978732192bSJames Henderson uint64_t SpecialAddr = 0x5678; 9988732192bSJames Henderson uint64_t AdvancePCAddr = 0xabcd; 9998732192bSJames Henderson uint64_t NoProblemOffset; 10008732192bSJames Henderson uint64_t ConstAddPCOffset; 10018732192bSJames Henderson uint64_t SpecialOffset; 10028732192bSJames Henderson uint64_t AdvancePCOffset; 10038732192bSJames Henderson 10048732192bSJames Henderson uint16_t Version = 4; 10058732192bSJames Henderson bool IsErrorExpected; 10068732192bSJames Henderson }; 10078732192bSJames Henderson 10088732192bSJames Henderson struct MaxOpsPerInstFixture 10098732192bSJames Henderson : TestWithParam<std::tuple<uint16_t, uint8_t, bool>>, 10108732192bSJames Henderson AdjustAddressFixtureBase { 10118732192bSJames Henderson void SetUp() override { 10128732192bSJames Henderson std::tie(Version, MaxOpsPerInst, IsErrorExpected) = GetParam(); 10138732192bSJames Henderson } 10148732192bSJames Henderson 10158732192bSJames Henderson uint64_t editPrologue(LineTable <) override { 10168732192bSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 10178732192bSJames Henderson Prologue.MaxOpsPerInst = MaxOpsPerInst; 10188732192bSJames Henderson LT.setPrologue(Prologue); 10198732192bSJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 10208732192bSJames Henderson } 10218732192bSJames Henderson 10228732192bSJames Henderson uint8_t MaxOpsPerInst; 10238732192bSJames Henderson }; 10248732192bSJames Henderson 1025*d24e721dSJake Egan #ifdef _AIX 1026*d24e721dSJake Egan TEST_P(MaxOpsPerInstFixture, DISABLED_MaxOpsPerInstProblemsReportedCorrectly) { 1027*d24e721dSJake Egan #else 10288732192bSJames Henderson TEST_P(MaxOpsPerInstFixture, MaxOpsPerInstProblemsReportedCorrectly) { 1029*d24e721dSJake Egan #endif 10308732192bSJames Henderson runTest(/*CheckAdvancePC=*/true, 10318732192bSJames Henderson "but the prologue maximum_operations_per_instruction value is " + 10328732192bSJames Henderson Twine(unsigned(MaxOpsPerInst)) + 10338732192bSJames Henderson ", which is unsupported. Assuming a value of 1 instead"); 10348732192bSJames Henderson } 10358732192bSJames Henderson 1036d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 10378732192bSJames Henderson MaxOpsPerInstParams, MaxOpsPerInstFixture, 10388732192bSJames Henderson Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error). 10398732192bSJames Henderson std::make_tuple(4, 0, true), // Test zero value for V4 (error). 10408732192bSJames Henderson std::make_tuple(4, 1, false), // Test good value for V4 (no error). 10418732192bSJames Henderson std::make_tuple( 1042d4d80a29SBenjamin Kramer 4, 2, true))); // Test one higher than permitted V4 (error). 10438732192bSJames Henderson 10446e0c9e46SJames Henderson struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>, 10456e0c9e46SJames Henderson AdjustAddressFixtureBase { 10466e0c9e46SJames Henderson void SetUp() override { std::tie(LineRange, IsErrorExpected) = GetParam(); } 10476e0c9e46SJames Henderson 10486e0c9e46SJames Henderson uint64_t editPrologue(LineTable <) override { 10496e0c9e46SJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 10506e0c9e46SJames Henderson Prologue.LineRange = LineRange; 10516e0c9e46SJames Henderson LT.setPrologue(Prologue); 10526e0c9e46SJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 10536e0c9e46SJames Henderson } 10546e0c9e46SJames Henderson 10556e0c9e46SJames Henderson uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 10566e0c9e46SJames Henderson uint64_t SpecialIncr, 10576e0c9e46SJames Henderson uint64_t AdvanceIncr) override { 10586e0c9e46SJames Henderson if (LineRange == 0) 10596e0c9e46SJames Henderson return Base + AdvanceIncr; 10606e0c9e46SJames Henderson return AdjustAddressFixtureBase::getAdjustedAddr(Base, ConstIncr, 10616e0c9e46SJames Henderson SpecialIncr, AdvanceIncr); 10626e0c9e46SJames Henderson } 10636e0c9e46SJames Henderson 10646e0c9e46SJames Henderson uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override { 10656e0c9e46SJames Henderson return LineRange != 0 10666e0c9e46SJames Henderson ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr) 10676e0c9e46SJames Henderson : Base; 10686e0c9e46SJames Henderson } 10696e0c9e46SJames Henderson 10706e0c9e46SJames Henderson uint8_t LineRange; 10716e0c9e46SJames Henderson }; 10726e0c9e46SJames Henderson 1073*d24e721dSJake Egan #ifdef _AIX 1074*d24e721dSJake Egan TEST_P(LineRangeFixture, DISABLED_LineRangeProblemsReportedCorrectly) { 1075*d24e721dSJake Egan #else 10766e0c9e46SJames Henderson TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) { 1077*d24e721dSJake Egan #endif 10786e0c9e46SJames Henderson runTest(/*CheckAdvancePC=*/false, 10796e0c9e46SJames Henderson "but the prologue line_range value is 0. The address and line will " 10806e0c9e46SJames Henderson "not be adjusted"); 10816e0c9e46SJames Henderson } 10826e0c9e46SJames Henderson 1083d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 10846e0c9e46SJames Henderson LineRangeParams, LineRangeFixture, 10856e0c9e46SJames Henderson Values(std::make_tuple(0, true), // Test zero value (error). 1086d4d80a29SBenjamin Kramer std::make_tuple(14, false))); // Test non-zero value (no error). 10876e0c9e46SJames Henderson 1088684d6fdeSJames Henderson struct BadMinInstLenFixture : TestWithParam<std::tuple<uint8_t, bool>>, 1089684d6fdeSJames Henderson AdjustAddressFixtureBase { 1090684d6fdeSJames Henderson void SetUp() override { 1091684d6fdeSJames Henderson std::tie(MinInstLength, IsErrorExpected) = GetParam(); 1092684d6fdeSJames Henderson } 1093684d6fdeSJames Henderson 1094684d6fdeSJames Henderson uint64_t editPrologue(LineTable <) override { 1095684d6fdeSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 1096684d6fdeSJames Henderson Prologue.MinInstLength = MinInstLength; 1097684d6fdeSJames Henderson LT.setPrologue(Prologue); 1098684d6fdeSJames Henderson return Prologue.TotalLength + Prologue.sizeofTotalLength(); 1099684d6fdeSJames Henderson } 1100684d6fdeSJames Henderson 1101684d6fdeSJames Henderson uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, 1102684d6fdeSJames Henderson uint64_t SpecialIncr, 1103684d6fdeSJames Henderson uint64_t AdvanceIncr) override { 1104684d6fdeSJames Henderson return MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( 1105684d6fdeSJames Henderson Base, ConstIncr, SpecialIncr, AdvanceIncr) 1106684d6fdeSJames Henderson : Base; 1107684d6fdeSJames Henderson } 1108684d6fdeSJames Henderson 1109684d6fdeSJames Henderson uint8_t MinInstLength; 1110684d6fdeSJames Henderson }; 1111684d6fdeSJames Henderson 1112*d24e721dSJake Egan #ifdef _AIX 1113*d24e721dSJake Egan TEST_P(BadMinInstLenFixture, DISABLED_MinInstLengthProblemsReportedCorrectly) { 1114*d24e721dSJake Egan #else 1115684d6fdeSJames Henderson TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) { 1116*d24e721dSJake Egan #endif 1117684d6fdeSJames Henderson runTest(/*CheckAdvancePC=*/true, 1118684d6fdeSJames Henderson "but the prologue minimum_instruction_length value is 0, which " 1119684d6fdeSJames Henderson "prevents any address advancing"); 1120684d6fdeSJames Henderson } 1121684d6fdeSJames Henderson 1122d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 1123684d6fdeSJames Henderson BadMinInstLenParams, BadMinInstLenFixture, 1124684d6fdeSJames Henderson Values(std::make_tuple(0, true), // Test zero value (error). 1125d4d80a29SBenjamin Kramer std::make_tuple(1, false))); // Test non-zero value (no error). 1126684d6fdeSJames Henderson 1127*d24e721dSJake Egan #ifdef _AIX 1128*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserParsesCorrectly) { 1129*d24e721dSJake Egan #else 1130a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { 1131*d24e721dSJake Egan #endif 1132a3acf99eSJames Henderson if (!setupGenerator()) 1133a3acf99eSJames Henderson return; 1134a3acf99eSJames Henderson 1135a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 1136a3acf99eSJames Henderson 113711a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 1138a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1139a3acf99eSJames Henderson 1140004b729eSJames Henderson DWARFDebugLine::LineTable Parsed = 1141004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1142a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16); 114311a9de74SJames Henderson EXPECT_EQ(Parsed.Sequences.size(), 1u); 114411a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 1145a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1146a3acf99eSJames Henderson 1147a3acf99eSJames Henderson DWARFDebugLine::LineTable Parsed2 = 1148004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1149a3acf99eSJames Henderson checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16); 115011a9de74SJames Henderson EXPECT_EQ(Parsed2.Sequences.size(), 1u); 115111a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 1152a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1153a3acf99eSJames Henderson 1154004b729eSJames Henderson EXPECT_FALSE(Recoverable); 1155004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1156a3acf99eSJames Henderson } 1157a3acf99eSJames Henderson 1158*d24e721dSJake Egan #ifdef _AIX 1159*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserSkipsCorrectly) { 1160*d24e721dSJake Egan #else 1161a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) { 1162*d24e721dSJake Egan #endif 1163a3acf99eSJames Henderson if (!setupGenerator()) 1164a3acf99eSJames Henderson return; 1165a3acf99eSJames Henderson 1166a3acf99eSJames Henderson DWARFDebugLine::SectionParser Parser = setupParser(); 1167a3acf99eSJames Henderson 116811a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 0u); 1169a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1170a3acf99eSJames Henderson 11717116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 117211a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 62u); 1173a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1174a3acf99eSJames Henderson 11757116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 117611a9de74SJames Henderson EXPECT_EQ(Parser.getOffset(), 136u); 1177a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1178a3acf99eSJames Henderson 11797116e431SJames Henderson EXPECT_FALSE(Recoverable); 1180004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1181a3acf99eSJames Henderson } 1182a3acf99eSJames Henderson 1183*d24e721dSJake Egan #ifdef _AIX 1184*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_ParserAlwaysDoneForEmptySection) { 1185*d24e721dSJake Egan #else 1186a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) { 1187*d24e721dSJake Egan #endif 1188a3acf99eSJames Henderson if (!setupGenerator()) 1189a3acf99eSJames Henderson return; 1190a3acf99eSJames Henderson 1191a3acf99eSJames Henderson generate(); 119251a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1193a3acf99eSJames Henderson 1194a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1195a3acf99eSJames Henderson } 1196a3acf99eSJames Henderson 1197*d24e721dSJake Egan #ifdef _AIX 1198*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1199*d24e721dSJake Egan DISABLED_ParserMarkedAsDoneForBadLengthWhenParsing) { 1200*d24e721dSJake Egan #else 1201d978656fSPavel Labath TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) { 1202*d24e721dSJake Egan #endif 1203a3acf99eSJames Henderson if (!setupGenerator()) 1204a3acf99eSJames Henderson return; 1205a3acf99eSJames Henderson 1206a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 1207f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1208a3acf99eSJames Henderson Gen->addLineTable(); 1209a3acf99eSJames Henderson generate(); 1210a3acf99eSJames Henderson 121151a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1212004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1213a3acf99eSJames Henderson 1214d978656fSPavel Labath EXPECT_EQ(Parser.getOffset(), 0u); 1215a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 1216004b729eSJames Henderson EXPECT_FALSE(Recoverable); 1217a3acf99eSJames Henderson 12189b23024cSPavel Labath EXPECT_THAT_ERROR( 12199b23024cSPavel Labath std::move(Unrecoverable), 12209b23024cSPavel Labath FailedWithMessage( 1221d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 1222d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 1223a3acf99eSJames Henderson } 1224a3acf99eSJames Henderson 1225*d24e721dSJake Egan #ifdef _AIX 1226*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1227*d24e721dSJake Egan DISABLED_ParserMarkedAsDoneForBadLengthWhenSkipping) { 1228*d24e721dSJake Egan #else 1229d978656fSPavel Labath TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) { 1230*d24e721dSJake Egan #endif 1231a3acf99eSJames Henderson if (!setupGenerator()) 1232a3acf99eSJames Henderson return; 1233a3acf99eSJames Henderson 1234a3acf99eSJames Henderson LineTable < = Gen->addLineTable(); 1235f48bc018SIgor Kudrin LT.setCustomPrologue({{0xfffffff0, LineTable::Long}}); 1236a3acf99eSJames Henderson Gen->addLineTable(); 1237a3acf99eSJames Henderson generate(); 1238a3acf99eSJames Henderson 123951a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 12407116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1241a3acf99eSJames Henderson 1242d978656fSPavel Labath EXPECT_EQ(Parser.getOffset(), 0u); 1243a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 12447116e431SJames Henderson EXPECT_FALSE(Recoverable); 1245a3acf99eSJames Henderson 12469b23024cSPavel Labath EXPECT_THAT_ERROR( 12479b23024cSPavel Labath std::move(Unrecoverable), 12489b23024cSPavel Labath FailedWithMessage( 1249d978656fSPavel Labath "parsing line table prologue at offset 0x00000000: unsupported " 1250d978656fSPavel Labath "reserved unit length of value 0xfffffff0")); 1251a3acf99eSJames Henderson } 1252a3acf99eSJames Henderson 1253*d24e721dSJake Egan #ifdef _AIX 1254*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1255*d24e721dSJake Egan DISABLED_ParserReportsFirstErrorInEachTableWhenParsing) { 1256*d24e721dSJake Egan #else 1257a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { 1258*d24e721dSJake Egan #endif 1259a3acf99eSJames Henderson if (!setupGenerator()) 1260a3acf99eSJames Henderson return; 1261a3acf99eSJames Henderson 1262a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1263a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1264a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1265a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1266a3acf99eSJames Henderson generate(); 1267a3acf99eSJames Henderson 126851a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1269004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1270a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 1271004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1272a3acf99eSJames Henderson 1273a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 12749b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded()); 1275a3acf99eSJames Henderson 12769b23024cSPavel Labath EXPECT_THAT_ERROR( 12779b23024cSPavel Labath std::move(Unrecoverable), 1278d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1279d978656fSPavel Labath "unsupported version 0", 1280d978656fSPavel Labath "parsing line table prologue at offset 0x00000006: " 1281d978656fSPavel Labath "unsupported version 1")); 1282a3acf99eSJames Henderson } 1283a3acf99eSJames Henderson 1284*d24e721dSJake Egan #ifdef _AIX 1285*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1286*d24e721dSJake Egan DISABLED_ParserReportsNonPrologueProblemsWhenParsing) { 1287*d24e721dSJake Egan #else 1288a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { 1289*d24e721dSJake Egan #endif 1290a3acf99eSJames Henderson if (!setupGenerator()) 1291a3acf99eSJames Henderson return; 1292a3acf99eSJames Henderson 1293a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1294a3acf99eSJames Henderson LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {}); 1295a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1296a3acf99eSJames Henderson LT2.addExtendedOpcode(9, DW_LNE_set_address, 1297a3acf99eSJames Henderson {{0x1234567890abcdef, LineTable::Quad}}); 1298a3acf99eSJames Henderson LT2.addStandardOpcode(DW_LNS_copy, {}); 1299a3acf99eSJames Henderson LT2.addByte(0xbb); 1300a3acf99eSJames Henderson generate(); 1301a3acf99eSJames Henderson 130251a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 1303004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1304f1be770fSJames Henderson EXPECT_FALSE(Unrecoverable); 1305a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 13069b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 13079b23024cSPavel Labath FailedWithMessage("unexpected line op length at offset " 13089b23024cSPavel Labath "0x00000030 expected 0x42 found 0x01")); 1309a3acf99eSJames Henderson 1310a3acf99eSJames Henderson // Reset the error state so that it does not confuse the next set of checks. 1311004b729eSJames Henderson Unrecoverable = Error::success(); 1312004b729eSJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable); 1313a3acf99eSJames Henderson 1314a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13159b23024cSPavel Labath EXPECT_THAT_ERROR(std::move(Recoverable), 13169b23024cSPavel Labath FailedWithMessage("last sequence in debug line table at " 13179b23024cSPavel Labath "offset 0x00000031 is not terminated")); 1318004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 1319a3acf99eSJames Henderson } 1320a3acf99eSJames Henderson 1321*d24e721dSJake Egan #ifdef _AIX 1322*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1323*d24e721dSJake Egan DISABLED_ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1324*d24e721dSJake Egan #else 1325a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, 1326a3acf99eSJames Henderson ParserReportsPrologueErrorsInEachTableWhenSkipping) { 1327*d24e721dSJake Egan #endif 1328a3acf99eSJames Henderson if (!setupGenerator()) 1329a3acf99eSJames Henderson return; 1330a3acf99eSJames Henderson 1331a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1332a3acf99eSJames Henderson LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}}); 1333a3acf99eSJames Henderson LineTable <2 = Gen->addLineTable(DWARF32); 1334a3acf99eSJames Henderson LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}}); 1335a3acf99eSJames Henderson generate(); 1336a3acf99eSJames Henderson 133751a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 13387116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1339a3acf99eSJames Henderson ASSERT_FALSE(Parser.done()); 13407116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1341a3acf99eSJames Henderson 1342a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13437116e431SJames Henderson EXPECT_FALSE(Recoverable); 1344a3acf99eSJames Henderson 13459b23024cSPavel Labath EXPECT_THAT_ERROR( 13469b23024cSPavel Labath std::move(Unrecoverable), 1347d978656fSPavel Labath FailedWithMessage("parsing line table prologue at offset 0x00000000: " 1348d978656fSPavel Labath "unsupported version 0", 1349d978656fSPavel Labath "parsing line table prologue at offset 0x00000006: " 1350d978656fSPavel Labath "unsupported version 1")); 1351a3acf99eSJames Henderson } 1352a3acf99eSJames Henderson 1353*d24e721dSJake Egan #ifdef _AIX 1354*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, 1355*d24e721dSJake Egan DISABLED_ParserIgnoresNonPrologueErrorsWhenSkipping) { 1356*d24e721dSJake Egan #else 1357a3acf99eSJames Henderson TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) { 1358*d24e721dSJake Egan #endif 1359a3acf99eSJames Henderson if (!setupGenerator()) 1360a3acf99eSJames Henderson return; 1361a3acf99eSJames Henderson 1362a3acf99eSJames Henderson LineTable < = Gen->addLineTable(DWARF32); 1363a3acf99eSJames Henderson LT.addExtendedOpcode(42, DW_LNE_end_sequence, {}); 1364a3acf99eSJames Henderson generate(); 1365a3acf99eSJames Henderson 136651a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 13677116e431SJames Henderson Parser.skip(RecordRecoverable, RecordUnrecoverable); 1368a3acf99eSJames Henderson 1369a3acf99eSJames Henderson EXPECT_TRUE(Parser.done()); 13707116e431SJames Henderson EXPECT_FALSE(Recoverable); 1371004b729eSJames Henderson EXPECT_FALSE(Unrecoverable); 137266702629SJames Henderson } 137366702629SJames Henderson 1374*d24e721dSJake Egan #ifdef _AIX 1375*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_VerboseOutput) { 1376*d24e721dSJake Egan #else 1377e3547adeSJames Henderson TEST_F(DebugLineBasicFixture, VerboseOutput) { 1378*d24e721dSJake Egan #endif 1379e3547adeSJames Henderson if (!setupGenerator(5)) 13802f815502SJames Henderson return; 13812f815502SJames Henderson 1382e3547adeSJames Henderson LineTable < = Gen->addLineTable(); 1383e3547adeSJames Henderson LT.addByte(0); // Extended opcode with zero length. 1384e3547adeSJames Henderson LT.addByte(0); 1385e3547adeSJames Henderson // Zero-value extended opcode. 1386e3547adeSJames Henderson LT.addExtendedOpcode(2, 0, {{1, LineTable::Byte}}); 1387e3547adeSJames Henderson // Unknown extended opcode. 1388e3547adeSJames Henderson LT.addExtendedOpcode(2, 0x42, {{1, LineTable::Byte}}); 1389e3547adeSJames Henderson LT.addExtendedOpcode(9, DW_LNE_set_address, 1390e3547adeSJames Henderson {{0x123456789abcdef, LineTable::Quad}}); 1391e3547adeSJames Henderson LT.addExtendedOpcode(6, DW_LNE_define_file, 1392e3547adeSJames Henderson {{'a', LineTable::Byte}, 1393e3547adeSJames Henderson {'\0', LineTable::Byte}, 1394e3547adeSJames Henderson {2, LineTable::ULEB}, 1395e3547adeSJames Henderson {3, LineTable::ULEB}, 1396e3547adeSJames Henderson {4, LineTable::ULEB}}); 1397e3547adeSJames Henderson LT.addExtendedOpcode(2, DW_LNE_set_discriminator, {{0x7f, LineTable::ULEB}}); 13982f815502SJames Henderson LT.addStandardOpcode(DW_LNS_copy, {}); 1399e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_advance_pc, {{11, LineTable::ULEB}}); 1400e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_advance_line, {{22, LineTable::SLEB}}); 1401e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_file, {{33, LineTable::ULEB}}); 1402e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_column, {{44, LineTable::ULEB}}); 14032f815502SJames Henderson LT.addStandardOpcode(DW_LNS_negate_stmt, {}); 14042f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_basic_block, {}); 14052f815502SJames Henderson LT.addStandardOpcode(DW_LNS_const_add_pc, {}); 1406e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{55, LineTable::Half}}); 14072f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); 14082f815502SJames Henderson LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {}); 1409e3547adeSJames Henderson LT.addStandardOpcode(DW_LNS_set_isa, {{66, LineTable::ULEB}}); 14103b7ec64dSJames Henderson // Add unknown standard opcode with operands. 1411e3547adeSJames Henderson LT.addStandardOpcode( 1412e3547adeSJames Henderson 0xd, {{1, LineTable::ULEB}, {0x123456789abcdef, LineTable::ULEB}}); 14133b7ec64dSJames Henderson // Add unknown standard opcode without operands. 14143b7ec64dSJames Henderson LT.addStandardOpcode(0xe, {}); 1415e3547adeSJames Henderson LT.addByte(0xff); // Special opcode. 14162f815502SJames Henderson LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); 1417e3547adeSJames Henderson 1418e3547adeSJames Henderson // Adjust the prologue to account for the extra standard opcode. 1419e3547adeSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 14203b7ec64dSJames Henderson Prologue.TotalLength += 2; 14213b7ec64dSJames Henderson Prologue.PrologueLength += 2; 14223b7ec64dSJames Henderson Prologue.OpcodeBase += 2; 1423e3547adeSJames Henderson Prologue.StandardOpcodeLengths.push_back(2); 14243b7ec64dSJames Henderson Prologue.StandardOpcodeLengths.push_back(0); 1425e3547adeSJames Henderson LT.setPrologue(Prologue); 1426e3547adeSJames Henderson 14272f815502SJames Henderson generate(); 14282f815502SJames Henderson 142951a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 14302f815502SJames Henderson std::string Output; 14312f815502SJames Henderson raw_string_ostream OS(Output); 1432dbd26fe0SJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1433dbd26fe0SJames Henderson /*Verbose=*/true); 14342f815502SJames Henderson OS.flush(); 1435e3547adeSJames Henderson StringRef OutputRef(Output); 14362f815502SJames Henderson 1437e3547adeSJames Henderson size_t Pos = 0; 1438e3547adeSJames Henderson auto NextLine = [&Pos, &OutputRef]() { 1439e3547adeSJames Henderson size_t EOL = OutputRef.find_first_of('\n', Pos); 1440e3547adeSJames Henderson StringRef Line = OutputRef.substr(Pos, EOL - Pos); 1441e3547adeSJames Henderson Pos = EOL + 1; 1442e3547adeSJames Henderson return Line; 14432f815502SJames Henderson }; 1444e3547adeSJames Henderson EXPECT_EQ(NextLine(), "Line table prologue:"); 14453b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " total_length: 0x00000078"); 1446e3547adeSJames Henderson EXPECT_EQ(NextLine(), " format: DWARF32"); 1447e3547adeSJames Henderson EXPECT_EQ(NextLine(), " version: 5"); 1448e3547adeSJames Henderson EXPECT_EQ(NextLine(), " address_size: 8"); 1449e3547adeSJames Henderson EXPECT_EQ(NextLine(), " seg_select_size: 0"); 14503b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " prologue_length: 0x0000002c"); 1451e3547adeSJames Henderson EXPECT_EQ(NextLine(), " min_inst_length: 1"); 1452e3547adeSJames Henderson EXPECT_EQ(NextLine(), "max_ops_per_inst: 1"); 1453e3547adeSJames Henderson EXPECT_EQ(NextLine(), " default_is_stmt: 1"); 1454e3547adeSJames Henderson EXPECT_EQ(NextLine(), " line_base: -5"); 1455e3547adeSJames Henderson EXPECT_EQ(NextLine(), " line_range: 14"); 14563b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " opcode_base: 15"); 1457e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_copy] = 0"); 1458e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_pc] = 1"); 1459e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_advance_line] = 1"); 1460e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_file] = 1"); 1461e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_column] = 1"); 1462e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_negate_stmt] = 0"); 1463e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_basic_block] = 0"); 1464e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_const_add_pc] = 0"); 1465e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1"); 1466e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_prologue_end] = 0"); 1467e3547adeSJames Henderson EXPECT_EQ(NextLine(), 1468e3547adeSJames Henderson "standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0"); 1469e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_set_isa] = 1"); 1470e3547adeSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_d] = 2"); 14713b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "standard_opcode_lengths[DW_LNS_unknown_e] = 0"); 1472e3547adeSJames Henderson EXPECT_EQ(NextLine(), "include_directories[ 0] = \"a dir\""); 1473e3547adeSJames Henderson EXPECT_EQ(NextLine(), "file_names[ 0]:"); 1474e3547adeSJames Henderson EXPECT_EQ(NextLine(), " name: \"a file\""); 1475e3547adeSJames Henderson EXPECT_EQ(NextLine(), " dir_index: 0"); 1476e3547adeSJames Henderson EXPECT_EQ(NextLine(), ""); 1477e3547adeSJames Henderson EXPECT_EQ(NextLine(), " Address Line Column File ISA Discriminator Flags"); 1478e3547adeSJames Henderson EXPECT_EQ(NextLine(), " ------------------ ------ ------ ------ --- ------------- -------------"); 1479e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14803b7ec64dSJames Henderson "0x00000038: 00 Badly formed extended line op (length 0)"); 1481e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14823b7ec64dSJames Henderson "0x0000003a: 00 Unrecognized extended op 0x00 length 2"); 1483e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14843b7ec64dSJames Henderson "0x0000003e: 00 Unrecognized extended op 0x42 length 2"); 1485e3547adeSJames Henderson EXPECT_EQ(NextLine(), 14863b7ec64dSJames Henderson "0x00000042: 00 DW_LNE_set_address (0x0123456789abcdef)"); 14873b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000004d: 00 DW_LNE_define_file (a, dir=2, " 1488e3547adeSJames Henderson "mod_time=(0x0000000000000003), length=4)"); 14893b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000055: 00 DW_LNE_set_discriminator (127)"); 14903b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy"); 1491e3547adeSJames Henderson EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 " 1492e3547adeSJames Henderson "0 127 is_stmt"); 14933b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (11)"); 14943b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)"); 14953b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)"); 14963b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)"); 14973b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt"); 14983b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block"); 1499e3547adeSJames Henderson EXPECT_EQ(NextLine(), 15003b7ec64dSJames Henderson "0x00000064: 08 DW_LNS_const_add_pc (0x0000000000000011)"); 15013b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (0x0037)"); 15023b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end"); 15033b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin"); 15043b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)"); 15053b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode " 15063b7ec64dSJames Henderson "(operands: 0x0000000000000001, 0x0123456789abcdef)"); 15073b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode"); 15083b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3"); 1509e3547adeSJames Henderson EXPECT_EQ(NextLine(), 15103b7ec64dSJames Henderson " 0x0123456789abce53 20 44 33 66 " 1511e3547adeSJames Henderson " 0 basic_block prologue_end epilogue_begin"); 15123b7ec64dSJames Henderson EXPECT_EQ(NextLine(), "0x00000079: 00 DW_LNE_end_sequence"); 15133b7ec64dSJames Henderson EXPECT_EQ(NextLine(), " 0x0123456789abce53 20 44 33 " 1514e3547adeSJames Henderson "66 0 end_sequence"); 1515e3547adeSJames Henderson EXPECT_EQ(NextLine(), ""); 1516e3547adeSJames Henderson EXPECT_EQ(Output.size(), Pos); 15172f815502SJames Henderson } 15182f815502SJames Henderson 15199e09a54cSJames Henderson struct TruncatedPrologueFixture 15209e09a54cSJames Henderson : public TestWithParam< 15219e09a54cSJames Henderson std::tuple<uint64_t, uint64_t, uint16_t, DwarfFormat, StringRef>>, 15229e09a54cSJames Henderson public CommonFixture { 152331eb8349SLogan Smith void SetUp() override { 15249e09a54cSJames Henderson std::tie(Length, ExpectedOffset, Version, Format, ExpectedErr) = GetParam(); 15259e09a54cSJames Henderson } 15269e09a54cSJames Henderson 15279e09a54cSJames Henderson uint64_t Length; 15289e09a54cSJames Henderson uint64_t ExpectedOffset; 15299e09a54cSJames Henderson uint16_t Version; 15309e09a54cSJames Henderson DwarfFormat Format; 15319e09a54cSJames Henderson StringRef ExpectedErr; 15329e09a54cSJames Henderson }; 15339e09a54cSJames Henderson 1534*d24e721dSJake Egan #ifdef _AIX 1535*d24e721dSJake Egan TEST_P(TruncatedPrologueFixture, DISABLED_ErrorForTruncatedPrologue) { 1536*d24e721dSJake Egan #else 15379e09a54cSJames Henderson TEST_P(TruncatedPrologueFixture, ErrorForTruncatedPrologue) { 1538*d24e721dSJake Egan #endif 15399e09a54cSJames Henderson if (!setupGenerator(Version)) 15409e09a54cSJames Henderson return; 15419e09a54cSJames Henderson 15429e09a54cSJames Henderson LineTable &Padding = Gen->addLineTable(); 15439e09a54cSJames Henderson // Add some padding to show that a non-zero offset is handled correctly. 15449e09a54cSJames Henderson Padding.setCustomPrologue({{0, LineTable::Byte}}); 15459e09a54cSJames Henderson 15469e09a54cSJames Henderson // Add a table with only two standard opcodes - we don't need to test the full 15479e09a54cSJames Henderson // set. 15489e09a54cSJames Henderson LineTable &Table = Gen->addLineTable(Format); 15499e09a54cSJames Henderson DWARFDebugLine::Prologue InputPrologue = Table.createBasicPrologue(); 15509e09a54cSJames Henderson InputPrologue.OpcodeBase = 3; 15519e09a54cSJames Henderson InputPrologue.StandardOpcodeLengths.resize(2); 15529e09a54cSJames Henderson Table.setPrologue(InputPrologue); 15539e09a54cSJames Henderson 15549e09a54cSJames Henderson generate(); 15559e09a54cSJames Henderson // Truncate the data extractor to the specified length. 15569e09a54cSJames Henderson LineData = DWARFDataExtractor(LineData, Length); 15579e09a54cSJames Henderson 15589e09a54cSJames Henderson DWARFDebugLine::Prologue Prologue; 15599e09a54cSJames Henderson uint64_t Offset = 1; 15609e09a54cSJames Henderson Error Err = Prologue.parse(LineData, &Offset, RecordRecoverable, *Context); 15619e09a54cSJames Henderson 15629e09a54cSJames Henderson EXPECT_THAT_ERROR(std::move(Err), FailedWithMessage(ExpectedErr.str())); 15639e09a54cSJames Henderson EXPECT_EQ(Offset, ExpectedOffset); 15649e09a54cSJames Henderson } 15659e09a54cSJames Henderson 1566d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 15679e09a54cSJames Henderson TruncatedPrologueParams, TruncatedPrologueFixture, 15689e09a54cSJames Henderson Values( 15699e09a54cSJames Henderson // Truncated length: 15709e09a54cSJames Henderson std::make_tuple( 15719e09a54cSJames Henderson 4, 1, 4, DWARF32, 15729e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15739e09a54cSJames Henderson "of data at offset 0x4 while reading [0x1, 0x5)"), 15749e09a54cSJames Henderson std::make_tuple( 15759e09a54cSJames Henderson 4, 1, 4, DWARF64, 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 0xc, 1, 4, DWARF64, 15809e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15819e09a54cSJames Henderson "of data at offset 0xc while reading [0x5, 0xd)"), 15829e09a54cSJames Henderson // Truncated version: 15839e09a54cSJames Henderson std::make_tuple( 15849e09a54cSJames Henderson 6, 5, 4, DWARF32, 15859e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15869e09a54cSJames Henderson "of data at offset 0x6 while reading [0x5, 0x7)"), 15879e09a54cSJames Henderson // Truncated address size: 15889e09a54cSJames Henderson std::make_tuple( 15899e09a54cSJames Henderson 7, 7, 5, DWARF32, 15909e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15919e09a54cSJames Henderson "of data at offset 0x7 while reading [0x7, 0x8)"), 15929e09a54cSJames Henderson // Truncated segment selector size: 15939e09a54cSJames Henderson std::make_tuple( 15949e09a54cSJames Henderson 8, 8, 5, DWARF32, 15959e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 15969e09a54cSJames Henderson "of data at offset 0x8 while reading [0x8, 0x9)"), 15979e09a54cSJames Henderson // Truncated prologue length: 15989e09a54cSJames Henderson std::make_tuple( 15999e09a54cSJames Henderson 0xa, 7, 4, DWARF32, 16009e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16019e09a54cSJames Henderson "of data at offset 0xa while reading [0x7, 0xb)"), 16029e09a54cSJames Henderson std::make_tuple( 16039e09a54cSJames Henderson 0x16, 0xf, 4, DWARF64, 16049e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16059e09a54cSJames Henderson "of data at offset 0x16 while reading [0xf, 0x17)"), 16069e09a54cSJames Henderson // Truncated min instruction length: 16079e09a54cSJames Henderson std::make_tuple( 16089e09a54cSJames Henderson 0xb, 0xb, 4, DWARF32, 16099e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16109e09a54cSJames Henderson "of data at offset 0xb while reading [0xb, 0xc)"), 16119e09a54cSJames Henderson // Truncated max ops per inst: 16129e09a54cSJames Henderson std::make_tuple( 16139e09a54cSJames Henderson 0xc, 0xc, 4, DWARF32, 16149e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16159e09a54cSJames Henderson "of data at offset 0xc while reading [0xc, 0xd)"), 16169e09a54cSJames Henderson // Truncated default is stmt: 16179e09a54cSJames Henderson std::make_tuple( 16189e09a54cSJames Henderson 0xd, 0xd, 4, DWARF32, 16199e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16209e09a54cSJames Henderson "of data at offset 0xd while reading [0xd, 0xe)"), 16219e09a54cSJames Henderson // Truncated line base: 16229e09a54cSJames Henderson std::make_tuple( 16239e09a54cSJames Henderson 0xe, 0xe, 4, DWARF32, 16249e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16259e09a54cSJames Henderson "of data at offset 0xe while reading [0xe, 0xf)"), 16269e09a54cSJames Henderson // Truncated line range: 16279e09a54cSJames Henderson std::make_tuple( 16289e09a54cSJames Henderson 0xf, 0xf, 4, DWARF32, 16299e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16309e09a54cSJames Henderson "of data at offset 0xf while reading [0xf, 0x10)"), 16319e09a54cSJames Henderson // Truncated opcode base: 16329e09a54cSJames Henderson std::make_tuple( 16339e09a54cSJames Henderson 0x10, 0x10, 4, DWARF32, 16349e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16359e09a54cSJames Henderson "of data at offset 0x10 while reading [0x10, 0x11)"), 16369e09a54cSJames Henderson // Truncated first standard opcode: 16379e09a54cSJames Henderson std::make_tuple( 16389e09a54cSJames Henderson 0x11, 0x11, 4, DWARF32, 16399e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 16409e09a54cSJames Henderson "of data at offset 0x11 while reading [0x11, 0x12)"), 16419e09a54cSJames Henderson // Truncated second standard opcode: 16429e09a54cSJames Henderson std::make_tuple( 16439e09a54cSJames Henderson 0x12, 0x12, 4, DWARF32, 16449e09a54cSJames Henderson "parsing line table prologue at offset 0x00000001: unexpected end " 1645d4d80a29SBenjamin Kramer "of data at offset 0x12 while reading [0x12, 0x13)"))); 16469e09a54cSJames Henderson 16475777570dSJames Henderson using ValueAndLengths = std::vector<LineTable::ValueAndLength>; 16485777570dSJames Henderson 16491a789047SJames Henderson struct TruncatedOpcodeFixtureBase : public CommonFixture { 16501a789047SJames Henderson LineTable &setupTable() { 16515777570dSJames Henderson LineTable < = Gen->addLineTable(); 16521a789047SJames Henderson 16531a789047SJames Henderson // Creating the prologue before adding any opcodes ensures that the unit 16545777570dSJames Henderson // length does not include the table body. 16555777570dSJames Henderson DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); 16565777570dSJames Henderson 16571a789047SJames Henderson // Add an unrecognised standard opcode, and adjust prologue properties 16581a789047SJames Henderson // accordingly. 16591a789047SJames Henderson Prologue.TotalLength += BodyLength + 1; 16601a789047SJames Henderson ++Prologue.PrologueLength; 16611a789047SJames Henderson ++Prologue.OpcodeBase; 16621a789047SJames Henderson Prologue.StandardOpcodeLengths.push_back(2); 16631a789047SJames Henderson LT.setPrologue(Prologue); 16641a789047SJames Henderson 16651a789047SJames Henderson return LT; 16661a789047SJames Henderson } 16671a789047SJames Henderson 16681a789047SJames Henderson void runTest(uint8_t OpcodeValue) { 16691a789047SJames Henderson generate(); 167051a50534SDavid Blaikie DWARFDebugLine::SectionParser Parser(LineData, *Context, Units); 16715777570dSJames Henderson std::string Output; 16725777570dSJames Henderson raw_string_ostream OS(Output); 1673dbd26fe0SJames Henderson Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS, 1674dbd26fe0SJames Henderson /*Verbose=*/true); 16755777570dSJames Henderson OS.flush(); 16765777570dSJames Henderson 16771a789047SJames Henderson std::string LinePrefix = 16781a789047SJames Henderson ("0x0000002f: 0" + Twine::utohexstr(OpcodeValue) + " ").str(); 16795777570dSJames Henderson StringRef OutputRef(Output); 16805777570dSJames Henderson StringRef OutputToCheck = OutputRef.split(LinePrefix).second; 1681dbd26fe0SJames Henderson // Each extended opcode ends with a new line and then the table ends with an 1682dbd26fe0SJames Henderson // additional blank line. 1683dbd26fe0SJames Henderson EXPECT_EQ((ExpectedOutput + "\n\n").str(), OutputToCheck); 16845777570dSJames Henderson } 16855777570dSJames Henderson 16865777570dSJames Henderson uint64_t BodyLength; 16875777570dSJames Henderson uint8_t Opcode; 16885777570dSJames Henderson ValueAndLengths Operands; 16895777570dSJames Henderson StringRef ExpectedOutput; 16905777570dSJames Henderson StringRef ExpectedErr; 16915777570dSJames Henderson }; 16925777570dSJames Henderson 16931a789047SJames Henderson struct TruncatedStandardOpcodeFixture 16941a789047SJames Henderson : public TestWithParam< 16951a789047SJames Henderson std::tuple<uint64_t, uint8_t, ValueAndLengths, StringRef, StringRef>>, 16961a789047SJames Henderson public TruncatedOpcodeFixtureBase { 169731eb8349SLogan Smith void SetUp() override { 16981a789047SJames Henderson std::tie(BodyLength, Opcode, Operands, ExpectedOutput, ExpectedErr) = 16991a789047SJames Henderson GetParam(); 17001a789047SJames Henderson } 17011a789047SJames Henderson }; 17021a789047SJames Henderson 17031a789047SJames Henderson struct TruncatedExtendedOpcodeFixture 17041a789047SJames Henderson : public TestWithParam<std::tuple<uint64_t, uint64_t, uint8_t, 17051a789047SJames Henderson ValueAndLengths, StringRef, StringRef>>, 17061a789047SJames Henderson public TruncatedOpcodeFixtureBase { 170731eb8349SLogan Smith void SetUp() override { 17081a789047SJames Henderson std::tie(BodyLength, OpcodeLength, Opcode, Operands, ExpectedOutput, 17091a789047SJames Henderson ExpectedErr) = GetParam(); 17101a789047SJames Henderson } 17111a789047SJames Henderson 17121a789047SJames Henderson uint64_t OpcodeLength; 17131a789047SJames Henderson }; 17141a789047SJames Henderson 1715*d24e721dSJake Egan #ifdef _AIX 1716*d24e721dSJake Egan TEST_P(TruncatedExtendedOpcodeFixture, 1717*d24e721dSJake Egan DISABLED_ErrorForTruncatedExtendedOpcode) { 1718*d24e721dSJake Egan #else 17195777570dSJames Henderson TEST_P(TruncatedExtendedOpcodeFixture, ErrorForTruncatedExtendedOpcode) { 1720*d24e721dSJake Egan #endif 17215777570dSJames Henderson if (!setupGenerator()) 17225777570dSJames Henderson return; 17231a789047SJames Henderson LineTable < = setupTable(); 17241a789047SJames Henderson LT.addExtendedOpcode(OpcodeLength, Opcode, Operands); 17251a789047SJames Henderson runTest(0); 17261a789047SJames Henderson EXPECT_THAT_ERROR(std::move(Recoverable), 17271a789047SJames Henderson FailedWithMessage(ExpectedErr.str())); 17285777570dSJames Henderson } 17295777570dSJames Henderson 1730d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 17315777570dSJames Henderson TruncatedExtendedOpcodeParams, TruncatedExtendedOpcodeFixture, 17325777570dSJames Henderson Values( 17339782c922SJames Henderson // Truncated length: 17349782c922SJames Henderson std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 17351a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 17365777570dSJames Henderson "malformed uleb128, extends past end"), 17379782c922SJames Henderson // Truncated opcode: 17385777570dSJames Henderson std::make_tuple( 17399782c922SJames Henderson 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", 17401a789047SJames Henderson "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"), 17419782c922SJames Henderson // Truncated operands: 17425777570dSJames Henderson std::make_tuple( 17435777570dSJames Henderson 3, 9, DW_LNE_set_address, 17449782c922SJames Henderson ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}}, 17459782c922SJames Henderson "DW_LNE_set_address", 17461a789047SJames Henderson "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"), 17479782c922SJames Henderson std::make_tuple( 17489782c922SJames Henderson 10, 9, DW_LNE_set_address, 1749670dbad4SDavid Tenty ValueAndLengths{{0x1234567878563412, LineTable::Quad}}, 1750670dbad4SDavid Tenty "DW_LNE_set_address (<parsing error> 12 34 56 78 78 56 34)", 17519782c922SJames Henderson "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"), 17529782c922SJames Henderson std::make_tuple(3, 6, DW_LNE_define_file, 17535777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17545777570dSJames Henderson {'\0', LineTable::Byte}, 17555777570dSJames Henderson {1, LineTable::ULEB}, 17565777570dSJames Henderson {1, LineTable::ULEB}, 17575777570dSJames Henderson {1, LineTable::ULEB}}, 17589782c922SJames Henderson "DW_LNE_define_file", 17591a789047SJames Henderson "no null terminated string at offset 0x32"), 17609782c922SJames Henderson std::make_tuple(5, 6, DW_LNE_define_file, 17615777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17625777570dSJames Henderson {'\0', LineTable::Byte}, 17635777570dSJames Henderson {1, LineTable::ULEB}, 17645777570dSJames Henderson {1, LineTable::ULEB}, 17655777570dSJames Henderson {1, LineTable::ULEB}}, 17669782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00)", 17671a789047SJames Henderson "unable to decode LEB128 at offset 0x00000034: " 17685777570dSJames Henderson "malformed uleb128, extends past end"), 17699782c922SJames Henderson std::make_tuple(6, 6, DW_LNE_define_file, 17705777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17715777570dSJames Henderson {'\0', LineTable::Byte}, 17725777570dSJames Henderson {1, LineTable::ULEB}, 17735777570dSJames Henderson {1, LineTable::ULEB}, 17745777570dSJames Henderson {1, LineTable::ULEB}}, 17759782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00 01)", 17761a789047SJames Henderson "unable to decode LEB128 at offset 0x00000035: " 17775777570dSJames Henderson "malformed uleb128, extends past end"), 17789782c922SJames Henderson std::make_tuple(7, 6, DW_LNE_define_file, 17795777570dSJames Henderson ValueAndLengths{{'a', LineTable::Byte}, 17805777570dSJames Henderson {'\0', LineTable::Byte}, 17815777570dSJames Henderson {1, LineTable::ULEB}, 17825777570dSJames Henderson {1, LineTable::ULEB}, 17835777570dSJames Henderson {1, LineTable::ULEB}}, 17849782c922SJames Henderson "DW_LNE_define_file (<parsing error> 61 00 01 01)", 17851a789047SJames Henderson "unable to decode LEB128 at offset 0x00000036: " 17865777570dSJames Henderson "malformed uleb128, extends past end"), 17875777570dSJames Henderson std::make_tuple(3, 2, DW_LNE_set_discriminator, 17885777570dSJames Henderson ValueAndLengths{{1, LineTable::ULEB}}, 17899782c922SJames Henderson "DW_LNE_set_discriminator", 17901a789047SJames Henderson "unable to decode LEB128 at offset 0x00000032: " 17919782c922SJames Henderson "malformed uleb128, extends past end"), 17929782c922SJames Henderson std::make_tuple( 17939782c922SJames Henderson 6, 5, /*Unknown=*/0x7f, 1794670dbad4SDavid Tenty ValueAndLengths{{0x12343412, LineTable::Long}}, 1795670dbad4SDavid Tenty "Unrecognized extended op 0x7f length 5 (<parsing error> 12 34 34)", 17969782c922SJames Henderson "unexpected end of data at offset 0x35 while reading [0x32, " 1797d4d80a29SBenjamin Kramer "0x36)"))); 17981a789047SJames Henderson 1799*d24e721dSJake Egan #ifdef _AIX 1800*d24e721dSJake Egan TEST_P(TruncatedStandardOpcodeFixture, 1801*d24e721dSJake Egan DISABLED_ErrorForTruncatedStandardOpcode) { 1802*d24e721dSJake Egan #else 18031a789047SJames Henderson TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) { 1804*d24e721dSJake Egan #endif 18051a789047SJames Henderson if (!setupGenerator()) 18061a789047SJames Henderson return; 18071a789047SJames Henderson LineTable < = setupTable(); 18081a789047SJames Henderson LT.addStandardOpcode(Opcode, Operands); 18091a789047SJames Henderson runTest(Opcode); 18101a789047SJames Henderson EXPECT_THAT_ERROR(std::move(Unrecoverable), 18111a789047SJames Henderson FailedWithMessage(ExpectedErr.str())); 18121a789047SJames Henderson } 18131a789047SJames Henderson 1814d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P( 18151a789047SJames Henderson TruncatedStandardOpcodeParams, TruncatedStandardOpcodeFixture, 18161a789047SJames Henderson Values( 18171a789047SJames Henderson std::make_tuple(2, DW_LNS_advance_pc, 18181a789047SJames Henderson ValueAndLengths{{0x100, LineTable::ULEB}}, 18191a789047SJames Henderson "DW_LNS_advance_pc", 18201a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18211a789047SJames Henderson "malformed uleb128, extends past end"), 18221a789047SJames Henderson std::make_tuple(2, DW_LNS_advance_line, 18231a789047SJames Henderson ValueAndLengths{{0x200, LineTable::SLEB}}, 18241a789047SJames Henderson "DW_LNS_advance_line", 18251a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18261a789047SJames Henderson "malformed sleb128, extends past end"), 18271a789047SJames Henderson std::make_tuple(2, DW_LNS_set_file, 18281a789047SJames Henderson ValueAndLengths{{0x300, LineTable::ULEB}}, 18291a789047SJames Henderson "DW_LNS_set_file", 18301a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18311a789047SJames Henderson "malformed uleb128, extends past end"), 18321a789047SJames Henderson std::make_tuple(2, DW_LNS_set_column, 18331a789047SJames Henderson ValueAndLengths{{0x400, LineTable::ULEB}}, 18341a789047SJames Henderson "DW_LNS_set_column", 18351a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18361a789047SJames Henderson "malformed uleb128, extends past end"), 18371a789047SJames Henderson std::make_tuple( 18381a789047SJames Henderson 2, DW_LNS_fixed_advance_pc, 18391a789047SJames Henderson ValueAndLengths{{0x500, LineTable::Half}}, 18401a789047SJames Henderson "DW_LNS_fixed_advance_pc", 18411a789047SJames Henderson "unexpected end of data at offset 0x31 while reading [0x30, 0x32)"), 18421a789047SJames Henderson std::make_tuple(2, DW_LNS_set_isa, 18431a789047SJames Henderson ValueAndLengths{{0x600, LineTable::ULEB}}, 18441a789047SJames Henderson "DW_LNS_set_isa", 18451a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18461a789047SJames Henderson "malformed uleb128, extends past end"), 18471a789047SJames Henderson std::make_tuple(2, 0xd, 18481a789047SJames Henderson ValueAndLengths{{0x700, LineTable::ULEB}, 18491a789047SJames Henderson {0x800, LineTable::ULEB}}, 18501a789047SJames Henderson "Unrecognized standard opcode", 18511a789047SJames Henderson "unable to decode LEB128 at offset 0x00000030: " 18521a789047SJames Henderson "malformed uleb128, extends past end"), 18531a789047SJames Henderson std::make_tuple( 18541a789047SJames Henderson 4, 0xd, 18551a789047SJames Henderson ValueAndLengths{{0x900, LineTable::ULEB}, {0xa00, LineTable::ULEB}}, 18561a789047SJames Henderson "Unrecognized standard opcode (operands: 0x0000000000000900)", 18571a789047SJames Henderson "unable to decode LEB128 at offset 0x00000032: " 1858d4d80a29SBenjamin Kramer "malformed uleb128, extends past end"))); 18595777570dSJames Henderson 1860*d24e721dSJake Egan #ifdef _AIX 1861*d24e721dSJake Egan TEST_F(DebugLineBasicFixture, DISABLED_PrintPathsProperly) { 1862*d24e721dSJake Egan #else 1863417375d7SSterling Augustine TEST_F(DebugLineBasicFixture, PrintPathsProperly) { 1864*d24e721dSJake Egan #endif 1865417375d7SSterling Augustine if (!setupGenerator(5)) 1866417375d7SSterling Augustine return; 1867417375d7SSterling Augustine 1868417375d7SSterling Augustine LineTable < = Gen->addLineTable(); 1869417375d7SSterling Augustine DWARFDebugLine::Prologue P = LT.createBasicPrologue(); 1870417375d7SSterling Augustine P.IncludeDirectories.push_back( 1871417375d7SSterling Augustine DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); 1872417375d7SSterling Augustine P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); 1873417375d7SSterling Augustine P.FileNames.back().Name = 1874417375d7SSterling Augustine DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); 1875417375d7SSterling Augustine P.FileNames.back().DirIdx = 1; 18766f55b5a1SPavel Labath P.TotalLength += 14; 1877417375d7SSterling Augustine P.PrologueLength += 14; 1878417375d7SSterling Augustine LT.setPrologue(P); 1879417375d7SSterling Augustine generate(); 1880417375d7SSterling Augustine 1881417375d7SSterling Augustine auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, 1882417375d7SSterling Augustine nullptr, RecordRecoverable); 1883417375d7SSterling Augustine EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); 1884417375d7SSterling Augustine std::string Result; 1885417375d7SSterling Augustine // DWARF 5 stores the compilation directory in two places: the Compilation 1886417375d7SSterling Augustine // Unit and the directory table entry 0, and implementations are free to use 1887417375d7SSterling Augustine // one or the other. This copy serves as the one stored in the CU. 1888417375d7SSterling Augustine StringRef CompDir = "a dir"; 1889417375d7SSterling Augustine EXPECT_FALSE( 1890417375d7SSterling Augustine (*ExpectedLineTable) 1891417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1892417375d7SSterling Augustine 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); 1893417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1894417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1895417375d7SSterling Augustine 1, CompDir, 18965de4ba17SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::RawValue, Result)); 18975de4ba17SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 18985de4ba17SSterling Augustine ->Prologue.getFileNameByIndex( 18995de4ba17SSterling Augustine 1, CompDir, 19005de4ba17SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly, 19015de4ba17SSterling Augustine Result)); 1902417375d7SSterling Augustine EXPECT_STREQ(Result.c_str(), "b file"); 1903417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1904417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1905417375d7SSterling Augustine 1, CompDir, 1906417375d7SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, 1907417375d7SSterling Augustine Result)); 1908257e4127SSterling Augustine EXPECT_THAT(Result.c_str(), MatchesRegex("b dir.b file")); 1909417375d7SSterling Augustine EXPECT_TRUE((*ExpectedLineTable) 1910417375d7SSterling Augustine ->Prologue.getFileNameByIndex( 1911417375d7SSterling Augustine 1, CompDir, 1912417375d7SSterling Augustine DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 1913417375d7SSterling Augustine Result)); 1914257e4127SSterling Augustine EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file")); 1915417375d7SSterling Augustine } 1916417375d7SSterling Augustine 191766702629SJames Henderson } // end anonymous namespace 1918