diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3269,6 +3269,60 @@ return var_sp; } +/// Creates a DWARFExpressionList from an DW_AT_location form_value. +static DWARFExpressionList GetExprListFromAtLocation(DWARFFormValue form_value, + ModuleSP module, + const DWARFDIE &die, + const addr_t func_low_pc) { + if (DWARFFormValue::IsBlockForm(form_value.Form())) { + const DWARFDataExtractor &data = die.GetData(); + + uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + return DWARFExpressionList( + module, DataExtractor(data, block_offset, block_length), die.GetCU()); + } + + DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU()); + DataExtractor data = die.GetCU()->GetLocationData(); + dw_offset_t offset = form_value.Unsigned(); + if (form_value.Form() == DW_FORM_loclistx) + offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + const DWARFUnit *dwarf_cu = form_value.GetUnit(); + if (DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, &location_list)) + location_list.SetFuncFileAddress(func_low_pc); + } + + return location_list; +} + +/// Creates a DWARFExpressionList from an DW_AT_const_value. This is either a +/// block form, or a string, or a data form. For data forms, this returns an +/// empty list, as we cannot initialize it properly without a SymbolFileType. +static DWARFExpressionList +GetExprListFromAtConstValue(DWARFFormValue form_value, ModuleSP module, + const DWARFDIE &die) { + const DWARFDataExtractor &debug_info_data = die.GetData(); + if (DWARFFormValue::IsBlockForm(form_value.Form())) { + // Retrieve the value as a block expression. + uint32_t block_offset = + form_value.BlockData() - debug_info_data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + return DWARFExpressionList( + module, DataExtractor(debug_info_data, block_offset, block_length), + die.GetCU()); + } + if (const char *str = form_value.AsCString()) + return DWARFExpressionList(module, + DataExtractor(str, strlen(str) + 1, + die.GetCU()->GetByteOrder(), + die.GetCU()->GetAddressByteSize()), + die.GetCU()); + return DWARFExpressionList(module, DWARFExpression(), die.GetCU()); +} + VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const DWARFDIE &die, const lldb::addr_t func_low_pc) { @@ -3290,7 +3344,6 @@ const char *mangled = nullptr; Declaration decl; DWARFFormValue type_die_form; - DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU()); bool is_external = false; bool is_artificial = false; DWARFFormValue const_value_form, location_form; @@ -3355,57 +3408,16 @@ // for static constexpr member variables -- DW_AT_const_value will be // present in the class declaration and DW_AT_location in the DIE defining // the member. - bool location_is_const_value_data = false; - bool has_explicit_location = location_form.IsValid(); - bool use_type_size_for_value = false; - if (location_form.IsValid()) { - if (DWARFFormValue::IsBlockForm(location_form.Form())) { - const DWARFDataExtractor &data = die.GetData(); - - uint32_t block_offset = location_form.BlockData() - data.GetDataStart(); - uint32_t block_length = location_form.Unsigned(); - location_list = DWARFExpressionList( - module, DataExtractor(data, block_offset, block_length), die.GetCU()); - } else { - DataExtractor data = die.GetCU()->GetLocationData(); - dw_offset_t offset = location_form.Unsigned(); - if (location_form.Form() == DW_FORM_loclistx) - offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1); - if (data.ValidOffset(offset)) { - data = DataExtractor(data, offset, data.GetByteSize() - offset); - const DWARFUnit *dwarf_cu = location_form.GetUnit(); - if (DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, - &location_list)) - location_list.SetFuncFileAddress(func_low_pc); - } - } - } else if (const_value_form.IsValid()) { - location_is_const_value_data = true; - // The constant value will be either a block, a data value or a - // string. - const DWARFDataExtractor &debug_info_data = die.GetData(); - if (DWARFFormValue::IsBlockForm(const_value_form.Form())) { - // Retrieve the value as a block expression. - uint32_t block_offset = - const_value_form.BlockData() - debug_info_data.GetDataStart(); - uint32_t block_length = const_value_form.Unsigned(); - location_list = DWARFExpressionList( - module, DataExtractor(debug_info_data, block_offset, block_length), - die.GetCU()); - } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) { - // Constant value size does not have to match the size of the - // variable. We will fetch the size of the type after we create - // it. - use_type_size_for_value = true; - } else if (const char *str = const_value_form.AsCString()) { - uint32_t string_length = strlen(str) + 1; - location_list = DWARFExpressionList( - module, - DataExtractor(str, string_length, die.GetCU()->GetByteOrder(), - die.GetCU()->GetAddressByteSize()), - die.GetCU()); - } - } + bool location_is_const_value_data = + const_value_form.IsValid() && !location_form.IsValid(); + + DWARFExpressionList location_list = [&] { + if (location_form.IsValid()) + return GetExprListFromAtLocation(location_form, module, die, func_low_pc); + if (const_value_form.IsValid()) + return GetExprListFromAtConstValue(const_value_form, module, die); + return DWARFExpressionList(module, DWARFExpression(), die.GetCU()); + }(); const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); @@ -3448,6 +3460,7 @@ // Clang likes to combine small global variables into the same symbol // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus // so we need to look through the whole expression. + bool has_explicit_location = location_form.IsValid(); bool is_static_lifetime = has_explicit_mangled || (has_explicit_location && !location_list.IsValid()); @@ -3597,6 +3610,9 @@ auto type_sp = std::make_shared( *this, type_die_form.Reference().GetID()); + bool use_type_size_for_value = + location_is_const_value_data && + DWARFFormValue::IsDataForm(const_value_form.Form()); if (use_type_size_for_value && type_sp->GetType()) { DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); location->UpdateValue(const_value_form.Unsigned(),