diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1036,18 +1036,20 @@ // FIXME: Rather than parsing the whole line table and then copying it over // into LLDB, we should explore using a callback to populate the line table // while we parse to reduce memory usage. - std::unique_ptr sequence = - LineTable::CreateLineSequenceContainer(); std::vector> sequences; - for (auto &row : line_table->Rows) { - LineTable::AppendLineEntryToSequence( - sequence.get(), row.Address.Address, row.Line, row.Column, row.File, - row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, - row.EndSequence); - if (row.EndSequence) { - sequences.push_back(std::move(sequence)); - sequence = LineTable::CreateLineSequenceContainer(); + // The Sequences view contains only valid line sequences. Don't iterate over + // the Rows directly. + for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) { + std::unique_ptr sequence = + LineTable::CreateLineSequenceContainer(); + for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) { + const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx]; + LineTable::AppendLineEntryToSequence( + sequence.get(), row.Address.Address, row.Line, row.Column, row.File, + row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, + row.EndSequence); } + sequences.push_back(std::move(sequence)); } std::unique_ptr line_table_up = diff --git a/lldb/test/Shell/SymbolFile/DWARF/debug_line-tombstone.s b/lldb/test/Shell/SymbolFile/DWARF/debug_line-tombstone.s new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/debug_line-tombstone.s @@ -0,0 +1,106 @@ +# This test that we don't get confused by line tables containing a tombstone +# (-1) value, as produced by recent lld's. Line sequences with the tombstone +# value should be completely ignored. The tombstone sequence is deliberately +# longer so that any attempt at an address binary search will likely land inside +# the sequence. + +# RUN: llvm-mc --filetype=obj --triple=x86_64-pc-linux %s -o %t +# RUN: %lldb -o "image lookup -n main -v" -o "image dump line-table main.cpp" \ +# RUN: -o exit %t | FileCheck %s + +# CHECK-LABEL: image lookup -n main -v +# CHECK: LineEntry: [0x0000000000001000-0x0000000000001001): main.cpp:1 +# CHECK-LABEL: image dump line-table main.cpp +# CHECK-NEXT: Line table for main.cpp +# CHECK-NEXT: 0x0000000000001000: main.cpp:1 +# CHECK-NEXT: 0x0000000000001001: main.cpp:1 +# CHECK-EMPTY: +# CHECK-NEXT: exit + + .text +.space 0x1000 +main: + nop +.Lmain_end: + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 37 # DW_AT_producer + .byte 8 # DW_FORM_string + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xc4 DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + .asciz "main.cpp" # DW_AT_name + .long 0 # DW_AT_stmt_list + .quad main-.text # DW_AT_low_pc + .long .Lmain_end-main # DW_AT_high_pc +.Ldebug_info_end0: + +.section .debug_line,"",@progbits + .long .Llt1_end - .Llt1_start # Length of Unit (DWARF-32 format) +.Llt1_start: + .short 4 # DWARF version number + .long .Lprologue1_end-.Lprologue1_start # Length of Prologue +.Lprologue1_start: + .byte 1 # Minimum Instruction Length + .byte 1 # Maximum Operations per Instruction + .byte 1 # Default is_stmt + .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 + .asciz "main.cpp" # File table + .byte 0, 0, 0 + .byte 0 +.Lprologue1_end: + .byte 0, 9, 2 # DW_LNE_set_address + .quad -1 + .byte 1 # DW_LNS_copy + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 33 # address += 1, line += 1 + .byte 2 # DW_LNS_advance_pc + .uleb128 1 + .byte 0, 1, 1 # DW_LNE_end_sequence + + .byte 0, 9, 2 # DW_LNE_set_address + .quad main-.text + .byte 18 # address += 0, line += 0 + .byte 2 # DW_LNS_advance_pc + .uleb128 1 + .byte 0, 1, 1 # DW_LNE_end_sequence +.Llt1_end: +