Skip to content

Commit ed468a3

Browse files
Merge pull request #1950 from adrian-prantl/D86615-main
[lldb/DWARF] Fix handling of variables with both location and const_v… …
2 parents 523e6ec + 31031e6 commit ed468a3

File tree

3 files changed

+218
-75
lines changed

3 files changed

+218
-75
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class DWARFFormValue {
4242
DWARFFormValue(const DWARFUnit *unit) : m_unit(unit) {}
4343
DWARFFormValue(const DWARFUnit *unit, dw_form_t form)
4444
: m_unit(unit), m_form(form) {}
45+
const DWARFUnit *GetUnit() const { return m_unit; }
4546
void SetUnit(const DWARFUnit *unit) { m_unit = unit; }
4647
dw_form_t Form() const { return m_form; }
4748
dw_form_t& FormRef() { return m_form; }

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

Lines changed: 73 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
249249
return support_files;
250250
}
251251

252-
static inline bool IsSwiftLanguage(LanguageType language) {
253-
return language == eLanguageTypePLI || language == eLanguageTypeSwift ||
254-
((uint32_t)language == (uint32_t)llvm::dwarf::DW_LANG_Swift);
255-
}
256-
257252
void SymbolFileDWARF::Initialize() {
258253
LogChannelDWARF::Initialize();
259254
PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -974,7 +969,7 @@ bool SymbolFileDWARF::ParseImportedModules(
974969
return false;
975970
auto lang = sc.comp_unit->GetLanguage();
976971
if (!ClangModulesDeclVendor::LanguageSupportsClangModules(lang) &&
977-
!IsSwiftLanguage(lang))
972+
lang != eLanguageTypeSwift)
978973
return false;
979974
UpdateExternalModuleListIfNeeded();
980975

@@ -3185,18 +3180,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
31853180
const char *name = nullptr;
31863181
const char *mangled = nullptr;
31873182
Declaration decl;
3188-
uint32_t i;
31893183
DWARFFormValue type_die_form;
31903184
DWARFExpression location;
31913185
bool is_external = false;
31923186
bool is_artificial = false;
3193-
bool location_is_const_value_data = false;
3194-
bool has_explicit_location = false;
3195-
DWARFFormValue const_value;
3187+
DWARFFormValue const_value_form, location_form;
31963188
Variable::RangeList scope_ranges;
31973189
// AccessType accessibility = eAccessNone;
31983190

3199-
for (i = 0; i < num_attributes; ++i) {
3191+
for (size_t i = 0; i < num_attributes; ++i) {
32003192
dw_attr_t attr = attributes.AttributeAtIndex(i);
32013193
DWARFFormValue form_value;
32023194

@@ -3226,65 +3218,11 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
32263218
is_external = form_value.Boolean();
32273219
break;
32283220
case DW_AT_const_value:
3229-
// If we have already found a DW_AT_location attribute, ignore this
3230-
// attribute.
3231-
if (!has_explicit_location) {
3232-
location_is_const_value_data = true;
3233-
// The constant value will be either a block, a data value or a
3234-
// string.
3235-
auto debug_info_data = die.GetData();
3236-
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
3237-
// Retrieve the value as a block expression.
3238-
uint32_t block_offset =
3239-
form_value.BlockData() - debug_info_data.GetDataStart();
3240-
uint32_t block_length = form_value.Unsigned();
3241-
location = DWARFExpression(
3242-
module,
3243-
DataExtractor(debug_info_data, block_offset, block_length),
3244-
die.GetCU());
3245-
} else if (DWARFFormValue::IsDataForm(form_value.Form())) {
3246-
// Constant value size does not have to match the size of the
3247-
// variable. We will fetch the size of the type after we create
3248-
// it.
3249-
const_value = form_value;
3250-
} else if (const char *str = form_value.AsCString()) {
3251-
uint32_t string_length = strlen(str) + 1;
3252-
location = DWARFExpression(
3253-
module,
3254-
DataExtractor(str, string_length,
3255-
die.GetCU()->GetByteOrder(),
3256-
die.GetCU()->GetAddressByteSize()),
3257-
die.GetCU());
3258-
}
3259-
}
3221+
const_value_form = form_value;
3222+
break;
3223+
case DW_AT_location:
3224+
location_form = form_value;
32603225
break;
3261-
case DW_AT_location: {
3262-
location_is_const_value_data = false;
3263-
has_explicit_location = true;
3264-
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
3265-
auto data = die.GetData();
3266-
3267-
uint32_t block_offset =
3268-
form_value.BlockData() - data.GetDataStart();
3269-
uint32_t block_length = form_value.Unsigned();
3270-
location = DWARFExpression(
3271-
module, DataExtractor(data, block_offset, block_length),
3272-
die.GetCU());
3273-
} else {
3274-
DataExtractor data = die.GetCU()->GetLocationData();
3275-
dw_offset_t offset = form_value.Unsigned();
3276-
if (form_value.Form() == DW_FORM_loclistx)
3277-
offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
3278-
if (data.ValidOffset(offset)) {
3279-
data = DataExtractor(data, offset, data.GetByteSize() - offset);
3280-
location = DWARFExpression(module, data, die.GetCU());
3281-
assert(func_low_pc != LLDB_INVALID_ADDRESS);
3282-
location.SetLocationListAddresses(
3283-
attributes.CompileUnitAtIndex(i)->GetBaseAddress(),
3284-
func_low_pc);
3285-
}
3286-
}
3287-
} break;
32883226
case DW_AT_specification:
32893227
spec_die = form_value.Reference();
32903228
break;
@@ -3311,9 +3249,69 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
33113249
}
33123250

33133251
if (tag == DW_TAG_variable && mangled &&
3314-
IsSwiftLanguage(sc.comp_unit->GetLanguage()))
3252+
sc.comp_unit->GetLanguage() == eLanguageTypeSwift)
33153253
mangled = NULL;
33163254

3255+
// Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
3256+
// for static constexpr member variables -- DW_AT_const_value will be
3257+
// present in the class declaration and DW_AT_location in the DIE defining
3258+
// the member.
3259+
bool location_is_const_value_data = false;
3260+
bool has_explicit_location = false;
3261+
bool use_type_size_for_value = false;
3262+
if (location_form.IsValid()) {
3263+
has_explicit_location = true;
3264+
if (DWARFFormValue::IsBlockForm(location_form.Form())) {
3265+
const DWARFDataExtractor &data = die.GetData();
3266+
3267+
uint32_t block_offset =
3268+
location_form.BlockData() - data.GetDataStart();
3269+
uint32_t block_length = location_form.Unsigned();
3270+
location = DWARFExpression(
3271+
module, DataExtractor(data, block_offset, block_length),
3272+
die.GetCU());
3273+
} else {
3274+
DataExtractor data = die.GetCU()->GetLocationData();
3275+
dw_offset_t offset = location_form.Unsigned();
3276+
if (location_form.Form() == DW_FORM_loclistx)
3277+
offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
3278+
if (data.ValidOffset(offset)) {
3279+
data = DataExtractor(data, offset, data.GetByteSize() - offset);
3280+
location = DWARFExpression(module, data, die.GetCU());
3281+
assert(func_low_pc != LLDB_INVALID_ADDRESS);
3282+
location.SetLocationListAddresses(
3283+
location_form.GetUnit()->GetBaseAddress(), func_low_pc);
3284+
}
3285+
}
3286+
} else if (const_value_form.IsValid()) {
3287+
location_is_const_value_data = true;
3288+
// The constant value will be either a block, a data value or a
3289+
// string.
3290+
const DWARFDataExtractor &debug_info_data = die.GetData();
3291+
if (DWARFFormValue::IsBlockForm(const_value_form.Form())) {
3292+
// Retrieve the value as a block expression.
3293+
uint32_t block_offset =
3294+
const_value_form.BlockData() - debug_info_data.GetDataStart();
3295+
uint32_t block_length = const_value_form.Unsigned();
3296+
location = DWARFExpression(
3297+
module,
3298+
DataExtractor(debug_info_data, block_offset, block_length),
3299+
die.GetCU());
3300+
} else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
3301+
// Constant value size does not have to match the size of the
3302+
// variable. We will fetch the size of the type after we create
3303+
// it.
3304+
use_type_size_for_value = true;
3305+
} else if (const char *str = const_value_form.AsCString()) {
3306+
uint32_t string_length = strlen(str) + 1;
3307+
location = DWARFExpression(
3308+
module,
3309+
DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
3310+
die.GetCU()->GetAddressByteSize()),
3311+
die.GetCU());
3312+
}
3313+
}
3314+
33173315
const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
33183316
const dw_tag_t parent_tag = die.GetParent().Tag();
33193317
bool is_static_member =
@@ -3493,18 +3491,18 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
34933491
}
34943492

34953493
if (symbol_context_scope) {
3496-
SymbolFileTypeSP type_sp(
3497-
new SymbolFileType(*this, GetUID(type_die_form.Reference())));
3494+
auto type_sp = std::make_shared<SymbolFileType>(
3495+
*this, GetUID(type_die_form.Reference()));
34983496

3499-
if (const_value.Form() && type_sp && type_sp->GetType())
3497+
if (use_type_size_for_value && type_sp->GetType())
35003498
location.UpdateValue(
3501-
const_value.Unsigned(),
3499+
const_value_form.Unsigned(),
35023500
type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
35033501
die.GetCU()->GetAddressByteSize());
35043502

35053503
// Swift let-bindings are marked by a DW_TAG_const_type.
35063504
bool is_constant = false;
3507-
if (IsSwiftLanguage(sc.comp_unit->GetLanguage())) {
3505+
if (sc.comp_unit->GetLanguage() == eLanguageTypeSwift) {
35083506
DWARFDIE type_die = die.GetReferencedDIE(llvm::dwarf::DW_AT_type);
35093507
if (type_die && type_die.Tag() == llvm::dwarf::DW_TAG_const_type)
35103508
is_constant = true;
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
## Test that we don't get confused by variables with both location and
2+
## const_value attributes. Such values are produced in C++ for class-level
3+
## static constexpr variables.
4+
5+
# REQUIRES: x86
6+
7+
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o %t
8+
# RUN: %lldb %t -o "target variable A::x A::y" -o exit | FileCheck %s
9+
10+
# CHECK-LABEL: target variable
11+
# CHECK: (const int) A::x = 142
12+
# CHECK: (const int) A::y = 242
13+
14+
.section .rodata,"a",@progbits
15+
.p2align 2
16+
_ZN1A1xE:
17+
.long 142
18+
_ZN1A1yE:
19+
.long 242
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 3 # DW_AT_name
28+
.byte 8 # DW_FORM_string
29+
.byte 0 # EOM(1)
30+
.byte 0 # EOM(2)
31+
.byte 3 # Abbreviation Code
32+
.byte 19 # DW_TAG_structure_type
33+
.byte 1 # DW_CHILDREN_yes
34+
.byte 3 # DW_AT_name
35+
.byte 8 # DW_FORM_string
36+
.byte 11 # DW_AT_byte_size
37+
.byte 11 # DW_FORM_data1
38+
.byte 0 # EOM(1)
39+
.byte 0 # EOM(2)
40+
.byte 4 # Abbreviation Code
41+
.byte 13 # DW_TAG_member
42+
.byte 0 # DW_CHILDREN_no
43+
.byte 3 # DW_AT_name
44+
.byte 8 # DW_FORM_string
45+
.byte 73 # DW_AT_type
46+
.byte 19 # DW_FORM_ref4
47+
.byte 60 # DW_AT_declaration
48+
.byte 25 # DW_FORM_flag_present
49+
.byte 28 # DW_AT_const_value
50+
.byte 13 # DW_FORM_sdata
51+
.byte 0 # EOM(1)
52+
.byte 0 # EOM(2)
53+
.byte 5 # Abbreviation Code
54+
.byte 38 # DW_TAG_const_type
55+
.byte 0 # DW_CHILDREN_no
56+
.byte 73 # DW_AT_type
57+
.byte 19 # DW_FORM_ref4
58+
.byte 0 # EOM(1)
59+
.byte 0 # EOM(2)
60+
.byte 6 # Abbreviation Code
61+
.byte 36 # DW_TAG_base_type
62+
.byte 0 # DW_CHILDREN_no
63+
.byte 3 # DW_AT_name
64+
.byte 8 # DW_FORM_string
65+
.byte 62 # DW_AT_encoding
66+
.byte 11 # DW_FORM_data1
67+
.byte 11 # DW_AT_byte_size
68+
.byte 11 # DW_FORM_data1
69+
.byte 0 # EOM(1)
70+
.byte 0 # EOM(2)
71+
.byte 7 # Abbreviation Code
72+
.byte 52 # DW_TAG_variable
73+
.byte 0 # DW_CHILDREN_no
74+
.byte 71 # DW_AT_specification
75+
.byte 19 # DW_FORM_ref4
76+
.byte 2 # DW_AT_location
77+
.byte 24 # DW_FORM_exprloc
78+
.byte 110 # DW_AT_linkage_name
79+
.byte 8 # DW_FORM_string
80+
.byte 0 # EOM(1)
81+
.byte 0 # EOM(2)
82+
## This deliberately inverts the order of the specification and location
83+
## attributes.
84+
.byte 8 # Abbreviation Code
85+
.byte 52 # DW_TAG_variable
86+
.byte 0 # DW_CHILDREN_no
87+
.byte 2 # DW_AT_location
88+
.byte 24 # DW_FORM_exprloc
89+
.byte 71 # DW_AT_specification
90+
.byte 19 # DW_FORM_ref4
91+
.byte 110 # DW_AT_linkage_name
92+
.byte 8 # DW_FORM_string
93+
.byte 0 # EOM(1)
94+
.byte 0 # EOM(2)
95+
.byte 0 # EOM(3)
96+
97+
.section .debug_info,"",@progbits
98+
.Lcu_begin0:
99+
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
100+
.Ldebug_info_start0:
101+
.short 4 # DWARF version number
102+
.long .debug_abbrev # Offset Into Abbrev. Section
103+
.byte 8 # Address Size (in bytes)
104+
.byte 1 # Abbrev DW_TAG_compile_unit
105+
.asciz "Hand-written DWARF" # DW_AT_producer
106+
.asciz "a.cc" # DW_AT_name
107+
.byte 7 # Abbrev DW_TAG_variable
108+
.long .LA__x-.Lcu_begin0 # DW_AT_specification
109+
.byte 9 # DW_AT_location
110+
.byte 3
111+
.quad _ZN1A1xE
112+
.asciz "_ZN1A1xE" # DW_AT_linkage_name
113+
.byte 8 # Abbrev DW_TAG_variable
114+
.byte 9 # DW_AT_location
115+
.byte 3
116+
.quad _ZN1A1yE
117+
.long .LA__y-.Lcu_begin0 # DW_AT_specification
118+
.asciz "_ZN1A1yE" # DW_AT_linkage_name
119+
.byte 3 # Abbrev DW_TAG_structure_type
120+
.asciz "A" # DW_AT_name
121+
.byte 1 # DW_AT_byte_size
122+
.LA__x:
123+
.byte 4 # Abbrev DW_TAG_member
124+
.asciz "x" # DW_AT_name
125+
.long .Lconst_int-.Lcu_begin0 # DW_AT_type
126+
# DW_AT_declaration
127+
.sleb128 147 # DW_AT_const_value
128+
.LA__y:
129+
.byte 4 # Abbrev DW_TAG_member
130+
.asciz "y" # DW_AT_name
131+
.long .Lconst_int-.Lcu_begin0 # DW_AT_type
132+
# DW_AT_declaration
133+
.sleb128 247 # DW_AT_const_value
134+
.byte 0 # End Of Children Mark
135+
.Lconst_int:
136+
.byte 5 # Abbrev DW_TAG_const_type
137+
.long .Lint-.Lcu_begin0 # DW_AT_type
138+
.Lint:
139+
.byte 6 # Abbrev DW_TAG_base_type
140+
.asciz "int" # DW_AT_name
141+
.byte 5 # DW_AT_encoding
142+
.byte 4 # DW_AT_byte_size
143+
.byte 0 # End Of Children Mark
144+
.Ldebug_info_end0:

0 commit comments

Comments
 (0)