Skip to content

Commit 15f9020

Browse files
authored
[lldb/DWARF] Respect member layout for types parsed through declarations (#110648)
LLDB code for using the type layout data from DWARF was not kicking in for types which were initially parsed from a declaration. The problem was in these lines of code: ``` if (type) layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8; ``` which determine the types layout size by getting the size from the lldb_private::Type object. The problem is that if the type object does not have this information cached, this request can trigger another (recursive) request to lay out/complete the type. This one, somewhat surprisingly, succeeds, but does that without the type layout information (because it hasn't been computed yet). The reasons why this hasn't been noticed so far are: - this is a relatively new bug. I haven't checked but I suspect it was introduced in the "delay type definition search" patchset from this summer -- if we search for the definition eagerly, we will always have a cached size value. - it requires the presence of another bug/issue, as otherwise the automatically computed layout will match the real thing. - it reproduces (much) more easily with -flimit-debug-info (though it is possible to trigger it without that flag). My fix consists of always fetching type size information from DWARF (which so far existed as a fallback path). I'm not quite sure why this code was there in the first place (the code goes back to before the Great LLDB Reformat), but I don't believe it is necessary, as the type size (for types parsed from definition DIEs) is set exactly from this attribute (in ParseStructureLikeDIE).
1 parent 8712140 commit 15f9020

File tree

3 files changed

+139
-8
lines changed

3 files changed

+139
-8
lines changed

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,14 +2128,10 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
21282128
TypeSystemClang::BuildIndirectFields(clang_type);
21292129
TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
21302130

2131-
if (type)
2132-
layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8;
2133-
if (layout_info.bit_size == 0)
2134-
layout_info.bit_size =
2135-
die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
2136-
if (layout_info.alignment == 0)
2137-
layout_info.alignment =
2138-
die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8;
2131+
layout_info.bit_size =
2132+
die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
2133+
layout_info.alignment =
2134+
die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8;
21392135

21402136
clang::CXXRecordDecl *record_decl =
21412137
m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
## Test that lldb respects the layout defined in DWARF even when starting out
2+
## with a declaration of the class.
3+
4+
# RUN: split-file %s %t
5+
# RUN: llvm-mc --triple x86_64-pc-linux %t/asm --filetype=obj -o %t.o
6+
# RUN: %lldb -s %t/commands -o exit %t.o 2>&1 | FileCheck %s
7+
8+
#--- commands
9+
target var a -fx
10+
# CHECK-LABEL: target var a
11+
# CHECK: (A) a = (i = 0xbaadf00d)
12+
13+
#--- asm
14+
.data
15+
.p2align 4
16+
.long 0
17+
a:
18+
.long 0xdeadbeef
19+
.long 0xbaadf00d
20+
21+
.section .debug_abbrev,"",@progbits
22+
.byte 1 # Abbreviation Code
23+
.byte 17 # DW_TAG_compile_unit
24+
.byte 1 # DW_CHILDREN_yes
25+
.byte 37 # DW_AT_producer
26+
.byte 8 # DW_FORM_string
27+
.byte 0 # EOM(1)
28+
.byte 0 # EOM(2)
29+
.byte 2 # Abbreviation Code
30+
.byte 52 # DW_TAG_variable
31+
.byte 0 # DW_CHILDREN_no
32+
.byte 3 # DW_AT_name
33+
.byte 8 # DW_FORM_string
34+
.byte 73 # DW_AT_type
35+
.byte 19 # DW_FORM_ref4
36+
.byte 2 # DW_AT_location
37+
.byte 24 # DW_FORM_exprloc
38+
.byte 0 # EOM(1)
39+
.byte 0 # EOM(2)
40+
.byte 3 # Abbreviation Code
41+
.byte 19 # DW_TAG_structure_type
42+
.byte 0 # DW_CHILDREN_no
43+
.byte 3 # DW_AT_name
44+
.byte 8 # DW_FORM_string
45+
.byte 60 # DW_AT_declaration
46+
.byte 25 # DW_FORM_flag_present
47+
.byte 0 # EOM(1)
48+
.byte 0 # EOM(2)
49+
.byte 4 # Abbreviation Code
50+
.byte 19 # DW_TAG_structure_type
51+
.byte 1 # DW_CHILDREN_yes
52+
.byte 3 # DW_AT_name
53+
.byte 8 # DW_FORM_string
54+
.byte 11 # DW_AT_byte_size
55+
.byte 11 # DW_FORM_data1
56+
.byte 0 # EOM(1)
57+
.byte 0 # EOM(2)
58+
.byte 5 # Abbreviation Code
59+
.byte 13 # DW_TAG_member
60+
.byte 0 # DW_CHILDREN_no
61+
.byte 3 # DW_AT_name
62+
.byte 8 # DW_FORM_string
63+
.byte 73 # DW_AT_type
64+
.byte 19 # DW_FORM_ref4
65+
.byte 56 # DW_AT_data_member_location
66+
.byte 11 # DW_FORM_data1
67+
.byte 0 # EOM(1)
68+
.byte 0 # EOM(2)
69+
.byte 6 # Abbreviation Code
70+
.byte 36 # DW_TAG_base_type
71+
.byte 0 # DW_CHILDREN_no
72+
.byte 3 # DW_AT_name
73+
.byte 8 # DW_FORM_string
74+
.byte 62 # DW_AT_encoding
75+
.byte 11 # DW_FORM_data1
76+
.byte 11 # DW_AT_byte_size
77+
.byte 11 # DW_FORM_data1
78+
.byte 0 # EOM(1)
79+
.byte 0 # EOM(2)
80+
.byte 0 # EOM(3)
81+
82+
.section .debug_info,"",@progbits
83+
.Lcu_begin0:
84+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
85+
.Ldebug_info_start0:
86+
.short 4 # DWARF version number
87+
.long .debug_abbrev # Offset Into Abbrev. Section
88+
.byte 8 # Address Size (in bytes)
89+
.byte 1 # Abbrev [1] DW_TAG_compile_unit
90+
.asciz "Hand-written DWARF" # DW_AT_producer
91+
92+
.byte 2 # Abbrev [2] DW_TAG_variable
93+
.asciz "a" # DW_AT_name
94+
.long .LA_decl-.Lcu_begin0 # DW_AT_type
95+
.byte 9 # DW_AT_location
96+
.byte 3
97+
.quad a
98+
.LA_decl:
99+
.byte 3 # Abbrev [3] DW_TAG_structure_type
100+
.asciz "A" # DW_AT_name
101+
# DW_AT_declaration
102+
.byte 0 # End Of Children Mark
103+
.Ldebug_info_end0:
104+
105+
.Lcu_begin1:
106+
.long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
107+
.Ldebug_info_start1:
108+
.short 4 # DWARF version number
109+
.long .debug_abbrev # Offset Into Abbrev. Section
110+
.byte 8 # Address Size (in bytes)
111+
.byte 1 # Abbrev [1] DW_TAG_compile_unit
112+
.asciz "Hand-written DWARF" # DW_AT_producer
113+
114+
.byte 4 # Abbrev [4] DW_TAG_structure_type
115+
.asciz "A" # DW_AT_name
116+
# DW_AT_declaration
117+
.byte 8 # DW_AT_byte_size
118+
.byte 5 # Abbrev [5] DW_TAG_member
119+
.asciz "i" # DW_AT_name
120+
.long .Lint-.Lcu_begin1 # DW_AT_type
121+
## NB: empty padding before this member
122+
.byte 4 # DW_AT_data_member_location
123+
.byte 0 # End Of Children Mark
124+
125+
.Lint:
126+
.byte 6 # Abbrev [6] DW_TAG_base_type
127+
.asciz "int" # DW_AT_name
128+
.byte 5 # DW_AT_encoding
129+
.byte 4 # DW_AT_byte_size
130+
131+
.byte 0 # End Of Children Mark
132+
.Ldebug_info_end1:

lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ c1:
105105
.byte 1 # DW_CHILDREN_yes
106106
.byte 3 # DW_AT_name
107107
.byte 8 # DW_FORM_string
108+
.byte 11 # DW_AT_byte_size
109+
.byte 11 # DW_FORM_data1
108110
.byte 0 # EOM(1)
109111
.byte 0 # EOM(2)
110112
.byte 7 # Abbreviation Code
@@ -251,6 +253,7 @@ c1:
251253
.LB1:
252254
.byte 6 # Abbrev [6] DW_TAG_class_type
253255
.asciz "B1" # DW_AT_name
256+
.byte 8 # DW_AT_byte_size
254257
.byte 7 # Abbrev [5] 0x58:0xc DW_TAG_member
255258
.asciz "ptr" # DW_AT_name
256259
.long .LAptr # DW_AT_type

0 commit comments

Comments
 (0)