[lld] 6e3ca96 - [DebugInfo] Improve error message text
Robinson, Paul via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 14 13:15:50 PST 2020
Hi James,
Did this commit mess up the line endings on DWARFDebugLineTest.cpp?
The diff makes it look like the entire file was modified.
--paulr
> -----Original Message-----
> From: llvm-commits <llvm-commits-bounces at lists.llvm.org> On Behalf Of
> James Henderson via llvm-commits
> Sent: Friday, January 10, 2020 10:00 AM
> To: llvm-commits at lists.llvm.org
> Subject: [lld] 6e3ca96 - [DebugInfo] Improve error message text
>
>
> Author: James Henderson
> Date: 2020-01-10T14:59:58Z
> New Revision: 6e3ca962fafb3d2a31279c49f0cde60eb626a002
>
> URL: https://github.com/llvm/llvm-
> project/commit/6e3ca962fafb3d2a31279c49f0cde60eb626a002
> DIFF: https://github.com/llvm/llvm-
> project/commit/6e3ca962fafb3d2a31279c49f0cde60eb626a002.diff
>
> LOG: [DebugInfo] Improve error message text
>
> Unlike most of our errors in the debug line parser, the "no end of
> sequence" message was missing any reference to which line table it
> refererred to. This change adds the offset to this message.
>
> Reviewed by: dblaikie
>
> Differential Revision: https://reviews.llvm.org/D72443
>
> Added:
>
>
> Modified:
> lld/test/ELF/undef.s
> llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
> llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
> llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
>
> Removed:
>
>
>
> ##########################################################################
> ######
> diff --git a/lld/test/ELF/undef.s b/lld/test/ELF/undef.s
> index e5ddcb5f52c6..2ca733a26fd7 100644
> --- a/lld/test/ELF/undef.s
> +++ b/lld/test/ELF/undef.s
> @@ -52,7 +52,7 @@
> # is requested, even if that particular part of the line information is
> not currently required.
> # Also show that the warnings are only printed once.
> # CHECK: warning: parsing line table prologue at 0x00000000 should
> have ended at 0x00000038 but it ended at 0x00000037
> -# CHECK-NEXT: warning: last sequence in debug line table is not
> terminated!
> +# CHECK-NEXT: warning: last sequence in debug line table at offset
> 0x0000005b is not terminated
> # CHECK: error: undefined symbol: zed6a
> # CHECK-NEXT: >>> referenced by {{.*}}tmp4.o:(.text+0x0)
> # CHECK: error: undefined symbol: zed6b
>
> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
> b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
> index 8e7ce58957d5..73480cecb982 100644
> --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
> +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
> @@ -883,9 +883,11 @@ Error DWARFDebugLine::LineTable::parse(
> }
>
> if (!State.Sequence.Empty)
> - RecoverableErrorCallback(
> - createStringError(errc::illegal_byte_sequence,
> - "last sequence in debug line table is not
> terminated!"));
> + RecoverableErrorCallback(createStringError(
> + errc::illegal_byte_sequence,
> + "last sequence in debug line table at offset 0x%8.8" PRIx64
> + " is not terminated",
> + DebugLineOffset));
>
> // Sort all sequences so that address lookup will work faster.
> if (!Sequences.empty()) {
>
> diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
> b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
> index cb8b2b8f3e4d..6bdc526570fa 100644
> --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
> +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
> @@ -158,7 +158,7 @@
> # ALL-NEXT: warning: parsing line table prologue at 0x00000081 should
> have ended at 0x000000b9 but it ended at 0x000000ba
> # ALL-NEXT: warning: parsing line table prologue at 0x000000c9 should
> have ended at 0x00000104 but it ended at 0x00000103
> # OTHER-NEXT: warning: unexpected line op length at offset 0x00000158
> expected 0x02 found 0x01
> -# OTHER-NEXT: warning: last sequence in debug line table is not
> terminated!
> +# OTHER-NEXT: warning: last sequence in debug line table at offset
> 0x00000167 is not terminated
> # ALL-NEXT: warning: parsing line table prologue at 0x000001ad should
> have ended at 0x000001c8 but it ended at 0x000001df
> # ALL-NEXT: warning: parsing line table prologue at 0x000001ed should
> have ended at 0x00000218 but it ended at 0x0000021f
> # ALL-NEXT: warning: parsing line table prologue at 0x0000022d should
> have ended at 0x0000024f but it ended at 0x0000025f
>
> diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
> b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
> index f29709442d4d..8b405b2b092d 100644
> --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
> +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
> @@ -1,761 +1,763 @@
> -//===- DWARFDebugLineTest.cpp -------------------------------------------
> --===//
> -//
> -// Part of the LLVM Project, under the Apache License v2.0 with LLVM
> Exceptions.
> -// See https://llvm.org/LICENSE.txt for license information.
> -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
> -//
> -//===--------------------------------------------------------------------
> --===//
> -
> -#include "DwarfGenerator.h"
> -#include "DwarfUtils.h"
> -#include "llvm/DebugInfo/DWARF/DWARFContext.h"
> -#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
> -#include "llvm/Object/ObjectFile.h"
> -#include "llvm/Testing/Support/Error.h"
> -#include "gtest/gtest.h"
> -
> -using namespace llvm;
> -using namespace dwarf;
> -using namespace dwarfgen;
> -using namespace object;
> -using namespace utils;
> -using namespace testing;
> -
> -namespace {
> -struct CommonFixture {
> - CommonFixture()
> - : LineData("", true, 0), Recoverable(Error::success()),
> - RecordRecoverable(std::bind(&CommonFixture::recordRecoverable,
> this,
> - std::placeholders::_1)),
> - Unrecoverable(Error::success()),
> -
> RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this,
> - std::placeholders::_1)){};
> -
> - ~CommonFixture() {
> - EXPECT_FALSE(Recoverable);
> - EXPECT_FALSE(Unrecoverable);
> - }
> -
> - bool setupGenerator(uint16_t Version = 4) {
> - Triple T = getDefaultTargetTripleForAddrSize(8);
> - if (!isConfigurationSupported(T))
> - return false;
> - auto ExpectedGenerator = Generator::create(T, Version);
> - if (ExpectedGenerator)
> - Gen.reset(ExpectedGenerator->release());
> - return true;
> - }
> -
> - void generate() {
> - Context = createContext();
> - assert(Context != nullptr && "test state is not valid");
> - const DWARFObject &Obj = Context->getDWARFObj();
> - LineData = DWARFDataExtractor(
> - Obj, Obj.getLineSection(),
> - getDefaultTargetTripleForAddrSize(8).isLittleEndian(), 8);
> - }
> -
> - std::unique_ptr<DWARFContext> createContext() {
> - if (!Gen)
> - return nullptr;
> - StringRef FileBytes = Gen->generate();
> - MemoryBufferRef FileBuffer(FileBytes, "dwarf");
> - auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
> - if (Obj)
> - return DWARFContext::create(**Obj);
> - return nullptr;
> - }
> -
> - DWARFDebugLine::SectionParser setupParser() {
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55,
> LineTable::Quad}});
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addByte(0xaa);
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> -
> - LineTable <2 = Gen->addLineTable(DWARF64);
> - LT2.addExtendedOpcode(9, DW_LNE_set_address,
> - {{0x11223344, LineTable::Quad}});
> - LT2.addStandardOpcode(DW_LNS_copy, {});
> - LT2.addByte(0xbb);
> - LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> -
> - generate();
> -
> - return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs);
> - }
> -
> - void recordRecoverable(Error Err) {
> - Recoverable = joinErrors(std::move(Recoverable), std::move(Err));
> - }
> - void recordUnrecoverable(Error Err) {
> - Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err));
> - }
> -
> - void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) {
> - ASSERT_TRUE(Err.operator bool());
> - size_t WhichMsg = 0;
> - Error Remaining =
> - handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
> - ASSERT_LT(WhichMsg, ExpectedMsgs.size());
> - // Use .str(), because googletest doesn't visualise a StringRef
> - // properly.
> - EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str());
> - });
> - EXPECT_EQ(WhichMsg, ExpectedMsgs.size());
> - EXPECT_FALSE(Remaining);
> - }
> -
> - void checkError(StringRef ExpectedMsg, Error Err) {
> - checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err));
> - }
> -
> - void checkGetOrParseLineTableEmitsFatalError(StringRef ExpectedMsg,
> - uint64_t Offset = 0) {
> - auto ExpectedLineTable = Line.getOrParseLineTable(
> - LineData, Offset, *Context, nullptr, RecordRecoverable);
> - EXPECT_FALSE(ExpectedLineTable);
> - EXPECT_FALSE(Recoverable);
> -
> - checkError(ExpectedMsg, ExpectedLineTable.takeError());
> - }
> -
> - void checkGetOrParseLineTableEmitsFatalError(ArrayRef<StringRef>
> ExpectedMsgs,
> - uint64_t Offset = 0) {
> - auto ExpectedLineTable = Line.getOrParseLineTable(
> - LineData, Offset, *Context, nullptr, RecordRecoverable);
> - EXPECT_FALSE(ExpectedLineTable);
> - EXPECT_FALSE(Recoverable);
> -
> - checkError(ExpectedMsgs, ExpectedLineTable.takeError());
> - }
> -
> - std::unique_ptr<Generator> Gen;
> - std::unique_ptr<DWARFContext> Context;
> - DWARFDataExtractor LineData;
> - DWARFDebugLine Line;
> - Error Recoverable;
> - std::function<void(Error)> RecordRecoverable;
> - Error Unrecoverable;
> - std::function<void(Error)> RecordUnrecoverable;
> -
> - SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs;
> - SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs;
> -};
> -
> -// Fixtures must derive from "Test", but parameterised fixtures from
> -// "TestWithParam". It does not seem possible to inherit from both, so we
> share
> -// the common state in a separate class, inherited by the two fixture
> classes.
> -struct DebugLineBasicFixture : public Test, public CommonFixture {};
> -
> -struct DebugLineParameterisedFixture
> - : public TestWithParam<std::pair<uint16_t, DwarfFormat>>,
> - public CommonFixture {
> - void SetUp() { std::tie(Version, Format) = GetParam(); }
> -
> - uint16_t Version;
> - DwarfFormat Format;
> -};
> -
> -void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,
> - DWARFDebugLine::Prologue Prologue,
> - uint64_t BodyLength) {
> - // Check version specific fields and values.
> - uint64_t UnitLength;
> - uint64_t PrologueLength;
> - switch (Version) {
> - case 4:
> - PrologueLength = 36;
> - UnitLength = PrologueLength + 2;
> - EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);
> - break;
> - case 2:
> - case 3:
> - PrologueLength = 35;
> - UnitLength = PrologueLength + 2;
> - break;
> - case 5:
> - PrologueLength = 39;
> - UnitLength = PrologueLength + 4;
> - EXPECT_EQ(Prologue.getAddressSize(), 8u);
> - EXPECT_EQ(Prologue.SegSelectorSize, 0u);
> - break;
> - default:
> - llvm_unreachable("unsupported DWARF version");
> - }
> - UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8);
> -
> - EXPECT_EQ(Prologue.TotalLength, UnitLength);
> - EXPECT_EQ(Prologue.PrologueLength, PrologueLength);
> - EXPECT_EQ(Prologue.MinInstLength, 1u);
> - EXPECT_EQ(Prologue.DefaultIsStmt, 1u);
> - EXPECT_EQ(Prologue.LineBase, -5);
> - EXPECT_EQ(Prologue.LineRange, 14u);
> - EXPECT_EQ(Prologue.OpcodeBase, 13u);
> - std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0,
> 0, 1};
> - EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths);
> - ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u);
> - ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string);
> - EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir");
> - ASSERT_EQ(Prologue.FileNames.size(), 1u);
> - ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string);
> - EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file");
> -}
> -
> -TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) {
> - if (!setupGenerator())
> - return;
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "offset 0x00000000 is not a valid debug line section offset", 0);
> - // Repeat to show that an error is reported each time.
> - checkGetOrParseLineTableEmitsFatalError(
> - "offset 0x00000000 is not a valid debug line section offset", 0);
> - // Show that an error is reported for later offsets too.
> - checkGetOrParseLineTableEmitsFatalError(
> - "offset 0x00000001 is not a valid debug line section offset", 1);
> -}
> -
> -TEST_F(DebugLineBasicFixture,
> GetOrParseLineTableAtInvalidOffsetAfterData) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue({{0, LineTable::Byte}});
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "offset 0x00000001 is not a valid debug line section offset", 1);
> -}
> -
> -TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
> - if (!setupGenerator(Version))
> - return;
> -
> - SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> - (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> -
> - LineTable < = Gen->addLineTable(Format);
> - LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55,
> LineTable::Quad}});
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addByte(0xaa);
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> -
> - LineTable <2 = Gen->addLineTable(Format);
> - LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344,
> LineTable::Quad}});
> - LT2.addStandardOpcode(DW_LNS_copy, {});
> - LT2.addByte(0xbb);
> - LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> - LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788,
> LineTable::Quad}});
> - LT2.addStandardOpcode(DW_LNS_copy, {});
> - LT2.addByte(0xcc);
> - LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> -
> - generate();
> -
> - auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0,
> *Context,
> - nullptr,
> RecordRecoverable);
> - ASSERT_TRUE(ExpectedLineTable.operator bool());
> - EXPECT_FALSE(Recoverable);
> - const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable;
> - checkDefaultPrologue(Version, Format, Expected->Prologue, 16);
> - EXPECT_EQ(Expected->Sequences.size(), 1u);
> -
> - uint64_t SecondOffset =
> - Expected->Prologue.sizeofTotalLength() + Expected-
> >Prologue.TotalLength;
> - Recoverable = Error::success();
> - auto ExpectedLineTable2 = Line.getOrParseLineTable(
> - LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
> - ASSERT_TRUE(ExpectedLineTable2.operator bool());
> - EXPECT_FALSE(Recoverable);
> - const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2;
> - checkDefaultPrologue(Version, Format, Expected2->Prologue, 32);
> - EXPECT_EQ(Expected2->Sequences.size(), 2u);
> -
> - EXPECT_NE(Expected, Expected2);
> -
> - // Check that if the same offset is requested, the exact same pointer
> is
> - // returned.
> - Recoverable = Error::success();
> - auto ExpectedLineTable3 = Line.getOrParseLineTable(
> - LineData, 0, *Context, nullptr, RecordRecoverable);
> - ASSERT_TRUE(ExpectedLineTable3.operator bool());
> - EXPECT_FALSE(Recoverable);
> - EXPECT_EQ(Expected, *ExpectedLineTable3);
> -
> - Recoverable = Error::success();
> - auto ExpectedLineTable4 = Line.getOrParseLineTable(
> - LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
> - ASSERT_TRUE(ExpectedLineTable4.operator bool());
> - EXPECT_FALSE(Recoverable);
> - EXPECT_EQ(Expected2, *ExpectedLineTable4);
> -
> - // TODO: Add tests that show that the body of the programs have been
> read
> - // correctly.
> -}
> -
> -TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "parsing line table prologue at offset 0x00000000 unsupported
> reserved "
> - "unit length found of value 0xfffffff0");
> -}
> -
> -TEST_F(DebugLineBasicFixture, ErrorForLowVersion) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue(
> - {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}});
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "parsing line table prologue at offset "
> - "0x00000000 found unsupported version "
> - "0x01");
> -}
> -
> -TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
> - if (!setupGenerator(5))
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue({
> - {19, LineTable::Long}, // unit length
> - {5, LineTable::Half}, // version
> - {8, LineTable::Byte}, // addr size
> - {0, LineTable::Byte}, // segment selector size
> - {11, LineTable::Long}, // prologue length
> - {1, LineTable::Byte}, // min instruction length
> - {1, LineTable::Byte}, // max ops per instruction
> - {1, LineTable::Byte}, // default is_stmt
> - {0, LineTable::Byte}, // line base
> - {14, LineTable::Byte}, // line range
> - {2, LineTable::Byte}, // opcode base (small to reduce the amount
> of
> - // setup required).
> - {0, LineTable::Byte}, // standard opcode lengths
> - {0, LineTable::Byte}, // directory entry format count (should not
> be
> - // zero).
> - {0, LineTable::ULEB}, // directories count
> - {0, LineTable::Byte}, // file name entry format count
> - {0, LineTable::ULEB} // file name entry count
> - });
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - {"parsing line table prologue at 0x00000000 found an invalid
> directory "
> - "or file table description at 0x00000014",
> - "failed to parse entry content descriptions because no path was
> found"});
> -}
> -
> -TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
> - if (!setupGenerator(Version))
> - return;
> -
> - SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> - (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> -
> - LineTable < = Gen->addLineTable(Format);
> - DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> - ++Prologue.PrologueLength;
> - LT.setPrologue(Prologue);
> -
> - generate();
> -
> - uint64_t ExpectedEnd =
> - Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
> - checkGetOrParseLineTableEmitsFatalError(
> - (Twine("parsing line table prologue at 0x00000000 should have ended
> at "
> - "0x000000") +
> - Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
> - Twine::utohexstr(ExpectedEnd - 1))
> - .str());
> -}
> -
> -TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
> - if (!setupGenerator(Version))
> - return;
> -
> - SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> - (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> -
> - LineTable < = Gen->addLineTable(Format);
> - DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> - // FIXME: Ideally, we'd test for 1 less than expected, but the code
> does not
> - // currently fail if missing only the terminator of a v2-4 file table.
> - if (Version < 5)
> - Prologue.PrologueLength -= 2;
> - else
> - Prologue.PrologueLength -= 1;
> - LT.setPrologue(Prologue);
> -
> - generate();
> -
> - uint64_t ExpectedEnd =
> - Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
> - if (Version < 5)
> - --ExpectedEnd;
> - checkGetOrParseLineTableEmitsFatalError(
> - (Twine("parsing line table prologue at 0x00000000 should have ended
> at "
> - "0x000000") +
> - Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
> - Twine::utohexstr(ExpectedEnd + 1))
> - .str());
> -}
> -
> -INSTANTIATE_TEST_CASE_P(
> - LineTableTestParams, DebugLineParameterisedFixture,
> - Values(std::make_pair(
> - 2, DWARF32), // Test lower-bound of v2-3 fields and
> DWARF32.
> - std::make_pair(3, DWARF32), // Test upper-bound of v2-3
> fields.
> - std::make_pair(4, DWARF64), // Test v4 fields and DWARF64.
> - std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), );
> -
> -TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - // The Length should be 1 for an end sequence opcode.
> - LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "unexpected line op length at offset "
> - "0x00000030 expected 0x02 found 0x01");
> -}
> -
> -TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable &Padding = Gen->addLineTable();
> - // Add some padding to show that a non-zero offset is handled
> correctly.
> - Padding.setCustomPrologue({{0, LineTable::Byte}});
> - LineTable < = Gen->addLineTable();
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addStandardOpcode(DW_LNS_const_add_pc, {});
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> - DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> - // Set the total length to 1 higher than the actual length. The program
> body
> - // has size 5.
> - Prologue.TotalLength += 6;
> - LT.setPrologue(Prologue);
> -
> - generate();
> -
> - auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1,
> *Context,
> - nullptr,
> RecordRecoverable);
> - checkError("line table program with offset 0x00000001 has length
> 0x00000034 "
> - "but only 0x00000033 bytes are available",
> - std::move(Recoverable));
> - ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
> - EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
> - EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
> -}
> -
> -TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - // The line data extractor expects size 8 (Quad) addresses.
> - LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x11223344,
> LineTable::Long}});
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addByte(0xaa);
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> -
> - generate();
> -
> - checkGetOrParseLineTableEmitsFatalError(
> - "mismatching address size at offset 0x00000030 expected 0x08 found
> 0x04");
> -}
> -
> -TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.addExtendedOpcode(9, DW_LNE_set_address,
> - {{0x1122334455667788, LineTable::Quad}});
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addByte(0xaa);
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> - LT.addExtendedOpcode(9, DW_LNE_set_address,
> - {{0x99aabbccddeeff00, LineTable::Quad}});
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addByte(0xbb);
> - LT.addByte(0xcc);
> -
> - generate();
> -
> - auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0,
> *Context,
> - nullptr,
> RecordRecoverable);
> - checkError("last sequence in debug line table is not terminated!",
> - std::move(Recoverable));
> - ASSERT_TRUE(ExpectedLineTable.operator bool());
> - EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u);
> - // The unterminated sequence is not added to the sequence list.
> - EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) {
> - if (!setupGenerator())
> - return;
> -
> - DWARFDebugLine::SectionParser Parser = setupParser();
> -
> - EXPECT_EQ(Parser.getOffset(), 0u);
> - ASSERT_FALSE(Parser.done());
> -
> - DWARFDebugLine::LineTable Parsed =
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> - checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16);
> - EXPECT_EQ(Parsed.Sequences.size(), 1u);
> - EXPECT_EQ(Parser.getOffset(), 62u);
> - ASSERT_FALSE(Parser.done());
> -
> - DWARFDebugLine::LineTable Parsed2 =
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> - checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16);
> - EXPECT_EQ(Parsed2.Sequences.size(), 1u);
> - EXPECT_EQ(Parser.getOffset(), 136u);
> - EXPECT_TRUE(Parser.done());
> -
> - EXPECT_FALSE(Recoverable);
> - EXPECT_FALSE(Unrecoverable);
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {
> - if (!setupGenerator())
> - return;
> -
> - DWARFDebugLine::SectionParser Parser = setupParser();
> -
> - EXPECT_EQ(Parser.getOffset(), 0u);
> - ASSERT_FALSE(Parser.done());
> -
> - Parser.skip(RecordUnrecoverable);
> - EXPECT_EQ(Parser.getOffset(), 62u);
> - ASSERT_FALSE(Parser.done());
> -
> - Parser.skip(RecordUnrecoverable);
> - EXPECT_EQ(Parser.getOffset(), 136u);
> - EXPECT_TRUE(Parser.done());
> -
> - EXPECT_FALSE(Unrecoverable);
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) {
> - if (!setupGenerator())
> - return;
> -
> - generate();
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> -
> - EXPECT_TRUE(Parser.done());
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> - Gen->addLineTable();
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> -
> - EXPECT_EQ(Parser.getOffset(), 4u);
> - EXPECT_TRUE(Parser.done());
> - EXPECT_FALSE(Recoverable);
> -
> - checkError("parsing line table prologue at offset 0x00000000
> unsupported "
> - "reserved unit length found of value 0xfffffff0",
> - std::move(Unrecoverable));
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable();
> - LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> - Gen->addLineTable();
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.skip(RecordUnrecoverable);
> -
> - EXPECT_EQ(Parser.getOffset(), 4u);
> - EXPECT_TRUE(Parser.done());
> -
> - checkError("parsing line table prologue at offset 0x00000000
> unsupported "
> - "reserved unit length found of value 0xfffffff0",
> - std::move(Unrecoverable));
> -}
> -
> -TEST_F(DebugLineBasicFixture,
> ParserReportsFirstErrorInEachTableWhenParsing) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
> - LineTable <2 = Gen->addLineTable(DWARF32);
> - LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> - ASSERT_FALSE(Parser.done());
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> -
> - EXPECT_TRUE(Parser.done());
> - EXPECT_FALSE(Recoverable);
> -
> - checkError({"parsing line table prologue at offset 0x00000000 found "
> - "unsupported version 0x00",
> - "parsing line table prologue at offset 0x00000006 found "
> - "unsupported version 0x01"},
> - std::move(Unrecoverable));
> -}
> -
> -TEST_F(DebugLineBasicFixture,
> ParserReportsNonPrologueProblemsWhenParsing) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
> - LineTable <2 = Gen->addLineTable(DWARF32);
> - LT2.addExtendedOpcode(9, DW_LNE_set_address,
> - {{0x1234567890abcdef, LineTable::Quad}});
> - LT2.addStandardOpcode(DW_LNS_copy, {});
> - LT2.addByte(0xbb);
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> - EXPECT_FALSE(Recoverable);
> - ASSERT_FALSE(Parser.done());
> - checkError(
> - "unexpected line op length at offset 0x00000030 expected 0x42 found
> 0x01",
> - std::move(Unrecoverable));
> -
> - // Reset the error state so that it does not confuse the next set of
> checks.
> - Unrecoverable = Error::success();
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> -
> - EXPECT_TRUE(Parser.done());
> - checkError("last sequence in debug line table is not terminated!",
> - std::move(Recoverable));
> - EXPECT_FALSE(Unrecoverable);
> -}
> -
> -TEST_F(DebugLineBasicFixture,
> - ParserReportsPrologueErrorsInEachTableWhenSkipping) {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
> - LineTable <2 = Gen->addLineTable(DWARF32);
> - LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.skip(RecordUnrecoverable);
> - ASSERT_FALSE(Parser.done());
> - Parser.skip(RecordUnrecoverable);
> -
> - EXPECT_TRUE(Parser.done());
> -
> - checkError({"parsing line table prologue at offset 0x00000000 found "
> - "unsupported version 0x00",
> - "parsing line table prologue at offset 0x00000006 found "
> - "unsupported version 0x01"},
> - std::move(Unrecoverable));
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping)
> {
> - if (!setupGenerator())
> - return;
> -
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - Parser.skip(RecordUnrecoverable);
> -
> - EXPECT_TRUE(Parser.done());
> - EXPECT_FALSE(Unrecoverable);
> -}
> -
> -TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) {
> - if (!setupGenerator())
> - return;
> -
> - using ValLen = dwarfgen::LineTable::ValueAndLength;
> - LineTable < = Gen->addLineTable(DWARF32);
> - LT.addStandardOpcode(DW_LNS_copy, {});
> - LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}});
> - LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22,
> LineTable::SLEB}});
> - LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}});
> - LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}});
> - LT.addStandardOpcode(DW_LNS_negate_stmt, {});
> - LT.addStandardOpcode(DW_LNS_set_basic_block, {});
> - LT.addStandardOpcode(DW_LNS_const_add_pc, {});
> - LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55,
> LineTable::Half}});
> - LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
> - LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {});
> - LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}});
> - LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> - generate();
> -
> - DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> - std::string Output;
> - raw_string_ostream OS(Output);
> - Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS);
> - OS.flush();
> -
> - EXPECT_FALSE(Recoverable);
> - EXPECT_FALSE(Unrecoverable);
> - auto InOutput = [&Output](char const *Str) {
> - return Output.find(Str) != std::string::npos;
> - };
> - EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output;
> - EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) <<
> Output;
> - // FIXME: The value printed after DW_LNS_advance_line is currently the
> result
> - // of the advance, but it should be the value being advanced by. See
> - // https://bugs.llvm.org/show_bug.cgi?id=44261 for details.
> - EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) <<
> Output;
> - EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) <<
> Output;
> - EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) <<
> Output;
> - EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output;
> - EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) <<
> Output;
> - EXPECT_TRUE(
> - InOutput("0x00000039: 08 DW_LNS_const_add_pc
> (0x0000000000000011)\n"))
> - << Output;
> - EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc
> (0x0037)\n"))
> - << Output;
> - EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) <<
> Output;
> - EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) <<
> Output;
> - EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) <<
> Output;
> -}
> -
> -} // end anonymous namespace
> +//===- DWARFDebugLineTest.cpp -------------------------------------------
> --===//
> +//
> +// Part of the LLVM Project, under the Apache License v2.0 with LLVM
> Exceptions.
> +// See https://llvm.org/LICENSE.txt for license information.
> +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
> +//
> +//===--------------------------------------------------------------------
> --===//
> +
> +#include "DwarfGenerator.h"
> +#include "DwarfUtils.h"
> +#include "llvm/DebugInfo/DWARF/DWARFContext.h"
> +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
> +#include "llvm/Object/ObjectFile.h"
> +#include "llvm/Testing/Support/Error.h"
> +#include "gtest/gtest.h"
> +
> +using namespace llvm;
> +using namespace dwarf;
> +using namespace dwarfgen;
> +using namespace object;
> +using namespace utils;
> +using namespace testing;
> +
> +namespace {
> +struct CommonFixture {
> + CommonFixture()
> + : LineData("", true, 0), Recoverable(Error::success()),
> + RecordRecoverable(std::bind(&CommonFixture::recordRecoverable,
> this,
> + std::placeholders::_1)),
> + Unrecoverable(Error::success()),
> +
> RecordUnrecoverable(std::bind(&CommonFixture::recordUnrecoverable, this,
> + std::placeholders::_1)){};
> +
> + ~CommonFixture() {
> + EXPECT_FALSE(Recoverable);
> + EXPECT_FALSE(Unrecoverable);
> + }
> +
> + bool setupGenerator(uint16_t Version = 4) {
> + Triple T = getDefaultTargetTripleForAddrSize(8);
> + if (!isConfigurationSupported(T))
> + return false;
> + auto ExpectedGenerator = Generator::create(T, Version);
> + if (ExpectedGenerator)
> + Gen.reset(ExpectedGenerator->release());
> + return true;
> + }
> +
> + void generate() {
> + Context = createContext();
> + assert(Context != nullptr && "test state is not valid");
> + const DWARFObject &Obj = Context->getDWARFObj();
> + LineData = DWARFDataExtractor(
> + Obj, Obj.getLineSection(),
> + getDefaultTargetTripleForAddrSize(8).isLittleEndian(), 8);
> + }
> +
> + std::unique_ptr<DWARFContext> createContext() {
> + if (!Gen)
> + return nullptr;
> + StringRef FileBytes = Gen->generate();
> + MemoryBufferRef FileBuffer(FileBytes, "dwarf");
> + auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
> + if (Obj)
> + return DWARFContext::create(**Obj);
> + return nullptr;
> + }
> +
> + DWARFDebugLine::SectionParser setupParser() {
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55,
> LineTable::Quad}});
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addByte(0xaa);
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> +
> + LineTable <2 = Gen->addLineTable(DWARF64);
> + LT2.addExtendedOpcode(9, DW_LNE_set_address,
> + {{0x11223344, LineTable::Quad}});
> + LT2.addStandardOpcode(DW_LNS_copy, {});
> + LT2.addByte(0xbb);
> + LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> +
> + generate();
> +
> + return DWARFDebugLine::SectionParser(LineData, *Context, CUs, TUs);
> + }
> +
> + void recordRecoverable(Error Err) {
> + Recoverable = joinErrors(std::move(Recoverable), std::move(Err));
> + }
> + void recordUnrecoverable(Error Err) {
> + Unrecoverable = joinErrors(std::move(Unrecoverable), std::move(Err));
> + }
> +
> + void checkError(ArrayRef<StringRef> ExpectedMsgs, Error Err) {
> + ASSERT_TRUE(Err.operator bool());
> + size_t WhichMsg = 0;
> + Error Remaining =
> + handleErrors(std::move(Err), [&](const ErrorInfoBase &Actual) {
> + ASSERT_LT(WhichMsg, ExpectedMsgs.size());
> + // Use .str(), because googletest doesn't visualise a StringRef
> + // properly.
> + EXPECT_EQ(Actual.message(), ExpectedMsgs[WhichMsg++].str());
> + });
> + EXPECT_EQ(WhichMsg, ExpectedMsgs.size());
> + EXPECT_FALSE(Remaining);
> + }
> +
> + void checkError(StringRef ExpectedMsg, Error Err) {
> + checkError(ArrayRef<StringRef>{ExpectedMsg}, std::move(Err));
> + }
> +
> + void checkGetOrParseLineTableEmitsFatalError(StringRef ExpectedMsg,
> + uint64_t Offset = 0) {
> + auto ExpectedLineTable = Line.getOrParseLineTable(
> + LineData, Offset, *Context, nullptr, RecordRecoverable);
> + EXPECT_FALSE(ExpectedLineTable);
> + EXPECT_FALSE(Recoverable);
> +
> + checkError(ExpectedMsg, ExpectedLineTable.takeError());
> + }
> +
> + void checkGetOrParseLineTableEmitsFatalError(ArrayRef<StringRef>
> ExpectedMsgs,
> + uint64_t Offset = 0) {
> + auto ExpectedLineTable = Line.getOrParseLineTable(
> + LineData, Offset, *Context, nullptr, RecordRecoverable);
> + EXPECT_FALSE(ExpectedLineTable);
> + EXPECT_FALSE(Recoverable);
> +
> + checkError(ExpectedMsgs, ExpectedLineTable.takeError());
> + }
> +
> + std::unique_ptr<Generator> Gen;
> + std::unique_ptr<DWARFContext> Context;
> + DWARFDataExtractor LineData;
> + DWARFDebugLine Line;
> + Error Recoverable;
> + std::function<void(Error)> RecordRecoverable;
> + Error Unrecoverable;
> + std::function<void(Error)> RecordUnrecoverable;
> +
> + SmallVector<std::unique_ptr<DWARFUnit>, 2> CUs;
> + SmallVector<std::unique_ptr<DWARFUnit>, 2> TUs;
> +};
> +
> +// Fixtures must derive from "Test", but parameterised fixtures from
> +// "TestWithParam". It does not seem possible to inherit from both, so we
> share
> +// the common state in a separate class, inherited by the two fixture
> classes.
> +struct DebugLineBasicFixture : public Test, public CommonFixture {};
> +
> +struct DebugLineParameterisedFixture
> + : public TestWithParam<std::pair<uint16_t, DwarfFormat>>,
> + public CommonFixture {
> + void SetUp() { std::tie(Version, Format) = GetParam(); }
> +
> + uint16_t Version;
> + DwarfFormat Format;
> +};
> +
> +void checkDefaultPrologue(uint16_t Version, DwarfFormat Format,
> + DWARFDebugLine::Prologue Prologue,
> + uint64_t BodyLength) {
> + // Check version specific fields and values.
> + uint64_t UnitLength;
> + uint64_t PrologueLength;
> + switch (Version) {
> + case 4:
> + PrologueLength = 36;
> + UnitLength = PrologueLength + 2;
> + EXPECT_EQ(Prologue.MaxOpsPerInst, 1u);
> + break;
> + case 2:
> + case 3:
> + PrologueLength = 35;
> + UnitLength = PrologueLength + 2;
> + break;
> + case 5:
> + PrologueLength = 39;
> + UnitLength = PrologueLength + 4;
> + EXPECT_EQ(Prologue.getAddressSize(), 8u);
> + EXPECT_EQ(Prologue.SegSelectorSize, 0u);
> + break;
> + default:
> + llvm_unreachable("unsupported DWARF version");
> + }
> + UnitLength += BodyLength + (Format == DWARF32 ? 4 : 8);
> +
> + EXPECT_EQ(Prologue.TotalLength, UnitLength);
> + EXPECT_EQ(Prologue.PrologueLength, PrologueLength);
> + EXPECT_EQ(Prologue.MinInstLength, 1u);
> + EXPECT_EQ(Prologue.DefaultIsStmt, 1u);
> + EXPECT_EQ(Prologue.LineBase, -5);
> + EXPECT_EQ(Prologue.LineRange, 14u);
> + EXPECT_EQ(Prologue.OpcodeBase, 13u);
> + std::vector<uint8_t> ExpectedLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0,
> 0, 1};
> + EXPECT_EQ(Prologue.StandardOpcodeLengths, ExpectedLengths);
> + ASSERT_EQ(Prologue.IncludeDirectories.size(), 1u);
> + ASSERT_EQ(Prologue.IncludeDirectories[0].getForm(), DW_FORM_string);
> + EXPECT_STREQ(*Prologue.IncludeDirectories[0].getAsCString(), "a dir");
> + ASSERT_EQ(Prologue.FileNames.size(), 1u);
> + ASSERT_EQ(Prologue.FileNames[0].Name.getForm(), DW_FORM_string);
> + EXPECT_STREQ(*Prologue.FileNames[0].Name.getAsCString(), "a file");
> +}
> +
> +TEST_F(DebugLineBasicFixture, GetOrParseLineTableAtInvalidOffset) {
> + if (!setupGenerator())
> + return;
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "offset 0x00000000 is not a valid debug line section offset", 0);
> + // Repeat to show that an error is reported each time.
> + checkGetOrParseLineTableEmitsFatalError(
> + "offset 0x00000000 is not a valid debug line section offset", 0);
> + // Show that an error is reported for later offsets too.
> + checkGetOrParseLineTableEmitsFatalError(
> + "offset 0x00000001 is not a valid debug line section offset", 1);
> +}
> +
> +TEST_F(DebugLineBasicFixture,
> GetOrParseLineTableAtInvalidOffsetAfterData) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue({{0, LineTable::Byte}});
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "offset 0x00000001 is not a valid debug line section offset", 1);
> +}
> +
> +TEST_P(DebugLineParameterisedFixture, GetOrParseLineTableValidTable) {
> + if (!setupGenerator(Version))
> + return;
> +
> + SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> + (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> +
> + LineTable < = Gen->addLineTable(Format);
> + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0xadd4e55,
> LineTable::Quad}});
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addByte(0xaa);
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> +
> + LineTable <2 = Gen->addLineTable(Format);
> + LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x11223344,
> LineTable::Quad}});
> + LT2.addStandardOpcode(DW_LNS_copy, {});
> + LT2.addByte(0xbb);
> + LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> + LT2.addExtendedOpcode(9, DW_LNE_set_address, {{0x55667788,
> LineTable::Quad}});
> + LT2.addStandardOpcode(DW_LNS_copy, {});
> + LT2.addByte(0xcc);
> + LT2.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> +
> + generate();
> +
> + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0,
> *Context,
> + nullptr,
> RecordRecoverable);
> + ASSERT_TRUE(ExpectedLineTable.operator bool());
> + EXPECT_FALSE(Recoverable);
> + const DWARFDebugLine::LineTable *Expected = *ExpectedLineTable;
> + checkDefaultPrologue(Version, Format, Expected->Prologue, 16);
> + EXPECT_EQ(Expected->Sequences.size(), 1u);
> +
> + uint64_t SecondOffset =
> + Expected->Prologue.sizeofTotalLength() + Expected-
> >Prologue.TotalLength;
> + Recoverable = Error::success();
> + auto ExpectedLineTable2 = Line.getOrParseLineTable(
> + LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
> + ASSERT_TRUE(ExpectedLineTable2.operator bool());
> + EXPECT_FALSE(Recoverable);
> + const DWARFDebugLine::LineTable *Expected2 = *ExpectedLineTable2;
> + checkDefaultPrologue(Version, Format, Expected2->Prologue, 32);
> + EXPECT_EQ(Expected2->Sequences.size(), 2u);
> +
> + EXPECT_NE(Expected, Expected2);
> +
> + // Check that if the same offset is requested, the exact same pointer
> is
> + // returned.
> + Recoverable = Error::success();
> + auto ExpectedLineTable3 = Line.getOrParseLineTable(
> + LineData, 0, *Context, nullptr, RecordRecoverable);
> + ASSERT_TRUE(ExpectedLineTable3.operator bool());
> + EXPECT_FALSE(Recoverable);
> + EXPECT_EQ(Expected, *ExpectedLineTable3);
> +
> + Recoverable = Error::success();
> + auto ExpectedLineTable4 = Line.getOrParseLineTable(
> + LineData, SecondOffset, *Context, nullptr, RecordRecoverable);
> + ASSERT_TRUE(ExpectedLineTable4.operator bool());
> + EXPECT_FALSE(Recoverable);
> + EXPECT_EQ(Expected2, *ExpectedLineTable4);
> +
> + // TODO: Add tests that show that the body of the programs have been
> read
> + // correctly.
> +}
> +
> +TEST_F(DebugLineBasicFixture, ErrorForReservedLength) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "parsing line table prologue at offset 0x00000000 unsupported
> reserved "
> + "unit length found of value 0xfffffff0");
> +}
> +
> +TEST_F(DebugLineBasicFixture, ErrorForLowVersion) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue(
> + {{LineTable::Half, LineTable::Long}, {1, LineTable::Half}});
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "parsing line table prologue at offset "
> + "0x00000000 found unsupported version "
> + "0x01");
> +}
> +
> +TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
> + if (!setupGenerator(5))
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue({
> + {19, LineTable::Long}, // unit length
> + {5, LineTable::Half}, // version
> + {8, LineTable::Byte}, // addr size
> + {0, LineTable::Byte}, // segment selector size
> + {11, LineTable::Long}, // prologue length
> + {1, LineTable::Byte}, // min instruction length
> + {1, LineTable::Byte}, // max ops per instruction
> + {1, LineTable::Byte}, // default is_stmt
> + {0, LineTable::Byte}, // line base
> + {14, LineTable::Byte}, // line range
> + {2, LineTable::Byte}, // opcode base (small to reduce the amount
> of
> + // setup required).
> + {0, LineTable::Byte}, // standard opcode lengths
> + {0, LineTable::Byte}, // directory entry format count (should not
> be
> + // zero).
> + {0, LineTable::ULEB}, // directories count
> + {0, LineTable::Byte}, // file name entry format count
> + {0, LineTable::ULEB} // file name entry count
> + });
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + {"parsing line table prologue at 0x00000000 found an invalid
> directory "
> + "or file table description at 0x00000014",
> + "failed to parse entry content descriptions because no path was
> found"});
> +}
> +
> +TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
> + if (!setupGenerator(Version))
> + return;
> +
> + SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> + (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> +
> + LineTable < = Gen->addLineTable(Format);
> + DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> + ++Prologue.PrologueLength;
> + LT.setPrologue(Prologue);
> +
> + generate();
> +
> + uint64_t ExpectedEnd =
> + Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
> + checkGetOrParseLineTableEmitsFatalError(
> + (Twine("parsing line table prologue at 0x00000000 should have ended
> at "
> + "0x000000") +
> + Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
> + Twine::utohexstr(ExpectedEnd - 1))
> + .str());
> +}
> +
> +TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
> + if (!setupGenerator(Version))
> + return;
> +
> + SCOPED_TRACE("Checking Version " + std::to_string(Version) + ", Format
> " +
> + (Format == DWARF64 ? "DWARF64" : "DWARF32"));
> +
> + LineTable < = Gen->addLineTable(Format);
> + DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> + // FIXME: Ideally, we'd test for 1 less than expected, but the code
> does not
> + // currently fail if missing only the terminator of a v2-4 file table.
> + if (Version < 5)
> + Prologue.PrologueLength -= 2;
> + else
> + Prologue.PrologueLength -= 1;
> + LT.setPrologue(Prologue);
> +
> + generate();
> +
> + uint64_t ExpectedEnd =
> + Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
> + if (Version < 5)
> + --ExpectedEnd;
> + checkGetOrParseLineTableEmitsFatalError(
> + (Twine("parsing line table prologue at 0x00000000 should have ended
> at "
> + "0x000000") +
> + Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +
> + Twine::utohexstr(ExpectedEnd + 1))
> + .str());
> +}
> +
> +INSTANTIATE_TEST_CASE_P(
> + LineTableTestParams, DebugLineParameterisedFixture,
> + Values(std::make_pair(
> + 2, DWARF32), // Test lower-bound of v2-3 fields and
> DWARF32.
> + std::make_pair(3, DWARF32), // Test upper-bound of v2-3
> fields.
> + std::make_pair(4, DWARF64), // Test v4 fields and DWARF64.
> + std::make_pair(5, DWARF32), std::make_pair(5, DWARF64)), );
> +
> +TEST_F(DebugLineBasicFixture, ErrorForInvalidExtendedOpcodeLength) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + // The Length should be 1 for an end sequence opcode.
> + LT.addExtendedOpcode(2, DW_LNE_end_sequence, {});
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "unexpected line op length at offset "
> + "0x00000030 expected 0x02 found 0x01");
> +}
> +
> +TEST_F(DebugLineBasicFixture, ErrorForUnitLengthTooLarge) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable &Padding = Gen->addLineTable();
> + // Add some padding to show that a non-zero offset is handled
> correctly.
> + Padding.setCustomPrologue({{0, LineTable::Byte}});
> + LineTable < = Gen->addLineTable();
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addStandardOpcode(DW_LNS_const_add_pc, {});
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> + DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
> + // Set the total length to 1 higher than the actual length. The program
> body
> + // has size 5.
> + Prologue.TotalLength += 6;
> + LT.setPrologue(Prologue);
> +
> + generate();
> +
> + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 1,
> *Context,
> + nullptr,
> RecordRecoverable);
> + checkError("line table program with offset 0x00000001 has length
> 0x00000034 "
> + "but only 0x00000033 bytes are available",
> + std::move(Recoverable));
> + ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
> + EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 2u);
> + EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
> +}
> +
> +TEST_F(DebugLineBasicFixture, ErrorForMismatchedAddressSize) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + // The line data extractor expects size 8 (Quad) addresses.
> + LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x11223344,
> LineTable::Long}});
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addByte(0xaa);
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> +
> + generate();
> +
> + checkGetOrParseLineTableEmitsFatalError(
> + "mismatching address size at offset 0x00000030 expected 0x08 found
> 0x04");
> +}
> +
> +TEST_F(DebugLineBasicFixture, CallbackUsedForUnterminatedSequence) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.addExtendedOpcode(9, DW_LNE_set_address,
> + {{0x1122334455667788, LineTable::Quad}});
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addByte(0xaa);
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> + LT.addExtendedOpcode(9, DW_LNE_set_address,
> + {{0x99aabbccddeeff00, LineTable::Quad}});
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addByte(0xbb);
> + LT.addByte(0xcc);
> +
> + generate();
> +
> + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0,
> *Context,
> + nullptr,
> RecordRecoverable);
> + checkError("last sequence in debug line table at offset 0x00000000 is
> not "
> + "terminated",
> + std::move(Recoverable));
> + ASSERT_TRUE(ExpectedLineTable.operator bool());
> + EXPECT_EQ((*ExpectedLineTable)->Rows.size(), 6u);
> + // The unterminated sequence is not added to the sequence list.
> + EXPECT_EQ((*ExpectedLineTable)->Sequences.size(), 1u);
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) {
> + if (!setupGenerator())
> + return;
> +
> + DWARFDebugLine::SectionParser Parser = setupParser();
> +
> + EXPECT_EQ(Parser.getOffset(), 0u);
> + ASSERT_FALSE(Parser.done());
> +
> + DWARFDebugLine::LineTable Parsed =
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> + checkDefaultPrologue(4, DWARF32, Parsed.Prologue, 16);
> + EXPECT_EQ(Parsed.Sequences.size(), 1u);
> + EXPECT_EQ(Parser.getOffset(), 62u);
> + ASSERT_FALSE(Parser.done());
> +
> + DWARFDebugLine::LineTable Parsed2 =
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> + checkDefaultPrologue(4, DWARF64, Parsed2.Prologue, 16);
> + EXPECT_EQ(Parsed2.Sequences.size(), 1u);
> + EXPECT_EQ(Parser.getOffset(), 136u);
> + EXPECT_TRUE(Parser.done());
> +
> + EXPECT_FALSE(Recoverable);
> + EXPECT_FALSE(Unrecoverable);
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {
> + if (!setupGenerator())
> + return;
> +
> + DWARFDebugLine::SectionParser Parser = setupParser();
> +
> + EXPECT_EQ(Parser.getOffset(), 0u);
> + ASSERT_FALSE(Parser.done());
> +
> + Parser.skip(RecordUnrecoverable);
> + EXPECT_EQ(Parser.getOffset(), 62u);
> + ASSERT_FALSE(Parser.done());
> +
> + Parser.skip(RecordUnrecoverable);
> + EXPECT_EQ(Parser.getOffset(), 136u);
> + EXPECT_TRUE(Parser.done());
> +
> + EXPECT_FALSE(Unrecoverable);
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserAlwaysDoneForEmptySection) {
> + if (!setupGenerator())
> + return;
> +
> + generate();
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> +
> + EXPECT_TRUE(Parser.done());
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> + Gen->addLineTable();
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> +
> + EXPECT_EQ(Parser.getOffset(), 4u);
> + EXPECT_TRUE(Parser.done());
> + EXPECT_FALSE(Recoverable);
> +
> + checkError("parsing line table prologue at offset 0x00000000
> unsupported "
> + "reserved unit length found of value 0xfffffff0",
> + std::move(Unrecoverable));
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable();
> + LT.setCustomPrologue({{0xfffffff0, LineTable::Long}});
> + Gen->addLineTable();
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.skip(RecordUnrecoverable);
> +
> + EXPECT_EQ(Parser.getOffset(), 4u);
> + EXPECT_TRUE(Parser.done());
> +
> + checkError("parsing line table prologue at offset 0x00000000
> unsupported "
> + "reserved unit length found of value 0xfffffff0",
> + std::move(Unrecoverable));
> +}
> +
> +TEST_F(DebugLineBasicFixture,
> ParserReportsFirstErrorInEachTableWhenParsing) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
> + LineTable <2 = Gen->addLineTable(DWARF32);
> + LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> + ASSERT_FALSE(Parser.done());
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> +
> + EXPECT_TRUE(Parser.done());
> + EXPECT_FALSE(Recoverable);
> +
> + checkError({"parsing line table prologue at offset 0x00000000 found "
> + "unsupported version 0x00",
> + "parsing line table prologue at offset 0x00000006 found "
> + "unsupported version 0x01"},
> + std::move(Unrecoverable));
> +}
> +
> +TEST_F(DebugLineBasicFixture,
> ParserReportsNonPrologueProblemsWhenParsing) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.addExtendedOpcode(0x42, DW_LNE_end_sequence, {});
> + LineTable <2 = Gen->addLineTable(DWARF32);
> + LT2.addExtendedOpcode(9, DW_LNE_set_address,
> + {{0x1234567890abcdef, LineTable::Quad}});
> + LT2.addStandardOpcode(DW_LNS_copy, {});
> + LT2.addByte(0xbb);
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> + EXPECT_FALSE(Recoverable);
> + ASSERT_FALSE(Parser.done());
> + checkError(
> + "unexpected line op length at offset 0x00000030 expected 0x42 found
> 0x01",
> + std::move(Unrecoverable));
> +
> + // Reset the error state so that it does not confuse the next set of
> checks.
> + Unrecoverable = Error::success();
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable);
> +
> + EXPECT_TRUE(Parser.done());
> + checkError("last sequence in debug line table at offset 0x00000031 is
> not "
> + "terminated",
> + std::move(Recoverable));
> + EXPECT_FALSE(Unrecoverable);
> +}
> +
> +TEST_F(DebugLineBasicFixture,
> + ParserReportsPrologueErrorsInEachTableWhenSkipping) {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.setCustomPrologue({{2, LineTable::Long}, {0, LineTable::Half}});
> + LineTable <2 = Gen->addLineTable(DWARF32);
> + LT2.setCustomPrologue({{2, LineTable::Long}, {1, LineTable::Half}});
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.skip(RecordUnrecoverable);
> + ASSERT_FALSE(Parser.done());
> + Parser.skip(RecordUnrecoverable);
> +
> + EXPECT_TRUE(Parser.done());
> +
> + checkError({"parsing line table prologue at offset 0x00000000 found "
> + "unsupported version 0x00",
> + "parsing line table prologue at offset 0x00000006 found "
> + "unsupported version 0x01"},
> + std::move(Unrecoverable));
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping)
> {
> + if (!setupGenerator())
> + return;
> +
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.addExtendedOpcode(42, DW_LNE_end_sequence, {});
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + Parser.skip(RecordUnrecoverable);
> +
> + EXPECT_TRUE(Parser.done());
> + EXPECT_FALSE(Unrecoverable);
> +}
> +
> +TEST_F(DebugLineBasicFixture, ParserPrintsStandardOpcodesWhenRequested) {
> + if (!setupGenerator())
> + return;
> +
> + using ValLen = dwarfgen::LineTable::ValueAndLength;
> + LineTable < = Gen->addLineTable(DWARF32);
> + LT.addStandardOpcode(DW_LNS_copy, {});
> + LT.addStandardOpcode(DW_LNS_advance_pc, {ValLen{11, LineTable::ULEB}});
> + LT.addStandardOpcode(DW_LNS_advance_line, {ValLen{22,
> LineTable::SLEB}});
> + LT.addStandardOpcode(DW_LNS_set_file, {ValLen{33, LineTable::ULEB}});
> + LT.addStandardOpcode(DW_LNS_set_column, {ValLen{44, LineTable::ULEB}});
> + LT.addStandardOpcode(DW_LNS_negate_stmt, {});
> + LT.addStandardOpcode(DW_LNS_set_basic_block, {});
> + LT.addStandardOpcode(DW_LNS_const_add_pc, {});
> + LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {ValLen{55,
> LineTable::Half}});
> + LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
> + LT.addStandardOpcode(DW_LNS_set_epilogue_begin, {});
> + LT.addStandardOpcode(DW_LNS_set_isa, {ValLen{66, LineTable::ULEB}});
> + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
> + generate();
> +
> + DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
> + std::string Output;
> + raw_string_ostream OS(Output);
> + Parser.parseNext(RecordRecoverable, RecordUnrecoverable, &OS);
> + OS.flush();
> +
> + EXPECT_FALSE(Recoverable);
> + EXPECT_FALSE(Unrecoverable);
> + auto InOutput = [&Output](char const *Str) {
> + return Output.find(Str) != std::string::npos;
> + };
> + EXPECT_TRUE(InOutput("0x0000002e: 01 DW_LNS_copy\n")) << Output;
> + EXPECT_TRUE(InOutput("0x0000002f: 02 DW_LNS_advance_pc (11)\n")) <<
> Output;
> + // FIXME: The value printed after DW_LNS_advance_line is currently the
> result
> + // of the advance, but it should be the value being advanced by. See
> + // https://bugs.llvm.org/show_bug.cgi?id=44261 for details.
> + EXPECT_TRUE(InOutput("0x00000031: 03 DW_LNS_advance_line (23)\n")) <<
> Output;
> + EXPECT_TRUE(InOutput("0x00000033: 04 DW_LNS_set_file (33)\n")) <<
> Output;
> + EXPECT_TRUE(InOutput("0x00000035: 05 DW_LNS_set_column (44)\n")) <<
> Output;
> + EXPECT_TRUE(InOutput("0x00000037: 06 DW_LNS_negate_stmt\n")) << Output;
> + EXPECT_TRUE(InOutput("0x00000038: 07 DW_LNS_set_basic_block\n")) <<
> Output;
> + EXPECT_TRUE(
> + InOutput("0x00000039: 08 DW_LNS_const_add_pc
> (0x0000000000000011)\n"))
> + << Output;
> + EXPECT_TRUE(InOutput("0x0000003a: 09 DW_LNS_fixed_advance_pc
> (0x0037)\n"))
> + << Output;
> + EXPECT_TRUE(InOutput("0x0000003d: 0a DW_LNS_set_prologue_end\n")) <<
> Output;
> + EXPECT_TRUE(InOutput("0x0000003e: 0b DW_LNS_set_epilogue_begin\n")) <<
> Output;
> + EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) <<
> Output;
> +}
> +
> +} // end anonymous namespace
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list