Skip to content

Commit f3fab39

Browse files
committed
[lldb/DWARF] Don't get confused by line sequences with tombstone values
Summary: With D81784, lld has started debug info resolving relocations to garbage-collected symbols as -1 (instead of relocation addend). For an unaware consumer this generated sequences which seemingly wrap the address space -- their first entry was 0xfffff, but all other entries were low numbers. Lldb stores line sequences concatenated into one large vector, sorted by the first entry, and searched with std::lower_bound. This resulted in the low-value entries being placed at the end of the vector, which utterly confused the lower_bound algorithm, and caused it to not find a match. (Previously, these sequences would be at the start of the vector, and normally would contain addresses that are far smaller than any real address we want to look up, so std::lower_bound was fine.) This patch makes lldb ignore these kinds of sequences completely. It does that by changing the construction algorithm from iterating over the rows (as parsed by llvm), to iterating over the sequences. This is important because the llvm parsed performs validity checks when constructing the sequence array, whereas the row array contains raw data. Reviewers: JDevlieghere, MaskRay Differential Revision: https://reviews.llvm.org/D83957
1 parent e412cc4 commit f3fab39

File tree

2 files changed

+118
-10
lines changed

2 files changed

+118
-10
lines changed

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,18 +1036,20 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
10361036
// FIXME: Rather than parsing the whole line table and then copying it over
10371037
// into LLDB, we should explore using a callback to populate the line table
10381038
// while we parse to reduce memory usage.
1039-
std::unique_ptr<LineSequence> sequence =
1040-
LineTable::CreateLineSequenceContainer();
10411039
std::vector<std::unique_ptr<LineSequence>> sequences;
1042-
for (auto &row : line_table->Rows) {
1043-
LineTable::AppendLineEntryToSequence(
1044-
sequence.get(), row.Address.Address, row.Line, row.Column, row.File,
1045-
row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
1046-
row.EndSequence);
1047-
if (row.EndSequence) {
1048-
sequences.push_back(std::move(sequence));
1049-
sequence = LineTable::CreateLineSequenceContainer();
1040+
// The Sequences view contains only valid line sequences. Don't iterate over
1041+
// the Rows directly.
1042+
for (const llvm::DWARFDebugLine::Sequence &seq : line_table->Sequences) {
1043+
std::unique_ptr<LineSequence> sequence =
1044+
LineTable::CreateLineSequenceContainer();
1045+
for (unsigned idx = seq.FirstRowIndex; idx < seq.LastRowIndex; ++idx) {
1046+
const llvm::DWARFDebugLine::Row &row = line_table->Rows[idx];
1047+
LineTable::AppendLineEntryToSequence(
1048+
sequence.get(), row.Address.Address, row.Line, row.Column, row.File,
1049+
row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin,
1050+
row.EndSequence);
10501051
}
1052+
sequences.push_back(std::move(sequence));
10511053
}
10521054

10531055
std::unique_ptr<LineTable> line_table_up =
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# This test that we don't get confused by line tables containing a tombstone
2+
# (-1) value, as produced by recent lld's. Line sequences with the tombstone
3+
# value should be completely ignored. The tombstone sequence is deliberately
4+
# longer so that any attempt at an address binary search will likely land inside
5+
# the sequence.
6+
7+
# RUN: llvm-mc --filetype=obj --triple=x86_64-pc-linux %s -o %t
8+
# RUN: %lldb -o "image lookup -n main -v" -o "image dump line-table main.cpp" \
9+
# RUN: -o exit %t | FileCheck %s
10+
11+
# CHECK-LABEL: image lookup -n main -v
12+
# CHECK: LineEntry: [0x0000000000001000-0x0000000000001001): main.cpp:1
13+
# CHECK-LABEL: image dump line-table main.cpp
14+
# CHECK-NEXT: Line table for main.cpp
15+
# CHECK-NEXT: 0x0000000000001000: main.cpp:1
16+
# CHECK-NEXT: 0x0000000000001001: main.cpp:1
17+
# CHECK-EMPTY:
18+
# CHECK-NEXT: exit
19+
20+
.text
21+
.space 0x1000
22+
main:
23+
nop
24+
.Lmain_end:
25+
26+
.section .debug_abbrev,"",@progbits
27+
.byte 1 # Abbreviation Code
28+
.byte 17 # DW_TAG_compile_unit
29+
.byte 0 # DW_CHILDREN_no
30+
.byte 37 # DW_AT_producer
31+
.byte 8 # DW_FORM_string
32+
.byte 3 # DW_AT_name
33+
.byte 8 # DW_FORM_string
34+
.byte 16 # DW_AT_stmt_list
35+
.byte 23 # DW_FORM_sec_offset
36+
.byte 17 # DW_AT_low_pc
37+
.byte 1 # DW_FORM_addr
38+
.byte 18 # DW_AT_high_pc
39+
.byte 6 # DW_FORM_data4
40+
.byte 0 # EOM(1)
41+
.byte 0 # EOM(2)
42+
.byte 0 # EOM(3)
43+
44+
.section .debug_info,"",@progbits
45+
.Lcu_begin0:
46+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
47+
.Ldebug_info_start0:
48+
.short 4 # DWARF version number
49+
.long 0 # Offset Into Abbrev. Section
50+
.byte 8 # Address Size (in bytes)
51+
.byte 1 # Abbrev [1] 0xb:0xc4 DW_TAG_compile_unit
52+
.asciz "Hand-written DWARF" # DW_AT_producer
53+
.asciz "main.cpp" # DW_AT_name
54+
.long 0 # DW_AT_stmt_list
55+
.quad main-.text # DW_AT_low_pc
56+
.long .Lmain_end-main # DW_AT_high_pc
57+
.Ldebug_info_end0:
58+
59+
.section .debug_line,"",@progbits
60+
.long .Llt1_end - .Llt1_start # Length of Unit (DWARF-32 format)
61+
.Llt1_start:
62+
.short 4 # DWARF version number
63+
.long .Lprologue1_end-.Lprologue1_start # Length of Prologue
64+
.Lprologue1_start:
65+
.byte 1 # Minimum Instruction Length
66+
.byte 1 # Maximum Operations per Instruction
67+
.byte 1 # Default is_stmt
68+
.byte -5 # Line Base
69+
.byte 14 # Line Range
70+
.byte 13 # Opcode Base
71+
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # Standard Opcode Lengths
72+
.byte 0
73+
.asciz "main.cpp" # File table
74+
.byte 0, 0, 0
75+
.byte 0
76+
.Lprologue1_end:
77+
.byte 0, 9, 2 # DW_LNE_set_address
78+
.quad -1
79+
.byte 1 # DW_LNS_copy
80+
.byte 33 # address += 1, line += 1
81+
.byte 33 # address += 1, line += 1
82+
.byte 33 # address += 1, line += 1
83+
.byte 33 # address += 1, line += 1
84+
.byte 33 # address += 1, line += 1
85+
.byte 33 # address += 1, line += 1
86+
.byte 33 # address += 1, line += 1
87+
.byte 33 # address += 1, line += 1
88+
.byte 33 # address += 1, line += 1
89+
.byte 33 # address += 1, line += 1
90+
.byte 33 # address += 1, line += 1
91+
.byte 33 # address += 1, line += 1
92+
.byte 33 # address += 1, line += 1
93+
.byte 33 # address += 1, line += 1
94+
.byte 33 # address += 1, line += 1
95+
.byte 2 # DW_LNS_advance_pc
96+
.uleb128 1
97+
.byte 0, 1, 1 # DW_LNE_end_sequence
98+
99+
.byte 0, 9, 2 # DW_LNE_set_address
100+
.quad main-.text
101+
.byte 18 # address += 0, line += 0
102+
.byte 2 # DW_LNS_advance_pc
103+
.uleb128 1
104+
.byte 0, 1, 1 # DW_LNE_end_sequence
105+
.Llt1_end:
106+

0 commit comments

Comments
 (0)