.quad zed6b
sym3:
.quad zed7
+sym4:
+ .quad zed8
.section .debug_line,"",@progbits
.Lunit:
.Lunit2:
.long .Lunit2_end - .Lunit2_start # unit length
.Lunit2_start:
+ .short 1 # version
+.Lunit2_end:
+
+.Lunit3:
+ .long .Lunit3_end - .Lunit3_start # unit length
+.Lunit3_start:
.short 4 # version
.long .Lprologue2_end - .Lprologue2_start # prologue length
.Lprologue2_start:
.byte 0
.Lprologue2_end:
.byte 0, 9, 2 # DW_LNE_set_address
- .quad sym3
+ .quad sym4
.byte 3 # DW_LNS_advance_line
.byte 10
.byte 1 # DW_LNS_copy
.byte 99 # DW_LNS_advance_pc
.byte 119
# Missing end of sequence.
-.Lunit2_end:
+.Lunit3_end:
.section .debug_info,"",@progbits
.long .Lcu_end - .Lcu_start # Length of Unit
.byte 0 # End Of Children Mark
.Lcu2_end:
+ .long .Lcu3_end - .Lcu3_start # Length of Unit
+.Lcu3_start:
+ .short 4 # DWARF version number
+ .long .Lsection_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x79 DW_TAG_compile_unit
+ .long .Lunit3 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x2a:0x15 DW_TAG_variable
+ .long .Linfo3_string # DW_AT_name
+ # DW_AT_external
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 0 # End Of Children Mark
+.Lcu3_end:
+
.section .debug_abbrev,"",@progbits
.Lsection_abbrev:
.byte 1 # Abbreviation Code
.asciz "sym2"
.Linfo2_string:
.asciz "sym3"
+.Linfo3_string:
+ .asciz "sym4"
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x10)
-# CHECK: error: undefined symbol: vtable for Foo
+# CHECK: error: undefined symbol: vtable for Foo
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x15)
# CHECK-NEXT: the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction)
# 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 at offset 0x0000005b is not terminated
+# CHECK-NEXT: warning: parsing line table prologue at offset 0x0000005b found unsupported version 0x01
+# CHECK-NEXT: warning: last sequence in debug line table at offset 0x00000061 is not terminated
# CHECK: error: undefined symbol: zed6a
-# CHECK-NEXT: >>> referenced by {{.*}}tmp4.o:(.text+0x0)
+# CHECK-NEXT: >>> referenced by undef-bad-debug.s:11 (dir{{/|\\}}undef-bad-debug.s:11)
+# CHECK-NEXT: >>> {{.*}}4.o:(.text+0x0)
# CHECK: error: undefined symbol: zed6b
-# CHECK-NEXT: >>> referenced by {{.*}}tmp4.o:(.text+0x8)
+# CHECK-NEXT: >>> referenced by undef-bad-debug.s:21 (dir{{/|\\}}undef-bad-debug.s:21)
+# CHECK-NEXT: >>> {{.*}}4.o:(.text+0x8)
+
+# Show that a problem in a line table that prevents further parsing of that
+# table means that no line information is displayed in the wardning.
+# CHECK: error: undefined symbol: zed7
+# CHECK-NEXT: >>> referenced by {{.*}}4.o:(.text+0x10)
# Show that a problem with one line table's information doesn't affect getting information from
# a different one in the same object.
-# CHECK: error: undefined symbol: zed7
+# CHECK: error: undefined symbol: zed8
# CHECK-NEXT: >>> referenced by undef-bad-debug2.s:11 (dir2{{/|\\}}undef-bad-debug2.s:11)
-# CHECK-NEXT: >>> {{.*}}tmp4.o:(.text+0x10)
+# CHECK-NEXT: >>> {{.*}}tmp4.o:(.text+0x18)
# RUN: not ld.lld %t.o %t2.a -o %t.exe -no-demangle 2>&1 | \
# RUN: FileCheck -check-prefix=NO-DEMANGLE %s
llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM();
llvm::DWARFContext &ctx = m_context.GetAsLLVM();
llvm::DWARFDebugLine::Prologue prologue;
- llvm::Error error = prologue.parse(data, &line_table_offset, ctx);
- if (error) {
+ auto report = [](llvm::Error error) {
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
LLDB_LOG_ERROR(log, std::move(error),
"SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
"the line table prologue");
+ };
+ llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
+ if (error) {
+ report(std::move(error));
} else {
list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(),
prologue, tu.GetPathStyle());
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);
};
/// 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.
///
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())
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();
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,
}
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,
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();
}
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.
}
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);
}
.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
.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
.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
.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
.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
.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
+.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0 # Standard Opcode Lengths
+.Linvalid_description_header_end0:
+# 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
-.byte 1 # DW_LNCT_path
-.byte 0x08 # DW_FORM_string
+.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
-.asciz "/tmp"
+.byte 1 # 1 directory | DW_LNS_copy
+.asciz "/tmp" # Directory name | four special opcodes + start of DW_LNE_end_sequence
# 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
+.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
-.asciz "a.c"
-.byte 1
-.Linvalid_description_header_end0:
-.byte 0, 9, 2 # DW_LNE_set_address
+.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:
.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
.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
.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
.byte 0x08 # DW_FORM_string
# Directory table entries
.byte 1 # 1 directory
-.asciz "/tmp"
+.Linvalid_dir_header_end0:
+# 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 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
+.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
-.asciz "a.c"
-.byte 1
-.Linvalid_dir_header_end0:
-.byte 0, 9, 2 # DW_LNE_set_address
+.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:
.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
.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
.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:
# RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL\r
\r
## Don't stop looking for the later unit if non-fatal issues are found.\r
-# RUN: llvm-dwarfdump -debug-line=0x2f8 %t-malformed.o 2> %t-malformed-off-last.err \\r
+# RUN: llvm-dwarfdump -debug-line=0x2ec %t-malformed.o 2> %t-malformed-off-last.err \\r
# RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]'\r
# RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL\r
\r
# FATAL-NEXT: total_length: 0xfffffffe\r
# FATAL-NOT: debug_line\r
\r
-## For non-fatal prologue issues, the table prologue should be dumped, and any\r
-## subsequent tables should also be.\r
+## For non-fatal issues, the table data should be dumped.\r
## Case 1: Version 0 table.\r
# NONFATAL: debug_line[0x00000048]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL-NOT: include_directories\r
# NONFATAL-NOT: file_names\r
-# NONFATAL-NOT: Address\r
+# NONFATAL: 0x8877665544332211 {{.*}} end_sequence\r
\r
## Case 4: Prologue with length shorter than parsed.\r
# NONFATAL: debug_line[0x00000081]\r
# NONFATAL-NEXT: name: "file2"\r
# NONFATAL-NEXT: dir_index: 1\r
# NONFATAL-NEXT: mod_time: 0x00000002\r
-# NONFATAL-NEXT: length: 0x00000003\r
-# NONFATAL-NOT: file_names\r
-# NONFATAL-NOT: Address\r
+# NONFATAL-NEXT: length: 0x00000006\r
+# NONFATAL: 0x1122334455667788 {{.*}} 0 end_sequence{{$}}\r
\r
## Case 5: Prologue with length longer than parsed.\r
-# NONFATAL: debug_line[0x000000c9]\r
+# NONFATAL: debug_line[0x000000c8]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL: file_names[ 2]:\r
# NONFATAL-NEXT: name: "file2"\r
# NONFATAL-NEXT: mod_time: 0x00000002\r
# NONFATAL-NEXT: length: 0x00000003\r
# NONFATAL-NOT: file_names\r
-# NONFATAL-NOT: Address\r
+# NONFATAL: 0x1111222233334444 {{.*}} is_stmt end_sequence\r
\r
## Case 6: Extended opcode with incorrect length versus expected.\r
# NONFATAL: debug_line[0x00000111]\r
# NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1\r
# NONFATAL-NEXT: include_directories[ 0] = "/tmp"\r
# NONFATAL-NEXT: file_names[ 0]:\r
-# NONFATAL-NEXT: name: "a.c"\r
-# NONFATAL-NEXT: dir_index: 1\r
-# NONFATAL-NOT: Address\r
+# NONFATAL-NEXT: name: "xyz"\r
+# NONFATAL: 0x0000000000000000 1 0 1 0 0 is_stmt end_sequence\r
+# NONFATAL: 0x0000babb1ebabb1e {{.*}} end_sequence\r
\r
## Case 9: V5 prologue ends during file table.\r
-# NONFATAL: debug_line[0x000001f2]\r
+# NONFATAL: debug_line[0x000001ee]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL: include_directories[ 0] = "/tmp"\r
# NONFATAL-NEXT: file_names[ 0]:\r
-# NONFATAL-NEXT: name: "a.c"\r
+# NONFATAL-NEXT: name: "xyz"\r
# NONFATAL-NEXT: dir_index: 1\r
-# NONFATAL-NOT: Address\r
+# NONFATAL: 0x0000000000000000 {{.*}} epilogue_begin\r
+# NONFATAL: 0x00000ab4acadab4a {{.*}} end_sequence\r
\r
## Case 10: V5 prologue ends during directory table.\r
-# NONFATAL: debug_line[0x00000232]\r
+# NONFATAL: debug_line[0x0000022f]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL: include_directories[ 0] = "/tmp"\r
# NONFATAL-NEXT: file_names[ 0]:\r
-# NONFATAL-NEXT: name: "a.c"\r
-# NONFATAL-NEXT: dir_index: 1\r
-# NONFATAL-NOT: Address\r
+# NONFATAL-NEXT: name: "xyz"\r
+# NONFATAL: 0x0000000000000002 2 0 1 0 0 is_stmt{{$}}\r
+# NONFATAL: 0x4444333322221111 {{.*}} end_sequence\r
\r
## Case 11: V5 invalid MD5 hash form when there is still data to be read.\r
-# NONFATAL: debug_line[0x00000272]\r
+# NONFATAL: debug_line[0x0000026b]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL: include_directories[ 0] = "/tmp"\r
# NONFATAL-NOT: file_names\r
-# NONFATAL-NOT: Address\r
+# NONFATAL-NOT: is_stmt\r
+# NONFATAL: 0x1234123412341234 {{.*}} end_sequence\r
\r
## Case 12: V5 invalid MD5 hash form when data beyond the prologue length has\r
## been read before the MD5 problem is identified.\r
-# NONFATAL: debug_line[0x000002b5]\r
+# NONFATAL: debug_line[0x000002ae]\r
# NONFATAL-NEXT: Line table prologue\r
# NONFATAL: include_directories[ 0] = "/tmp"\r
# NONFATAL-NOT: file_names\r
-# NONFATAL-NOT: Address\r
+# NONFATAL: 0x0000000000000000 {{.*}} epilogue_begin\r
+# NONFATAL: 0x4321432143214321 {{.*}} is_stmt end_sequence\r
\r
-# LAST: debug_line[0x000002f8]\r
+# LAST: debug_line[0x000002ec]\r
# LAST: 0x00000000cafebabe {{.*}} end_sequence\r
\r
# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe\r
# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 0x01\r
# ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073\r
# ALL-NEXT: warning: failed to parse entry content descriptions because no path was found\r
-# FIXME - The latter offset in the next line should be 0xad. The filename parsing code does not notice a missing terminating byte.\r
# ALL-NEXT: warning: parsing line table prologue at 0x00000081 should have ended at 0x000000b9 but it ended at 0x000000ba\r
-# ALL-NEXT: warning: parsing line table prologue at 0x000000c9 should have ended at 0x00000104 but it ended at 0x00000103\r
+# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102\r
# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01\r
# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02\r
# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated\r
-# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001cd but it ended at 0x000001e4\r
-# ALL-NEXT: warning: parsing line table prologue at 0x000001f2 should have ended at 0x0000021d but it ended at 0x00000224\r
-# ALL-NEXT: warning: parsing line table prologue at 0x00000232 should have ended at 0x00000254 but it ended at 0x00000264\r
-# ALL-NEXT: warning: parsing line table prologue at 0x00000272 found an invalid directory or file table description at 0x000002a6\r
+# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1\r
+# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220\r
+# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e\r
+# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f\r
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid\r
-# ALL-NEXT: warning: parsing line table prologue at 0x000002b5 found an invalid directory or file table description at 0x000002e9\r
+# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0\r
# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid\r
+# ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0\r
# ALL-NOT: warning:\r
\r
generate();\r
\r
- checkGetOrParseLineTableEmitsFatalError(\r
+ auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,\r
+ nullptr, RecordRecoverable);\r
+ EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded());\r
+\r
+ checkError(\r
{"parsing line table prologue at 0x00000000 found an invalid directory "\r
"or file table description at 0x00000014",\r
- "failed to parse entry content descriptions because no path was found"});\r
+ "failed to parse entry content descriptions because no path was found"},\r
+ std::move(Recoverable));\r
}\r
\r
TEST_P(DebugLineParameterisedFixture, ErrorForTooLargePrologueLength) {\r
\r
generate();\r
\r
+ auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,\r
+ nullptr, RecordRecoverable);\r
+ ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());\r
+ DWARFDebugLine::LineTable Result(**ExpectedLineTable);\r
+ // Undo the earlier modification so that it can be compared against a\r
+ // "default" prologue.\r
+ --Result.Prologue.PrologueLength;\r
+ checkDefaultPrologue(Version, Format, Result.Prologue, 0);\r
+\r
uint64_t ExpectedEnd =\r
Prologue.TotalLength + 1 + Prologue.sizeofTotalLength();\r
- checkGetOrParseLineTableEmitsFatalError(\r
+ checkError(\r
(Twine("parsing line table prologue at 0x00000000 should have ended at "\r
"0x000000") +\r
Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +\r
Twine::utohexstr(ExpectedEnd - 1))\r
- .str());\r
+ .str(),\r
+ std::move(Recoverable));\r
}\r
\r
TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) {\r
\r
generate();\r
\r
+ auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,\r
+ nullptr, RecordRecoverable);\r
+ ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());\r
+ DWARFDebugLine::LineTable Result(**ExpectedLineTable);\r
+ // Undo the earlier modification so that it can be compared against a\r
+ // "default" prologue.\r
+ if (Version < 5)\r
+ Result.Prologue.PrologueLength += 2;\r
+ else\r
+ Result.Prologue.PrologueLength += 1;\r
+ checkDefaultPrologue(Version, Format, Result.Prologue, 0);\r
+\r
uint64_t ExpectedEnd =\r
Prologue.TotalLength - 1 + Prologue.sizeofTotalLength();\r
if (Version < 5)\r
--ExpectedEnd;\r
- checkGetOrParseLineTableEmitsFatalError(\r
+ checkError(\r
(Twine("parsing line table prologue at 0x00000000 should have ended at "\r
"0x000000") +\r
Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" +\r
Twine::utohexstr(ExpectedEnd + 1))\r
- .str());\r
+ .str(),\r
+ std::move(Recoverable));\r
}\r
\r
INSTANTIATE_TEST_CASE_P(\r
EXPECT_EQ(Parser.getOffset(), 0u);\r
ASSERT_FALSE(Parser.done());\r
\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
EXPECT_EQ(Parser.getOffset(), 62u);\r
ASSERT_FALSE(Parser.done());\r
\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
EXPECT_EQ(Parser.getOffset(), 136u);\r
EXPECT_TRUE(Parser.done());\r
\r
+ EXPECT_FALSE(Recoverable);\r
EXPECT_FALSE(Unrecoverable);\r
}\r
\r
generate();\r
\r
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
\r
EXPECT_EQ(Parser.getOffset(), 4u);\r
EXPECT_TRUE(Parser.done());\r
+ EXPECT_FALSE(Recoverable);\r
\r
checkError("parsing line table prologue at offset 0x00000000 unsupported "\r
"reserved unit length found of value 0xfffffff0",\r
generate();\r
\r
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
ASSERT_FALSE(Parser.done());\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
\r
EXPECT_TRUE(Parser.done());\r
+ EXPECT_FALSE(Recoverable);\r
\r
checkError({"parsing line table prologue at offset 0x00000000 found "\r
"unsupported version 0x00",\r
generate();\r
\r
DWARFDebugLine::SectionParser Parser(LineData, *Context, CUs, TUs);\r
- Parser.skip(RecordUnrecoverable);\r
+ Parser.skip(RecordRecoverable, RecordUnrecoverable);\r
\r
EXPECT_TRUE(Parser.done());\r
+ EXPECT_FALSE(Recoverable);\r
EXPECT_FALSE(Unrecoverable);\r
}\r
\r