Skip to content

Commit df6d057

Browse files
committed
Fix a crash in DWARFUnit::getInlinedChainForAddress in case of unexpected DWARF information.
In some cases a broken or invalid debug info could cause a crash in DWARFUnit::getInlinedChainForAddress during parsing a chain of in-lined functions. This patch fixes this issue. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D98119
1 parent 93b170e commit df6d057

File tree

2 files changed

+150
-5
lines changed

2 files changed

+150
-5
lines changed

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -688,15 +688,15 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address,
688688
DWARFDie SubroutineDIE =
689689
(DWO ? *DWO : *this).getSubroutineForAddress(Address);
690690

691-
if (!SubroutineDIE)
692-
return;
693-
694-
while (!SubroutineDIE.isSubprogramDIE()) {
691+
while (SubroutineDIE) {
692+
if (SubroutineDIE.isSubprogramDIE()) {
693+
InlinedChain.push_back(SubroutineDIE);
694+
return;
695+
}
695696
if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
696697
InlinedChain.push_back(SubroutineDIE);
697698
SubroutineDIE = SubroutineDIE.getParent();
698699
}
699-
InlinedChain.push_back(SubroutineDIE);
700700
}
701701

702702
const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
## This test checks how we handle parsing a broken DWARF when
2+
## a parent of DW_TAG_inlined_subroutine is anything other than DW_TAG_subprogram.
3+
4+
# REQUIRES: x86-registered-target
5+
6+
# RUN: llvm-mc -filetype=obj -triple=i386-linux-gnu -o %t.o %s
7+
# RUN: llvm-symbolizer "CODE %t.o 0" \
8+
# RUN: | FileCheck %s --strict-whitespace --match-full-lines --implicit-check-not={{.}}
9+
10+
# CHECK:main
11+
# CHECK-NEXT:/tmp/test{{/|\\}}test.cpp:2:3
12+
13+
## Generated from:
14+
##
15+
## int main() {
16+
## return 123;
17+
## }
18+
##
19+
## clang++ --target=i386-linux-gnu test.cpp -g -O2 -std=c++11 -S -o test.s
20+
21+
.text
22+
.file "test.cpp"
23+
.globl main # -- Begin function main
24+
.p2align 4, 0x90
25+
.type main,@function
26+
main: # @main
27+
.Lfunc_begin0:
28+
.file 1 "/tmp/test" "test.cpp"
29+
.loc 1 1 0 # test.cpp:1:0
30+
.cfi_sections .debug_frame
31+
.cfi_startproc
32+
# %bb.0: # %entry
33+
.loc 1 2 3 prologue_end # test.cpp:2:3
34+
movl $123, %eax
35+
retl
36+
.Ltmp0:
37+
.Lfunc_end0:
38+
.size main, .Lfunc_end0-main
39+
.cfi_endproc
40+
# -- End function
41+
.section .debug_abbrev,"",@progbits
42+
.byte 1 # Abbreviation Code
43+
.byte 17 # DW_TAG_compile_unit
44+
.byte 1 # DW_CHILDREN_yes
45+
.byte 37 # DW_AT_producer
46+
.byte 14 # DW_FORM_strp
47+
.byte 19 # DW_AT_language
48+
.byte 5 # DW_FORM_data2
49+
.byte 3 # DW_AT_name
50+
.byte 14 # DW_FORM_strp
51+
.byte 16 # DW_AT_stmt_list
52+
.byte 23 # DW_FORM_sec_offset
53+
.byte 27 # DW_AT_comp_dir
54+
.byte 14 # DW_FORM_strp
55+
.byte 17 # DW_AT_low_pc
56+
.byte 1 # DW_FORM_addr
57+
.byte 18 # DW_AT_high_pc
58+
.byte 6 # DW_FORM_data4
59+
.byte 0 # EOM(1)
60+
.byte 0 # EOM(2)
61+
.byte 2 # Abbreviation Code
62+
// Replace DW_TAG_subprogram with DW_TAG_inlined_subroutine
63+
// .byte 46 # DW_TAG_subprogram
64+
.byte 29 # DW_TAG_inlined_subroutine
65+
.byte 0 # DW_CHILDREN_no
66+
.byte 17 # DW_AT_low_pc
67+
.byte 1 # DW_FORM_addr
68+
.byte 18 # DW_AT_high_pc
69+
.byte 6 # DW_FORM_data4
70+
.byte 64 # DW_AT_frame_base
71+
.byte 24 # DW_FORM_exprloc
72+
.ascii "\227B" # DW_AT_GNU_all_call_sites
73+
.byte 25 # DW_FORM_flag_present
74+
.byte 3 # DW_AT_name
75+
.byte 14 # DW_FORM_strp
76+
.byte 58 # DW_AT_decl_file
77+
.byte 11 # DW_FORM_data1
78+
.byte 59 # DW_AT_decl_line
79+
.byte 11 # DW_FORM_data1
80+
.byte 73 # DW_AT_type
81+
.byte 19 # DW_FORM_ref4
82+
.byte 63 # DW_AT_external
83+
.byte 25 # DW_FORM_flag_present
84+
.byte 0 # EOM(1)
85+
.byte 0 # EOM(2)
86+
.byte 3 # Abbreviation Code
87+
.byte 36 # DW_TAG_base_type
88+
.byte 0 # DW_CHILDREN_no
89+
.byte 3 # DW_AT_name
90+
.byte 14 # DW_FORM_strp
91+
.byte 62 # DW_AT_encoding
92+
.byte 11 # DW_FORM_data1
93+
.byte 11 # DW_AT_byte_size
94+
.byte 11 # DW_FORM_data1
95+
.byte 0 # EOM(1)
96+
.byte 0 # EOM(2)
97+
.byte 0 # EOM(3)
98+
.section .debug_info,"",@progbits
99+
.Lcu_begin0:
100+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
101+
.Ldebug_info_start0:
102+
.short 4 # DWARF version number
103+
.long .debug_abbrev # Offset Into Abbrev. Section
104+
.byte 4 # Address Size (in bytes)
105+
.byte 1 # Abbrev [1] 0xb:0x38 DW_TAG_compile_unit
106+
.long .Linfo_string0 # DW_AT_producer
107+
.short 26 # DW_AT_language
108+
.long .Linfo_string1 # DW_AT_name
109+
.long .Lline_table_start0 # DW_AT_stmt_list
110+
.long .Linfo_string2 # DW_AT_comp_dir
111+
.long .Lfunc_begin0 # DW_AT_low_pc
112+
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
113+
.byte 2 # Abbrev [2] 0x26:0x15 DW_TAG_subprogram
114+
.long .Lfunc_begin0 # DW_AT_low_pc
115+
.long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
116+
.byte 1 # DW_AT_frame_base
117+
.byte 84
118+
# DW_AT_GNU_all_call_sites
119+
.long .Linfo_string3 # DW_AT_name
120+
.byte 1 # DW_AT_decl_file
121+
.byte 1 # DW_AT_decl_line
122+
.long 59 # DW_AT_type
123+
# DW_AT_external
124+
.byte 3 # Abbrev [3] 0x3b:0x7 DW_TAG_base_type
125+
.long .Linfo_string4 # DW_AT_name
126+
.byte 5 # DW_AT_encoding
127+
.byte 4 # DW_AT_byte_size
128+
.byte 0 # End Of Children Mark
129+
.Ldebug_info_end0:
130+
.section .debug_str,"MS",@progbits,1
131+
.Linfo_string0:
132+
.asciz "clang version 13.0.0"
133+
.Linfo_string1:
134+
.asciz "test.cpp"
135+
.Linfo_string2:
136+
.asciz "/tmp/test" # string offset=114
137+
.Linfo_string3:
138+
.asciz "main"
139+
.Linfo_string4:
140+
.asciz "int"
141+
.ident "clang version 13.0.0"
142+
.section ".note.GNU-stack","",@progbits
143+
.addrsig
144+
.section .debug_line,"",@progbits
145+
.Lline_table_start0:

0 commit comments

Comments
 (0)