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

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 28 03:30:04 PST 2020


Author: James Henderson
Date: 2020-01-28T11:29:50Z
New Revision: b94191fecdbadc18b342a27df1109754edcb8c4b

URL: https://github.com/llvm/llvm-project/commit/b94191fecdbadc18b342a27df1109754edcb8c4b
DIFF: https://github.com/llvm/llvm-project/commit/b94191fecdbadc18b342a27df1109754edcb8c4b.diff

LOG: [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

Added: 
    

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
    llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
    llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
    llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
    llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index d5b6c72c0461..e55f885f0040 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -138,6 +138,7 @@ class DWARFDebugLine {
     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 @@ class DWARFDebugLine {
     /// 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.
     ///

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 01073aff5667..e363290212dd 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -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())

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index b97753eb9ddb..73753a9847f9 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -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);
 }
 

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
index 501b3ed598fd..913ec625caf4 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
+++ b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
@@ -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
+.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:
@@ -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"
+.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:
@@ -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:

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
index 256d1c07b6c9..45bd52cb6e46 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
@@ -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:

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
index 731afafc1aa1..89c28bc7af41 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
@@ -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);
 }
 


        


More information about the llvm-commits mailing list