[DebugInfo] Print line table extended opcode bytes if parsing fails

Previously, if there was an error whilst parsing the operands of an
extended opcode, the operands would be treated as zero and printed. This
could potentially be slightly confusing. This patch changes the
behaviour to print the raw bytes instead.

Reviewed by: ikudrin

Differential Revision: https://reviews.llvm.org/D81570
This commit is contained in:
James Henderson 2020-06-17 11:29:29 +01:00
parent 7a55d98497
commit 9782c922cb
3 changed files with 61 additions and 28 deletions

View File

@ -784,15 +784,21 @@ Error DWARFDebugLine::LineTable::parse(
// 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 @@ Error DWARFDebugLine::LineTable::parse(
// 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 @@ Error DWARFDebugLine::LineTable::parse(
TableData.setAddressSize(ExtractorAddressSize);
}
if (Verbose)
if (Cursor && Verbose)
*OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address);
}
break;
@ -893,7 +902,7 @@ Error DWARFDebugLine::LineTable::parse(
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 @@ Error DWARFDebugLine::LineTable::parse(
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 @@ Error DWARFDebugLine::LineTable::parse(
"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 << " (<parsing error>";
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)

View File

@ -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 (<parsing error> 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

View File

@ -1461,64 +1461,71 @@ TEST_P(TruncatedExtendedOpcodeFixture, ErrorForTruncatedExtendedOpcode) {
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 (<parsing error> 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 (<parsing error> 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 (<parsing error> 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 (<parsing error> 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 (<parsing error> 78 56 34)",
"unexpected end of data at offset 0x35 while reading [0x32, "
"0x36)")), );
TEST_P(TruncatedStandardOpcodeFixture, ErrorForTruncatedStandardOpcode) {
if (!setupGenerator())