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 @@ -784,15 +784,21 @@ // Tolerate zero-length; assume length is correct and soldier on. if (Len == 0) { - if (Verbose) + if (Cursor && Verbose) *OS << "Badly formed extended line op (length 0)\n"; - if (!Cursor) + if (!Cursor) { + if (Verbose) + *OS << "\n"; RecoverableErrorHandler(Cursor.takeError()); + } *OffsetPtr = Cursor.tell(); continue; } uint8_t SubOpcode = TableData.getU8(Cursor); + // OperandOffset will be the same as ExtOffset, if it was not possible to + // read the SubOpcode. + uint64_t OperandOffset = Cursor.tell(); if (Verbose) *OS << LNExtendedString(SubOpcode); switch (SubOpcode) { @@ -805,6 +811,9 @@ // address is that of the byte after the last target machine instruction // of the sequence. State.Row.EndSequence = true; + // No need to test the Cursor is valid here, since it must be to get + // into this code path - if it were invalid, the default case would be + // followed. if (Verbose) { *OS << "\n"; OS->indent(12); @@ -858,7 +867,7 @@ TableData.setAddressSize(ExtractorAddressSize); } - if (Verbose) + if (Cursor && Verbose) *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address); } break; @@ -893,7 +902,7 @@ FileEntry.ModTime = TableData.getULEB128(Cursor); FileEntry.Length = TableData.getULEB128(Cursor); Prologue.FileNames.push_back(FileEntry); - if (Verbose) + if (Cursor && Verbose) *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time=" << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime) << ", length=" << FileEntry.Length << ")"; @@ -902,12 +911,12 @@ case DW_LNE_set_discriminator: State.Row.Discriminator = TableData.getULEB128(Cursor); - if (Verbose) + if (Cursor && Verbose) *OS << " (" << State.Row.Discriminator << ")"; break; default: - if (Verbose) + if (Cursor && Verbose) *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode) << format(" length %" PRIx64, Len); // Len doesn't include the zero opcode byte or the length itself, but @@ -926,6 +935,23 @@ "unexpected line op length at offset 0x%8.8" PRIx64 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64, ExtOffset, Len, Cursor.tell() - ExtOffset)); + if (!Cursor && Verbose) { + DWARFDataExtractor::Cursor ByteCursor(OperandOffset); + uint8_t Byte = TableData.getU8(ByteCursor); + if (ByteCursor) { + *OS << " ("; + do { + *OS << format(" %2.2" PRIx8, Byte); + Byte = TableData.getU8(ByteCursor); + } while (ByteCursor); + *OS << ")"; + } + + // The only parse failure in this case should be if the end was reached. + // In that case, throw away the error, as the main Cursor's error will + // be sufficient. + consumeError(ByteCursor.takeError()); + } *OffsetPtr = End; } else if (Opcode < Prologue.OpcodeBase) { if (Verbose) 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 @@ -244,7 +244,7 @@ # VERBOSE-NEXT: DW_LNE_set_address (0x00000000feedfeed) # VERBOSE-NEXT: DW_LNS_copy # NONFATAL-NEXT: 0x00000000feedfeed -# VERBOSE-NEXT: DW_LNE_set_address (0x0000000000000000) +# VERBOSE-NEXT: DW_LNE_set_address ( 00 f0 01 f0 f0 00 01) # MORE-ERR-NEXT: warning: unexpected end of data at offset 0x3ed while reading [0x3e6, 0x3ee) # MORE-ERR-NEXT: warning: last sequence in debug line table at offset 0x0000039d is not terminated 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 @@ -1461,64 +1461,71 @@ INSTANTIATE_TEST_CASE_P( TruncatedExtendedOpcodeParams, TruncatedExtendedOpcodeFixture, Values( - std::make_tuple(1, 1, DW_LNE_end_sequence, ValueAndLengths(), - "Badly formed extended line op (length 0)", + // Truncated length: + std::make_tuple(1, 1, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", "unable to decode LEB128 at offset 0x00000030: " "malformed uleb128, extends past end"), + // Truncated opcode: std::make_tuple( - 2, 9, DW_LNE_set_address, - ValueAndLengths{{0x12345678, LineTable::Quad}}, - "Unrecognized extended op 0x00 length 9", + 2, 9, /*ArbitraryOpcode=*/0x7f, ValueAndLengths(), "", "unexpected end of data at offset 0x31 while reading [0x31, 0x32)"), + // Truncated operands: std::make_tuple( 3, 9, DW_LNE_set_address, - ValueAndLengths{{0x12345678, LineTable::Quad}}, - "DW_LNE_set_address (0x0000000000000000)", + ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}}, + "DW_LNE_set_address", "unexpected end of data at offset 0x32 while reading [0x32, 0x3a)"), - std::make_tuple(3, 5, DW_LNE_define_file, + std::make_tuple( + 10, 9, DW_LNE_set_address, + ValueAndLengths{{0x1234567890abcdef, LineTable::Quad}}, + "DW_LNE_set_address ( ef cd ab 90 78 56 34)", + "unexpected end of data at offset 0x39 while reading [0x32, 0x3a)"), + std::make_tuple(3, 6, DW_LNE_define_file, ValueAndLengths{{'a', LineTable::Byte}, {'\0', LineTable::Byte}, {1, LineTable::ULEB}, {1, LineTable::ULEB}, {1, LineTable::ULEB}}, - "DW_LNE_define_file (, dir=0, " - "mod_time=(0x0000000000000000), length=0)", + "DW_LNE_define_file", "no null terminated string at offset 0x32"), - std::make_tuple(5, 5, DW_LNE_define_file, + std::make_tuple(5, 6, DW_LNE_define_file, ValueAndLengths{{'a', LineTable::Byte}, {'\0', LineTable::Byte}, {1, LineTable::ULEB}, {1, LineTable::ULEB}, {1, LineTable::ULEB}}, - "DW_LNE_define_file (a, dir=0, " - "mod_time=(0x0000000000000000), length=0)", + "DW_LNE_define_file ( 61 00)", "unable to decode LEB128 at offset 0x00000034: " "malformed uleb128, extends past end"), - std::make_tuple(6, 5, DW_LNE_define_file, + std::make_tuple(6, 6, DW_LNE_define_file, ValueAndLengths{{'a', LineTable::Byte}, {'\0', LineTable::Byte}, {1, LineTable::ULEB}, {1, LineTable::ULEB}, {1, LineTable::ULEB}}, - "DW_LNE_define_file (a, dir=1, " - "mod_time=(0x0000000000000000), length=0)", + "DW_LNE_define_file ( 61 00 01)", "unable to decode LEB128 at offset 0x00000035: " "malformed uleb128, extends past end"), - std::make_tuple(7, 5, DW_LNE_define_file, + std::make_tuple(7, 6, DW_LNE_define_file, ValueAndLengths{{'a', LineTable::Byte}, {'\0', LineTable::Byte}, {1, LineTable::ULEB}, {1, LineTable::ULEB}, {1, LineTable::ULEB}}, - "DW_LNE_define_file (a, dir=1, " - "mod_time=(0x0000000000000001), length=0)", + "DW_LNE_define_file ( 61 00 01 01)", "unable to decode LEB128 at offset 0x00000036: " "malformed uleb128, extends past end"), std::make_tuple(3, 2, DW_LNE_set_discriminator, ValueAndLengths{{1, LineTable::ULEB}}, - "DW_LNE_set_discriminator (0)", + "DW_LNE_set_discriminator", "unable to decode LEB128 at offset 0x00000032: " - "malformed uleb128, extends past end")), ); + "malformed uleb128, extends past end"), + std::make_tuple( + 6, 5, /*Unknown=*/0x7f, + ValueAndLengths{{0x12345678, LineTable::Long}}, + "Unrecognized extended op 0x7f length 5 ( 78 56 34)", + "unexpected end of data at offset 0x35 while reading [0x32, " + "0x36)")), ); TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) { if (!setupGenerator())