Skip to content

Commit fd623ba

Browse files
slackitotstellar
authored andcommitted
Fix crash after looking up dwo_id=0 in CU index.
In the current state, if getFromHash(0) is called and there's no CU with dwo_id=0, the lookup will stop at an empty slot, then the check `Rows[H].getSignature() != S` won't cause the lookup to fail and return a nullptr (as it should), because the empty slot has a 0 in the signature field, and a pointer to the empty slot will be incorrectly returned. This patch fixes this by using the index field in the hash entry to check for empty slots: signature = 0 can match a valid hash but according to the spec the index for an occupied slot will always be non-zero. Differential Revision: https://reviews.llvm.org/D91670 (cherry picked from commit 314a0d7)
1 parent f590845 commit fd623ba

File tree

2 files changed

+124
-2
lines changed

2 files changed

+124
-2
lines changed

llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,14 @@ const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
286286

287287
auto H = S & Mask;
288288
auto HP = ((S >> 32) & Mask) | 1;
289-
while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
289+
// The spec says "while 0 is a valid hash value, the row index in a used slot
290+
// will always be non-zero". Loop until we find a match or an empty slot.
291+
while (Rows[H].getSignature() != S && Rows[H].Index != nullptr)
290292
H = (H + HP) & Mask;
291293

292-
if (Rows[H].getSignature() != S)
294+
// If the slot is empty, we don't care whether the signature matches (it could
295+
// be zero and still match the zeros in the empty slot).
296+
if (Rows[H].Index == nullptr)
293297
return nullptr;
294298

295299
return &Rows[H];
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
## This test checks that looking up a zero hash in the .debug_cu_index hash
2+
## table works correctly when there's no CU with signature = 0.
3+
##
4+
## LLVM used to check just the signature bits to decide if the hash lookup ended
5+
## at a match or at an empty slot. This is wrong when signature = 0 because
6+
## empty slots have all zeros in the signature field too, and LLVM would return
7+
## the empty slot as a valid result.
8+
9+
# REQUIRES: x86-registered-target
10+
11+
# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t --defsym MAIN=0
12+
# RUN: llvm-mc --filetype=obj --triple x86_64 %s -o %t.dwp
13+
# RUN: llvm-symbolizer --obj=%t --dwp=%t.dwp 0x0 | FileCheck %s
14+
15+
## This expected output is very uninteresting, but it's better than a crash.
16+
# CHECK: ??:0:0
17+
18+
.section .debug_abbrev,"",@progbits
19+
.byte 1 # Abbreviation Code
20+
.byte 17 # DW_TAG_compile_unit
21+
.byte 0 # DW_CHILDREN_no
22+
.ascii "\260B" # DW_AT_GNU_dwo_name
23+
.byte 8 # DW_FORM_string
24+
.ascii "\261B" # DW_AT_GNU_dwo_id
25+
.byte 7 # DW_FORM_data8
26+
.ascii "\263B" # DW_AT_GNU_addr_base
27+
.byte 23 # DW_FORM_sec_offset
28+
.byte 85 # DW_AT_ranges
29+
.byte 23 # DW_FORM_sec_offset
30+
.byte 0 # EOM(1)
31+
.byte 0 # EOM(2)
32+
.byte 0 # EOM(3)
33+
34+
## Create two CUs, with dwo_ids 0 and 1 respectively.
35+
.ifdef MAIN
36+
.irpc I,01
37+
.data
38+
A\I:
39+
.long \I
40+
41+
.text
42+
F\I:
43+
nop
44+
45+
.section .debug_info,"",@progbits
46+
.Lcu_begin\I:
47+
.long .Ldebug_info_end\I-.Ldebug_info_start\I # Length of Unit
48+
.Ldebug_info_start\I:
49+
.short 4 # DWARF version number
50+
.long .debug_abbrev # Offset Into Abbrev. Section
51+
.byte 8 # Address Size (in bytes)
52+
.byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
53+
.asciz "A.dwo" # DW_AT_GNU_dwo_name
54+
.quad \I # DW_AT_GNU_dwo_id
55+
.long .debug_addr # DW_AT_GNU_addr_base
56+
.long .Lranges\I # DW_AT_ranges
57+
.Ldebug_info_end\I:
58+
59+
.section .debug_addr,"",@progbits
60+
.quad A\I
61+
.quad F\I
62+
63+
.section .debug_ranges,"",@progbits
64+
.Lranges\I:
65+
.quad F\I
66+
.quad F\I+1
67+
.quad 0
68+
.quad 0
69+
.endr
70+
.else
71+
## Deliberately omit compile unit 0 in the DWP. We want to check the case where
72+
## a signature = 0 matches an empty hash slot in .debug_cu_index and the index
73+
## in the parallel table has to be checked.
74+
.section .debug_abbrev.dwo,"e",@progbits
75+
.Labbrev1:
76+
.byte 1 # Abbreviation Code
77+
.byte 17 # DW_TAG_compile_unit
78+
.byte 0 # DW_CHILDREN_no
79+
.byte 37 # DW_AT_producer
80+
.byte 8 # DW_FORM_string
81+
.byte 3 # DW_AT_name
82+
.byte 8 # DW_FORM_string
83+
.byte 0 # EOM(1)
84+
.byte 0 # EOM(2)
85+
.byte 0 # EOM(3)
86+
.Labbrev_end1:
87+
88+
.section .debug_info.dwo,"e",@progbits
89+
.Lcu_begin1:
90+
.long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
91+
.Ldebug_info_start1:
92+
.short 4 # DWARF version number
93+
.long 0 # Offset Into Abbrev. Section
94+
.byte 8 # Address Size (in bytes)
95+
.byte 1 # Abbrev DW_TAG_compile_unit
96+
.asciz "Hand-written DWARF" # DW_AT_producer
97+
.byte '1', '.', 'c', 0 # DW_AT_name
98+
.Ldebug_info_end1:
99+
100+
.section .debug_cu_index,"",@progbits
101+
.long 2 # DWARF version number
102+
.long 2 # Section count
103+
.long 1 # Unit count
104+
.long 8 # Slot count
105+
106+
.quad 1, 0, 0, 0, 0, 0, 0, 0 # Hash table
107+
.long 1, 0, 0, 0, 0, 0, 0, 0 # Index table
108+
109+
.long 1 # DW_SECT_INFO
110+
.long 3 # DW_SECT_ABBREV
111+
112+
.long .Lcu_begin1-.debug_info.dwo
113+
.long .Labbrev1-.debug_abbrev.dwo
114+
115+
.long .Ldebug_info_end1-.Lcu_begin1
116+
.long .Labbrev_end1-.Labbrev1
117+
118+
.endif

0 commit comments

Comments
 (0)