[DebugInfo] Make most debug line prologue errors non-fatal to parsing

Many of the debug line prologue errors are not inherently fatal. In most
cases, we can make reasonable assumptions and carry on. This patch does
exactly that. In the case of length problems, the approach of "the
claimed length is correct" is taken to be consistent with other
instances such as the SectionParser, which ignores the read length.

Reviewed by: dblaikie

Differential Revision: https://reviews.llvm.org/D72158
This commit is contained in:
James Henderson 2020-01-03 15:19:27 +00:00
parent dea11473db
commit b94191fecd
6 changed files with 181 additions and 118 deletions

View File

@ -138,6 +138,7 @@ public:
void clear();
void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
Error parse(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
function_ref<void(Error)> RecoverableErrorCallback,
const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
};
@ -341,9 +342,12 @@ public:
/// Skip the current line table and go to the following line table (if
/// present) immediately.
///
/// \param ErrorCallback - report any prologue parsing issues via this
/// callback.
void skip(function_ref<void(Error)> ErrorCallback);
/// \param RecoverableErrorCallback - report any recoverable prologue
/// parsing issues via this callback.
/// \param UnrecoverableErrorCallback - report any unrecoverable prologue
/// parsing issues via this callback.
void skip(function_ref<void(Error)> RecoverableErrorCallback,
function_ref<void(Error)> UnrecoverableErrorCallback);
/// Indicates if the parser has parsed as much as possible.
///

View File

@ -467,7 +467,7 @@ void DWARFContext::dump(
Optional<uint64_t> DumpOffset) {
while (!Parser.done()) {
if (DumpOffset && Parser.getOffset() != *DumpOffset) {
Parser.skip(dumpWarning);
Parser.skip(dumpWarning, dumpWarning);
continue;
}
OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())

View File

@ -299,10 +299,10 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
return Error::success();
}
Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
uint64_t *OffsetPtr,
const DWARFContext &Ctx,
const DWARFUnit *U) {
Error DWARFDebugLine::Prologue::parse(
const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
function_ref<void(Error)> RecoverableErrorCallback, const DWARFContext &Ctx,
const DWARFUnit *U) {
const uint64_t PrologueOffset = *OffsetPtr;
clear();
@ -311,6 +311,8 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
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,
@ -318,6 +320,9 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
}
FormParams.Version = DebugLineData.getU16(OffsetPtr);
if (getVersion() < 2)
// Treat this error as unrecoverable - we cannot be sure what any of
// the data represents including the length field, so cannot skip it or make
// any reasonable assumptions.
return createStringError(errc::not_supported,
"parsing line table prologue at offset 0x%8.8" PRIx64
" found unsupported version 0x%2.2" PRIx16,
@ -352,25 +357,32 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
if (Error E =
parseV5DirFileTables(DebugLineData, OffsetPtr, FormParams, Ctx, U,
ContentTypes, IncludeDirectories, FileNames)) {
return joinErrors(
RecoverableErrorCallback(joinErrors(
createStringError(
errc::invalid_argument,
"parsing line table prologue at 0x%8.8" PRIx64
" found an invalid directory or file table description at"
" 0x%8.8" PRIx64,
PrologueOffset, *OffsetPtr),
std::move(E));
std::move(E)));
// Skip to the end of the prologue, since the chances are that the parser
// did not read the whole table. This prevents the length check below from
// executing.
if (*OffsetPtr < EndPrologueOffset)
*OffsetPtr = EndPrologueOffset;
}
} else
parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
ContentTypes, IncludeDirectories, FileNames);
if (*OffsetPtr != EndPrologueOffset)
return createStringError(errc::invalid_argument,
"parsing line table prologue at 0x%8.8" PRIx64
" should have ended at 0x%8.8" PRIx64
" but it ended at 0x%8.8" PRIx64,
PrologueOffset, EndPrologueOffset, *OffsetPtr);
if (*OffsetPtr != EndPrologueOffset) {
RecoverableErrorCallback(createStringError(
errc::invalid_argument,
"parsing line table prologue at 0x%8.8" PRIx64
" should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64,
PrologueOffset, EndPrologueOffset, *OffsetPtr));
*OffsetPtr = EndPrologueOffset;
}
return Error::success();
}
@ -516,7 +528,8 @@ Error DWARFDebugLine::LineTable::parse(
clear();
Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr, Ctx, U);
Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr,
RecoverableErrorCallback, Ctx, U);
if (OS) {
// The presence of OS signals verbose dumping.
@ -1158,14 +1171,16 @@ DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
}
void DWARFDebugLine::SectionParser::skip(
function_ref<void(Error)> ErrorCallback) {
function_ref<void(Error)> RecoverableErrorCallback,
function_ref<void(Error)> UnrecoverableErrorCallback) {
assert(DebugLineData.isValidOffset(Offset) &&
"parsing should have terminated");
DWARFUnit *U = prepareToParse(Offset);
uint64_t OldOffset = Offset;
LineTable LT;
if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U))
ErrorCallback(std::move(Err));
if (Error Err = LT.Prologue.parse(DebugLineData, &Offset,
RecoverableErrorCallback, Context, U))
UnrecoverableErrorCallback(std::move(Err));
moveToNextTable(OldOffset, LT.Prologue);
}

View File

@ -64,7 +64,7 @@
.long .Lunit_short_prologue_end - .Lunit_short_prologue_start # unit length
.Lunit_short_prologue_start:
.short 4 # version
.long .Lprologue_short_prologue_end-.Lprologue_short_prologue_start - 2 # Length of Prologue
.long .Lprologue_short_prologue_end-.Lprologue_short_prologue_start # Length of Prologue
.Lprologue_short_prologue_start:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -79,9 +79,13 @@
.asciz "file1" # File table
.byte 0, 0, 0
.asciz "file2"
.byte 1, 2, 3
.byte 0
.byte 1, 2
.Lprologue_short_prologue_end:
.byte 6 # Read as part of the prologue,
# then later again as DW_LNS_negate_stmt.
# FIXME: There should be an additional 0 byte here, but the file name parsing
# code does not recognise a missing null terminator.
# Header end
.byte 0, 9, 2 # DW_LNE_set_address
.quad 0x1122334455667788
.byte 0, 1, 1 # DW_LNE_end_sequence
@ -91,7 +95,7 @@
.long .Lunit_long_prologue_end - .Lunit_long_prologue_start # unit length
.Lunit_long_prologue_start:
.short 4 # version
.long .Lprologue_long_prologue_end-.Lprologue_long_prologue_start + 1 # Length of Prologue
.long .Lprologue_long_prologue_end-.Lprologue_long_prologue_start # Length of Prologue
.Lprologue_long_prologue_start:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -108,6 +112,8 @@
.asciz "file2"
.byte 1, 2, 3
.byte 0
# Skipped byte (treated as part of prologue).
.byte 6
.Lprologue_long_prologue_end:
.byte 0, 9, 2 # DW_LNE_set_address
.quad 0x1111222233334444
@ -180,7 +186,7 @@
.short 5 # DWARF version number
.byte 8 # Address Size
.byte 0 # Segment Selector Size
.long 15 # Length of Prologue (invalid)
.long .Linvalid_description_header_end0 - .Linvalid_description_params0 # Length of Prologue (invalid)
.Linvalid_description_params0:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -188,26 +194,27 @@
.byte -5 # Line Base
.byte 14 # Line Range
.byte 13 # Opcode Base
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # Standard Opcode Lengths
# Directory table format
.byte 1 # One element per directory entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
# Directory table entries
.byte 1 # 1 directory
.asciz "/tmp"
# File table format
.byte 2 # 2 elements per file entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
.byte 2 # DW_LNCT_directory_index
.byte 0x0b # DW_FORM_data1
# File table entries
.byte 1 # 1 file
.asciz "a.c"
.byte 1
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0 # Standard Opcode Lengths
.Linvalid_description_header_end0:
.byte 0, 9, 2 # DW_LNE_set_address
# The bytes from here onwards will also be read as part of the main body.
# --- Prologue interpretation --- | --- Main body interpretation ---
.byte 0, 1 # More standard opcodes | First part of DW_LNE_end_sequence
# Directory table format
.byte 1 # One element per directory entry | End of DW_LNE_end_sequence
.byte 1 # DW_LNCT_path | DW_LNS_copy
.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc
# Directory table entries
.byte 1 # 1 directory | DW_LNS_copy
.asciz "/tmp" # Directory name | four special opcodes + start of DW_LNE_end_sequence
# File table format
.byte 1 # 1 element per file entry | DW_LNE_end_sequence length
.byte 1 # DW_LNCT_path | DW_LNE_end_sequence opcode
.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc
# File table entries
.byte 1 # 1 file | DW_LNS_copy
.asciz "xyz" # File name | three special opcodes + start of DW_LNE_set_address
# Header end
.byte 9, 2 # Remainder of DW_LNE_set_address
.quad 0xbabb1ebabb1e
.byte 0, 1, 1 # DW_LNE_end_sequence
.Linvalid_description_end0:
@ -218,7 +225,7 @@
.short 5 # DWARF version number
.byte 8 # Address Size
.byte 0 # Segment Selector Size
.long .Linvalid_file_header_end0-.Linvalid_file_params0-7 # Length of Prologue (invalid)
.long .Linvalid_file_header_end0 - .Linvalid_file_params0 # Length of Prologue (invalid)
.Linvalid_file_params0:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -239,12 +246,16 @@
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
.byte 2 # DW_LNCT_directory_index
.byte 0x0b # DW_FORM_data1
# File table entries
.byte 1 # 1 file
.asciz "a.c"
.byte 1
.Linvalid_file_header_end0:
# The bytes from here onwards will also be read as part of the main body.
# --- Prologue interpretation --- | --- Main body interpretation ---
.byte 0x0b # DW_FORM_data1 | DW_LNS_set_epilogue_begin
# File table entries
.byte 1 # 1 file | DW_LNS_copy
.asciz "xyz" # File name | 3 special opcodes + start of DW_LNE_end_sequence
.byte 1 # Dir index | DW_LNE_end_sequence length
# Header end
.byte 1 # DW_LNE_end_sequence opcode
.byte 0, 9, 2 # DW_LNE_set_address
.quad 0xab4acadab4a
.byte 0, 1, 1 # DW_LNE_end_sequence
@ -256,7 +267,7 @@
.short 5 # DWARF version number
.byte 8 # Address Size
.byte 0 # Segment Selector Size
.long .Linvalid_dir_header_end0-.Linvalid_dir_params0-16 # Length of Prologue (invalid)
.long .Linvalid_dir_header_end0 - .Linvalid_dir_params0 # Length of Prologue (invalid)
.Linvalid_dir_params0:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -271,19 +282,19 @@
.byte 0x08 # DW_FORM_string
# Directory table entries
.byte 1 # 1 directory
.asciz "/tmp"
# File table format
.byte 2 # 2 elements per file entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
.byte 2 # DW_LNCT_directory_index
.byte 0x0b # DW_FORM_data1
# File table entries
.byte 1 # 1 file
.asciz "a.c"
.byte 1
.Linvalid_dir_header_end0:
.byte 0, 9, 2 # DW_LNE_set_address
# The bytes from here onwards will also be read as part of the main body.
# --- Prologue interpretation --- | --- Main body interpretation ---
.asciz "/tmp" # Directory name | 4 special opcodes + start of DW_LNE_end_sequence
# File table format
.byte 1 # 1 element per file entry | DW_LNE_end_sequence length
.byte 1 # DW_LNCT_path | DW_LNE_end_sequence length opcode
.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc
# File table entries
.byte 1 # 1 file | DW_LNS_copy
.asciz "xyz" # File name | start of DW_LNE_set_address
# Header end
.byte 9, 2 # DW_LNE_set_address length + opcode
.quad 0x4444333322221111
.byte 0, 1, 1 # DW_LNE_end_sequence
.Linvalid_dir_end0:
@ -323,7 +334,7 @@
.asciz "a.c"
.byte 0
# Data to show that the rest of the prologue is skipped.
.byte 6
.byte 1
.Linvalid_md5_header_end0:
.byte 0, 9, 2 # DW_LNE_set_address
.quad 0x1234123412341234
@ -337,7 +348,7 @@
.short 5 # DWARF version number
.byte 8 # Address Size
.byte 0 # Segment Selector Size
.long .Linvalid_md5_header_end1-.Linvalid_md5_params1 - 10 # Length of Prologue
.long .Linvalid_md5_header_end1 - .Linvalid_md5_params1 # Length of Prologue
.Linvalid_md5_params1:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
@ -354,20 +365,20 @@
.byte 1 # 1 directory
.asciz "/tmp"
# File table format
.byte 3 # 2 elements per file entry
.byte 2 # 2 elements per file entry
.byte 1 # DW_LNCT_path
.byte 0x08 # DW_FORM_string
.byte 5 # DW_LNCT_MD5
.byte 0x0b # DW_FORM_data1
.byte 2 # DW_LNCT_directory_index
.byte 0x0b # DW_FORM_data1
# File table entries
.byte 1 # 1 file
.asciz "a.c"
.byte 6 # This byte will be consumed when reading the MD5 value.
.byte 0xb # This byte will not be read as part of the prologue.
.Linvalid_md5_header_end1:
.byte 0, 9, 2 # DW_LNE_set_address
# The bytes from here onwards will also be read as part of the main body.
# --- Prologue interpretation --- | --- Main body interpretation ---
.byte 0x0b # DW_FORM_data1 | DW_LNS_set_epilogue_begin
# File table entries
.byte 1 # 1 file | DW_LNS_copy
.asciz "xyz" # File name | 3 special opcodes + DW_LNE_set_address start
.byte 9 # MD5 hash value | DW_LNE_set_address length
# Header end
.byte 2 # DW_LNE_set_address opcode
.quad 0x4321432143214321
.byte 0, 1, 1 # DW_LNE_end_sequence
.Linvalid_md5_end1:

View File

@ -36,7 +36,7 @@
# RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL
## Don't stop looking for the later unit if non-fatal issues are found.
# RUN: llvm-dwarfdump -debug-line=0x2f8 %t-malformed.o 2> %t-malformed-off-last.err \
# RUN: llvm-dwarfdump -debug-line=0x2ec %t-malformed.o 2> %t-malformed-off-last.err \
# RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]'
# RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL
@ -53,8 +53,7 @@
# FATAL-NEXT: total_length: 0xfffffffe
# FATAL-NOT: debug_line
## For non-fatal prologue issues, the table prologue should be dumped, and any
## subsequent tables should also be.
## For non-fatal issues, the table data should be dumped.
## Case 1: Version 0 table.
# NONFATAL: debug_line[0x00000048]
# NONFATAL-NEXT: Line table prologue
@ -70,7 +69,7 @@
# NONFATAL-NEXT: Line table prologue
# NONFATAL-NOT: include_directories
# NONFATAL-NOT: file_names
# NONFATAL-NOT: Address
# NONFATAL: 0x8877665544332211 {{.*}} end_sequence
## Case 4: Prologue with length shorter than parsed.
# NONFATAL: debug_line[0x00000081]
@ -79,12 +78,11 @@
# NONFATAL-NEXT: name: "file2"
# NONFATAL-NEXT: dir_index: 1
# NONFATAL-NEXT: mod_time: 0x00000002
# NONFATAL-NEXT: length: 0x00000003
# NONFATAL-NOT: file_names
# NONFATAL-NOT: Address
# NONFATAL-NEXT: length: 0x00000006
# NONFATAL: 0x1122334455667788 {{.*}} 0 end_sequence{{$}}
## Case 5: Prologue with length longer than parsed.
# NONFATAL: debug_line[0x000000c9]
# NONFATAL: debug_line[0x000000c8]
# NONFATAL-NEXT: Line table prologue
# NONFATAL: file_names[ 2]:
# NONFATAL-NEXT: name: "file2"
@ -92,7 +90,7 @@
# NONFATAL-NEXT: mod_time: 0x00000002
# NONFATAL-NEXT: length: 0x00000003
# NONFATAL-NOT: file_names
# NONFATAL-NOT: Address
# NONFATAL: 0x1111222233334444 {{.*}} is_stmt end_sequence
## Case 6: Extended opcode with incorrect length versus expected.
# NONFATAL: debug_line[0x00000111]
@ -112,44 +110,47 @@
# NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1
# NONFATAL-NEXT: include_directories[ 0] = "/tmp"
# NONFATAL-NEXT: file_names[ 0]:
# NONFATAL-NEXT: name: "a.c"
# NONFATAL-NEXT: dir_index: 1
# NONFATAL-NOT: Address
# NONFATAL-NEXT: name: "xyz"
# NONFATAL: 0x0000000000000000 1 0 1 0 0 is_stmt end_sequence
# NONFATAL: 0x0000babb1ebabb1e {{.*}} end_sequence
## Case 9: V5 prologue ends during file table.
# NONFATAL: debug_line[0x000001f2]
# NONFATAL: debug_line[0x000001ee]
# NONFATAL-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NEXT: file_names[ 0]:
# NONFATAL-NEXT: name: "a.c"
# NONFATAL-NEXT: name: "xyz"
# NONFATAL-NEXT: dir_index: 1
# NONFATAL-NOT: Address
# NONFATAL: 0x0000000000000000 {{.*}} epilogue_begin
# NONFATAL: 0x00000ab4acadab4a {{.*}} end_sequence
## Case 10: V5 prologue ends during directory table.
# NONFATAL: debug_line[0x00000232]
# NONFATAL: debug_line[0x0000022f]
# NONFATAL-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NEXT: file_names[ 0]:
# NONFATAL-NEXT: name: "a.c"
# NONFATAL-NEXT: dir_index: 1
# NONFATAL-NOT: Address
# NONFATAL-NEXT: name: "xyz"
# NONFATAL: 0x0000000000000002 2 0 1 0 0 is_stmt{{$}}
# NONFATAL: 0x4444333322221111 {{.*}} end_sequence
## Case 11: V5 invalid MD5 hash form when there is still data to be read.
# NONFATAL: debug_line[0x00000272]
# NONFATAL: debug_line[0x0000026b]
# NONFATAL-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NOT: file_names
# NONFATAL-NOT: Address
# NONFATAL-NOT: is_stmt
# NONFATAL: 0x1234123412341234 {{.*}} end_sequence
## Case 12: V5 invalid MD5 hash form when data beyond the prologue length has
## been read before the MD5 problem is identified.
# NONFATAL: debug_line[0x000002b5]
# NONFATAL: debug_line[0x000002ae]
# NONFATAL-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NOT: file_names
# NONFATAL-NOT: Address
# NONFATAL: 0x0000000000000000 {{.*}} epilogue_begin
# NONFATAL: 0x4321432143214321 {{.*}} is_stmt end_sequence
# LAST: debug_line[0x000002f8]
# LAST: debug_line[0x000002ec]
# LAST: 0x00000000cafebabe {{.*}} end_sequence
# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe
@ -159,17 +160,17 @@
# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 0x01
# 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
# FIXME - The latter offset in the next line should be 0xad. The filename parsing code does not notice a missing terminating byte.
# 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
# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102
# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01
# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02
# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated
# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001cd but it ended at 0x000001e4
# ALL-NEXT: warning: parsing line table prologue at 0x000001f2 should have ended at 0x0000021d but it ended at 0x00000224
# ALL-NEXT: warning: parsing line table prologue at 0x00000232 should have ended at 0x00000254 but it ended at 0x00000264
# ALL-NEXT: warning: parsing line table prologue at 0x00000272 found an invalid directory or file table description at 0x000002a6
# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1
# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220
# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e
# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
# ALL-NEXT: warning: parsing line table prologue at 0x000002b5 found an invalid directory or file table description at 0x000002e9
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid
# ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0
# ALL-NOT: warning:

View File

@ -359,10 +359,15 @@ TEST_F(DebugLineBasicFixture, ErrorForInvalidV5IncludeDirTable) {
generate();
checkGetOrParseLineTableEmitsFatalError(
auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
nullptr, RecordRecoverable);
EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
checkError(
{"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"});
"failed to parse entry content descriptions because no path was found"},
std::move(Recoverable));
}
TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
@ -379,14 +384,24 @@ TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {
generate();
auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
nullptr, RecordRecoverable);
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
DWARFDebugLine::LineTable Result(**ExpectedLineTable);
// Undo the earlier modification so that it can be compared against a
// "default" prologue.
--Result.Prologue.PrologueLength;
checkDefaultPrologue(Version, Format, Result.Prologue, 0);
uint64_t ExpectedEnd =
Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();
checkGetOrParseLineTableEmitsFatalError(
checkError(
(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());
.str(),
std::move(Recoverable));
}
TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
@ -408,16 +423,29 @@ TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {
generate();
auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
nullptr, RecordRecoverable);
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
DWARFDebugLine::LineTable Result(**ExpectedLineTable);
// Undo the earlier modification so that it can be compared against a
// "default" prologue.
if (Version < 5)
Result.Prologue.PrologueLength += 2;
else
Result.Prologue.PrologueLength += 1;
checkDefaultPrologue(Version, Format, Result.Prologue, 0);
uint64_t ExpectedEnd =
Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();
if (Version < 5)
--ExpectedEnd;
checkGetOrParseLineTableEmitsFatalError(
checkError(
(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());
.str(),
std::move(Recoverable));
}
INSTANTIATE_TEST_CASE_P(
@ -636,14 +664,15 @@ TEST_F(DebugLineBasicFixture, ParserSkipsCorrectly) {
EXPECT_EQ(Parser.getOffset(), 0u);
ASSERT_FALSE(Parser.done());
Parser.skip(RecordUnrecoverable);
Parser.skip(RecordRecoverable, RecordUnrecoverable);
EXPECT_EQ(Parser.getOffset(), 62u);
ASSERT_FALSE(Parser.done());
Parser.skip(RecordUnrecoverable);
Parser.skip(RecordRecoverable, RecordUnrecoverable);
EXPECT_EQ(Parser.getOffset(), 136u);
EXPECT_TRUE(Parser.done());
EXPECT_FALSE(Recoverable);
EXPECT_FALSE(Unrecoverable);
}
@ -688,10 +717,11 @@ TEST_F(DebugLineBasicFixture, ParserMovesToEndForBadLengthWhenSkipping) {
generate();
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
Parser.skip(RecordUnrecoverable);
Parser.skip(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",
@ -767,11 +797,12 @@ TEST_F(DebugLineBasicFixture,
generate();
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
Parser.skip(RecordUnrecoverable);
Parser.skip(RecordRecoverable, RecordUnrecoverable);
ASSERT_FALSE(Parser.done());
Parser.skip(RecordUnrecoverable);
Parser.skip(RecordRecoverable, RecordUnrecoverable);
EXPECT_TRUE(Parser.done());
EXPECT_FALSE(Recoverable);
checkError({"parsing line table prologue at offset 0x00000000 found "
"unsupported version 0x00",
@ -789,9 +820,10 @@ TEST_F(DebugLineBasicFixture, ParserIgnoresNonPrologueErrorsWhenSkipping) {
generate();
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);
Parser.skip(RecordUnrecoverable);
Parser.skip(RecordRecoverable, RecordUnrecoverable);
EXPECT_TRUE(Parser.done());
EXPECT_FALSE(Recoverable);
EXPECT_FALSE(Unrecoverable);
}