jhenderson updated this revision to Diff 240852.
jhenderson added a reviewer: labath.
jhenderson added a comment.
Herald added subscribers: lldb-commits, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLDB.

Fix LLD test + fix LLDB build.

I'm uncertain if the LLDB fix is the right fix to make or not, but it does at 
least stop this change breaking the build.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72158/new/

https://reviews.llvm.org/D72158

Files:
  lld/test/ELF/Inputs/undef-bad-debug.s
  lld/test/ELF/undef.s
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  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

Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
===================================================================
--- llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
+++ llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
@@ -359,10 +359,15 @@
 
   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 @@
 
   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 @@
 
   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 @@
   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 @@
   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 @@
   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 @@
   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);
 }
 
Index: llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
===================================================================
--- llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test
+++ 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:
Index: llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
===================================================================
--- llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s
+++ 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:
Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -299,10 +299,10 @@
   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 @@
     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 @@
   }
   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 @@
     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 @@
 
   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 @@
 }
 
 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);
 }
 
Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -467,7 +467,7 @@
                              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())
Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
===================================================================
--- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -138,6 +138,7 @@
     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 @@
     /// 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.
     ///
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -893,12 +893,15 @@
     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());
Index: lld/test/ELF/undef.s
===================================================================
--- lld/test/ELF/undef.s
+++ lld/test/ELF/undef.s
@@ -22,7 +22,7 @@
 # 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)
@@ -52,17 +52,25 @@
 # 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
Index: lld/test/ELF/Inputs/undef-bad-debug.s
===================================================================
--- lld/test/ELF/Inputs/undef-bad-debug.s
+++ lld/test/ELF/Inputs/undef-bad-debug.s
@@ -5,6 +5,8 @@
     .quad zed6b
 sym3:
     .quad zed7
+sym4:
+    .quad zed8
 
 .section .debug_line,"",@progbits
 .Lunit:
@@ -47,6 +49,12 @@
 .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:
@@ -64,7 +72,7 @@
     .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
@@ -79,7 +87,7 @@
     .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
@@ -117,6 +125,21 @@
     .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
@@ -148,3 +171,5 @@
     .asciz "sym2"
 .Linfo2_string:
     .asciz "sym3"
+.Linfo3_string:
+    .asciz "sym4"
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to