diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -340,18 +340,15 @@ const uint64_t PrologueOffset = *OffsetPtr; clear(); - TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr); - if (TotalLength == dwarf::DW_LENGTH_DWARF64) { - FormParams.Format = dwarf::DWARF64; - TotalLength = DebugLineData.getU64(OffsetPtr); - } else if (TotalLength >= dwarf::DW_LENGTH_lo_reserved) { - // Treat this error as unrecoverable - we have no way of knowing where the - // table ends. - return createStringError(errc::invalid_argument, - "parsing line table prologue at offset 0x%8.8" PRIx64 - " unsupported reserved unit length found of value 0x%8.8" PRIx64, - PrologueOffset, TotalLength); - } + Error Err = Error::success(); + std::tie(TotalLength, FormParams.Format) = + DebugLineData.getInitialLength(OffsetPtr, &Err); + if (Err) + return createStringError( + errc::invalid_argument, + "parsing line table prologue at offset 0x%8.8" PRIx64 ": %s", + PrologueOffset, toString(std::move(Err)).c_str()); + FormParams.Version = DebugLineData.getU16(OffsetPtr); if (!versionIsSupported(getVersion())) // Treat this error as unrecoverable - we cannot be sure what any of @@ -360,7 +357,7 @@ return createStringError( errc::not_supported, "parsing line table prologue at offset 0x%8.8" PRIx64 - " found unsupported version %" PRIu16, + ": unsupported version %" PRIu16, PrologueOffset, getVersion()); if (getVersion() >= 5) { @@ -1218,8 +1215,7 @@ } bool DWARFDebugLine::Prologue::totalLengthIsValid() const { - return TotalLength == dwarf::DW_LENGTH_DWARF64 || - TotalLength < dwarf::DW_LENGTH_lo_reserved; + return TotalLength != 0u; } DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_dwarf64_large_table.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_dwarf64_large_table.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_dwarf64_large_table.s @@ -0,0 +1,37 @@ +## Test that we can dump the (intact) prologue of a large table which was +## truncated. Also, make sure we don't get confused by a DWARF64 length which +## matches one of the reserved initial length values. + +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s >%t +# RUN: llvm-dwarfdump %t -debug-line 2>&1 | FileCheck %s + +# CHECK: debug_line[0x00000000] +# CHECK-NEXT: warning: line table program with offset 0x00000000 has length 0xfffffffc but only 0x0000003a bytes are available +# CHECK-NEXT: Line table prologue: +# CHECK-NEXT: total_length: 0xfffffff0 +# CHECK-NEXT: version: 4 +# CHECK-NEXT: prologue_length: 0x00000016 + +# CHECK: 0x000000000badbeef 1 0 1 0 0 is_stmt end_sequence + +.section .debug_line,"",@progbits +.long 0xffffffff # Length of Unit (DWARF-64 format) +.quad 0xfffffff0 +.short 4 # DWARF version number +.quad .Lprologue1_end-.Lprologue1_start # Length of Prologue +.Lprologue1_start: +.byte 1 # Minimum Instruction Length +.byte 1 # Maximum Operations per Instruction +.byte 1 # Default is_stmt +.byte -5 # Line Base +.byte 14 # Line Range +.byte 1 # Opcode Base +.asciz "dir1" # Include table +.byte 0 +.asciz "file1" # File table +.byte 0, 0, 0 +.byte 0 +.Lprologue1_end: +.byte 0, 9, 2 # DW_LNE_set_address +.quad 0x0badbeef +.byte 0, 1, 1 # DW_LNE_end_sequence diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test @@ -46,7 +46,7 @@ ## For fatal issues, the following table(s) should not be dumped: # FATAL: debug_line[0x00000048] # RESERVED-NOT: prologue -# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe +# RESERVED: warning: parsing line table prologue at offset 0x00000048: unsupported reserved unit length of value 0xfffffffe # RESERVED-NOT: prologue # FATAL-NOT: debug_line @@ -197,8 +197,8 @@ # LAST: 0x00000000cafebabe {{.*}} end_sequence # ALL-NOT: warning: -# ALL: warning: parsing line table prologue at offset 0x00000048 found unsupported version 0 -# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 1 +# ALL: warning: parsing line table prologue at offset 0x00000048: unsupported version 0 +# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e: unsupported version 1 # ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073 # ALL-NEXT: warning: failed to parse entry content descriptions because no path was found # ALL-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -210,6 +210,11 @@ generate(); EXPECT_THAT_EXPECTED( + getOrParseLineTableFatalErrors(0), + FailedWithMessage("parsing line table prologue at offset 0x00000000: " + "unexpected end of data at offset 0x0")); + + EXPECT_THAT_EXPECTED( getOrParseLineTableFatalErrors(1), FailedWithMessage( "offset 0x00000001 is not a valid debug line section offset")); @@ -316,8 +321,8 @@ EXPECT_THAT_EXPECTED( getOrParseLineTableFatalErrors(), FailedWithMessage( - "parsing line table prologue at offset 0x00000000 unsupported " - "reserved unit length found of value 0xfffffff0")); + "parsing line table prologue at offset 0x00000000: unsupported " + "reserved unit length of value 0xfffffff0")); } struct DebugLineUnsupportedVersionFixture : public TestWithParam, @@ -339,8 +344,8 @@ EXPECT_THAT_EXPECTED( getOrParseLineTableFatalErrors(), - FailedWithMessage("parsing line table prologue at offset 0x00000000 " - "found unsupported version " + + FailedWithMessage("parsing line table prologue at offset 0x00000000: " + "unsupported version " + std::to_string(Version))); } @@ -807,7 +812,7 @@ EXPECT_TRUE(Parser.done()); } -TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenParsing) { +TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenParsing) { if (!setupGenerator()) return; @@ -819,18 +824,18 @@ DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); Parser.parseNext(RecordRecoverable, RecordUnrecoverable); - EXPECT_EQ(Parser.getOffset(), 4u); + EXPECT_EQ(Parser.getOffset(), 0u); EXPECT_TRUE(Parser.done()); EXPECT_FALSE(Recoverable); EXPECT_THAT_ERROR( std::move(Unrecoverable), FailedWithMessage( - "parsing line table prologue at offset 0x00000000 unsupported " - "reserved unit length found of value 0xfffffff0")); + "parsing line table prologue at offset 0x00000000: unsupported " + "reserved unit length of value 0xfffffff0")); } -TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) { +TEST_F(DebugLineBasicFixture, ParserMarkedAsDoneForBadLengthWhenSkipping) { if (!setupGenerator()) return; @@ -842,15 +847,15 @@ DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs); Parser.skip(RecordRecoverable, RecordUnrecoverable); - EXPECT_EQ(Parser.getOffset(), 4u); + EXPECT_EQ(Parser.getOffset(), 0u); EXPECT_TRUE(Parser.done()); EXPECT_FALSE(Recoverable); EXPECT_THAT_ERROR( std::move(Unrecoverable), FailedWithMessage( - "parsing line table prologue at offset 0x00000000 unsupported " - "reserved unit length found of value 0xfffffff0")); + "parsing line table prologue at offset 0x00000000: unsupported " + "reserved unit length of value 0xfffffff0")); } TEST_F(DebugLineBasicFixture, ParserReportsFirstErrorInEachTableWhenParsing) { @@ -873,10 +878,10 @@ EXPECT_THAT_ERROR( std::move(Unrecoverable), - FailedWithMessage("parsing line table prologue at offset 0x00000000 " - "found unsupported version 0", - "parsing line table prologue at offset 0x00000006 " - "found unsupported version 1")); + FailedWithMessage("parsing line table prologue at offset 0x00000000: " + "unsupported version 0", + "parsing line table prologue at offset 0x00000006: " + "unsupported version 1")); } TEST_F(DebugLineBasicFixture, ParserReportsNonPrologueProblemsWhenParsing) { @@ -932,10 +937,10 @@ EXPECT_THAT_ERROR( std::move(Unrecoverable), - FailedWithMessage("parsing line table prologue at offset 0x00000000 " - "found unsupported version 0", - "parsing line table prologue at offset 0x00000006 " - "found unsupported version 1")); + FailedWithMessage("parsing line table prologue at offset 0x00000000: " + "unsupported version 0", + "parsing line table prologue at offset 0x00000006: " + "unsupported version 1")); } TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) {