aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp399
1 files changed, 201 insertions, 198 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 2d1db66e7fd9..188a667ca564 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -209,11 +209,12 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));
SymbolFileDWARF *dwarf = die.GetDWARF();
- TypeSP type_sp(new Type(
- die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(),
- nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
- &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward,
- TypePayloadClang(GetOwningClangModule(die))));
+ TypeSP type_sp(new Type(die.GetID(), dwarf, pcm_type_sp->GetName(),
+ pcm_type_sp->GetByteSize(nullptr), nullptr,
+ LLDB_INVALID_UID, Type::eEncodingInvalid,
+ &pcm_type_sp->GetDeclaration(), type,
+ Type::ResolveState::Forward,
+ TypePayloadClang(GetOwningClangModule(die))));
dwarf->GetTypeList().Insert(type_sp);
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
@@ -229,31 +230,73 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
return type_sp;
}
-static void CompleteExternalTagDeclType(TypeSystemClang &ast,
- ClangASTImporter &ast_importer,
- clang::DeclContext *decl_ctx,
- DWARFDIE die,
- const char *type_name_cstr) {
+static void ForcefullyCompleteType(CompilerType type) {
+ bool started = TypeSystemClang::StartTagDeclarationDefinition(type);
+ lldbassert(started && "Unable to start a class type definition.");
+ TypeSystemClang::CompleteTagDeclarationDefinition(type);
+ const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type);
+ auto &ts = llvm::cast<TypeSystemClang>(*type.GetTypeSystem());
+ ts.GetMetadata(td)->SetIsForcefullyCompleted();
+}
+
+/// Complete a type from debug info, or mark it as forcefully completed if
+/// there is no definition of the type in the current Module. Call this function
+/// in contexts where the usual C++ rules require a type to be complete (base
+/// class, member, etc.).
+static void RequireCompleteType(CompilerType type) {
+ // Technically, enums can be incomplete too, but we don't handle those as they
+ // are emitted even under -flimit-debug-info.
+ if (!TypeSystemClang::IsCXXClassType(type))
+ return;
+
+ if (type.GetCompleteType())
+ return;
+
+ // No complete definition in this module. Mark the class as complete to
+ // satisfy local ast invariants, but make a note of the fact that
+ // it is not _really_ complete so we can later search for a definition in a
+ // different module.
+ // Since we provide layout assistance, layouts of types containing this class
+ // will be correct even if we are not able to find the definition elsewhere.
+ ForcefullyCompleteType(type);
+}
+
+/// This function serves a similar purpose as RequireCompleteType above, but it
+/// avoids completing the type if it is not immediately necessary. It only
+/// ensures we _can_ complete the type later.
+static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
+ ClangASTImporter &ast_importer,
+ clang::DeclContext *decl_ctx,
+ DWARFDIE die,
+ const char *type_name_cstr) {
auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
if (!tag_decl_ctx)
+ return; // Non-tag context are always ready.
+
+ // We have already completed the type, or we have found its definition and are
+ // ready to complete it later (cf. ParseStructureLikeDIE).
+ if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
return;
+ // We reach this point of the tag was present in the debug info as a
+ // declaration only. If it was imported from another AST context (in the
+ // gmodules case), we can complete the type by doing a full import.
+
// If this type was not imported from an external AST, there's nothing to do.
CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
- if (!type || !ast_importer.CanImport(type))
- return;
-
- auto qual_type = ClangUtil::GetQualType(type);
- if (!ast_importer.RequireCompleteType(qual_type)) {
+ if (type && ast_importer.CanImport(type)) {
+ auto qual_type = ClangUtil::GetQualType(type);
+ if (ast_importer.RequireCompleteType(qual_type))
+ return;
die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
"Unable to complete the Decl context for DIE '%s' at offset "
"0x%8.8x.\nPlease file a bug report.",
type_name_cstr ? type_name_cstr : "", die.GetOffset());
- // We need to make the type look complete otherwise, we might crash in
- // Clang when adding children.
- if (TypeSystemClang::StartTagDeclarationDefinition(type))
- TypeSystemClang::CompleteTagDeclarationDefinition(type);
}
+
+ // We don't have a type definition and/or the import failed. We must
+ // forcefully complete the type to avoid crashes.
+ ForcefullyCompleteType(type);
}
ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
@@ -298,7 +341,9 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
break;
case DW_AT_decl_file:
- decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned()));
+ // die.GetCU() can differ if DW_AT_specification uses DW_FORM_ref_addr.
+ decl.SetFile(
+ attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
break;
case DW_AT_decl_line:
decl.SetLine(form_value.Unsigned());
@@ -513,42 +558,51 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
TypeSP type_sp;
CompilerType clang_type;
- if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
- // Try to parse a typedef from the (DWARF embedded in the) Clang
- // module file first as modules can contain typedef'ed
- // structures that have no names like:
- //
- // typedef struct { int a; } Foo;
- //
- // In this case we will have a structure with no name and a
- // typedef named "Foo" that points to this unnamed
- // structure. The name in the typedef is the only identifier for
- // the struct, so always try to get typedefs from Clang modules
- // if possible.
- //
- // The type_sp returned will be empty if the typedef doesn't
- // exist in a module file, so it is cheap to call this function
- // just to check.
- //
- // If we don't do this we end up creating a TypeSP that says
- // this is a typedef to type 0x123 (the DW_AT_type value would
- // be 0x123 in the DW_TAG_typedef), and this is the unnamed
- // structure type. We will have a hard time tracking down an
- // unnammed structure type in the module debug info, so we make
- // sure we don't get into this situation by always resolving
- // typedefs from the module.
- const DWARFDIE encoding_die = attrs.type.Reference();
+ if (tag == DW_TAG_typedef) {
+ // DeclContext will be populated when the clang type is materialized in
+ // Type::ResolveCompilerType.
+ PrepareContextToReceiveMembers(
+ m_ast, GetClangASTImporter(),
+ GetClangDeclContextContainingDIE(die, nullptr), die,
+ attrs.name.GetCString());
- // First make sure that the die that this is typedef'ed to _is_
- // just a declaration (DW_AT_declaration == 1), not a full
- // definition since template types can't be represented in
- // modules since only concrete instances of templates are ever
- // emitted and modules won't contain those
- if (encoding_die &&
- encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
- type_sp = ParseTypeFromClangModule(sc, die, log);
- if (type_sp)
- return type_sp;
+ if (attrs.type.IsValid()) {
+ // Try to parse a typedef from the (DWARF embedded in the) Clang
+ // module file first as modules can contain typedef'ed
+ // structures that have no names like:
+ //
+ // typedef struct { int a; } Foo;
+ //
+ // In this case we will have a structure with no name and a
+ // typedef named "Foo" that points to this unnamed
+ // structure. The name in the typedef is the only identifier for
+ // the struct, so always try to get typedefs from Clang modules
+ // if possible.
+ //
+ // The type_sp returned will be empty if the typedef doesn't
+ // exist in a module file, so it is cheap to call this function
+ // just to check.
+ //
+ // If we don't do this we end up creating a TypeSP that says
+ // this is a typedef to type 0x123 (the DW_AT_type value would
+ // be 0x123 in the DW_TAG_typedef), and this is the unnamed
+ // structure type. We will have a hard time tracking down an
+ // unnammed structure type in the module debug info, so we make
+ // sure we don't get into this situation by always resolving
+ // typedefs from the module.
+ const DWARFDIE encoding_die = attrs.type.Reference();
+
+ // First make sure that the die that this is typedef'ed to _is_
+ // just a declaration (DW_AT_declaration == 1), not a full
+ // definition since template types can't be represented in
+ // modules since only concrete instances of templates are ever
+ // emitted and modules won't contain those
+ if (encoding_die &&
+ encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
+ type_sp = ParseTypeFromClangModule(sc, die, log);
+ if (type_sp)
+ return type_sp;
+ }
}
}
@@ -810,7 +864,7 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
bool is_signed = false;
enumerator_clang_type.IsIntegerType(is_signed);
ParseChildEnumerators(clang_type, is_signed,
- type_sp->GetByteSize().getValueOr(0), die);
+ type_sp->GetByteSize(nullptr).getValueOr(0), die);
}
TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
} else {
@@ -1172,7 +1226,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
}
if (!function_decl) {
- const char *name = attrs.name.GetCString();
+ llvm::StringRef name = attrs.name.GetStringRef();
// We currently generate function templates with template parameters in
// their name. In order to get closer to the AST that clang generates
@@ -1196,12 +1250,12 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
template_function_decl = m_ast.CreateFunctionDeclaration(
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
- GetOwningClangModule(die), attrs.name.GetCString(), clang_type,
+ GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type,
attrs.storage, attrs.is_inline);
clang::FunctionTemplateDecl *func_template_decl =
m_ast.CreateFunctionTemplateDecl(
containing_decl_ctx, GetOwningClangModule(die),
- template_function_decl, name, template_param_infos);
+ template_function_decl, template_param_infos);
m_ast.CreateFunctionTemplateSpecializationInfo(
template_function_decl, func_template_decl, template_param_infos);
}
@@ -1261,9 +1315,9 @@ TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,
attrs.bit_stride = array_info->bit_stride;
}
if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
- attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
+ attrs.byte_stride = element_type->GetByteSize(nullptr).getValueOr(0);
CompilerType array_element_type = element_type->GetForwardCompilerType();
- CompleteType(array_element_type);
+ RequireCompleteType(array_element_type);
uint64_t array_element_bit_stride =
attrs.byte_stride * 8 + attrs.bit_stride;
@@ -1318,28 +1372,6 @@ TypeSP DWARFASTParserClang::ParsePointerToMemberType(
return nullptr;
}
-void DWARFASTParserClang::CompleteType(CompilerType type) {
- // Technically, enums can be incomplete too, but we don't handle those as they
- // are emitted even under -flimit-debug-info.
- if (!TypeSystemClang::IsCXXClassType(type))
- return;
-
- if (type.GetCompleteType())
- return;
-
- // No complete definition in this module. Mark the class as complete to
- // satisfy local ast invariants, but make a note of the fact that
- // it is not _really_ complete so we can later search for a definition in a
- // different module.
- // Since we provide layout assistance, layouts of types containing this class
- // will be correct even if we are not able to find the definition elsewhere.
- bool started = TypeSystemClang::StartTagDeclarationDefinition(type);
- lldbassert(started && "Unable to start a class type definition.");
- TypeSystemClang::CompleteTagDeclarationDefinition(type);
- const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type);
- m_ast.GetMetadata(td)->SetIsForcefullyCompleted();
-}
-
TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
if (!type_sp)
@@ -1559,13 +1591,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
- // If your decl context is a record that was imported from another
- // AST context (in the gmodules case), we need to make sure the type
- // backing the Decl is complete before adding children to it. This is
- // not an issue in the non-gmodules case because the debug info will
- // always contain a full definition of parent types in that case.
- CompleteExternalTagDeclType(m_ast, GetClangASTImporter(), decl_ctx, die,
- attrs.name.GetCString());
+ PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die,
+ attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
// Check the decl context that contains this class/struct/union. If
@@ -1640,33 +1667,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
*unique_ast_entry_up);
- if (attrs.is_forward_declaration && die.HasChildren()) {
- // Check to see if the DIE actually has a definition, some version of
- // GCC will
- // emit DIEs with DW_AT_declaration set to true, but yet still have
- // subprogram, members, or inheritance, so we can't trust it
- DWARFDIE child_die = die.GetFirstChild();
- while (child_die) {
- switch (child_die.Tag()) {
- case DW_TAG_inheritance:
- case DW_TAG_subprogram:
- case DW_TAG_member:
- case DW_TAG_APPLE_property:
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- child_die.Clear();
- attrs.is_forward_declaration = false;
- break;
- default:
- child_die = child_die.GetSibling();
- break;
- }
- }
- }
-
if (!attrs.is_forward_declaration) {
// Always start the definition for a class type so that if the class
// has child classes or types that require the class to be created
@@ -1944,8 +1944,6 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
break;
}
}
- if (template_param_infos.args.empty())
- return false;
return template_param_infos.args.size() == template_param_infos.names.size();
}
@@ -2042,7 +2040,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
clang::TypeSourceInfo *type_source_info =
base_class->getTypeSourceInfo();
if (type_source_info)
- CompleteType(m_ast.GetType(type_source_info->getType()));
+ RequireCompleteType(m_ast.GetType(type_source_info->getType()));
}
m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
@@ -2057,7 +2055,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() ||
!layout_info.vbase_offsets.empty()) {
if (type)
- layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
+ layout_info.bit_size = type->GetByteSize(nullptr).getValueOr(0) * 8;
if (layout_info.bit_size == 0)
layout_info.bit_size =
die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
@@ -2079,7 +2077,7 @@ bool DWARFASTParserClang::CompleteEnumType(const DWARFDIE &die,
bool is_signed = false;
clang_type.IsIntegerType(is_signed);
ParseChildEnumerators(clang_type, is_signed,
- type->GetByteSize().getValueOr(0), die);
+ type->GetByteSize(nullptr).getValueOr(0), die);
}
TypeSystemClang::CompleteTagDeclarationDefinition(clang_type);
}
@@ -2567,7 +2565,7 @@ void DWARFASTParserClang::ParseSingleMember(
this_field_info.bit_offset = data_bit_offset;
} else {
if (!byte_size)
- byte_size = member_type->GetByteSize();
+ byte_size = member_type->GetByteSize(nullptr);
ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
if (objfile->GetByteOrder() == eByteOrderLittle) {
@@ -2578,10 +2576,18 @@ void DWARFASTParserClang::ParseSingleMember(
}
}
- if ((this_field_info.bit_offset >= parent_bit_size) ||
- (last_field_info.IsBitfield() &&
- !last_field_info.NextBitfieldOffsetIsValid(
- this_field_info.bit_offset))) {
+ // The ObjC runtime knows the byte offset but we still need to provide
+ // the bit-offset in the layout. It just means something different then
+ // what it does in C and C++. So we skip this check for ObjC types.
+ //
+ // We also skip this for fields of a union since they will all have a
+ // zero offset.
+ if (!TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type) &&
+ !(parent_die.Tag() == DW_TAG_union_type && this_field_info.bit_offset == 0) &&
+ ((this_field_info.bit_offset >= parent_bit_size) ||
+ (last_field_info.IsBitfield() &&
+ !last_field_info.NextBitfieldOffsetIsValid(
+ this_field_info.bit_offset)))) {
ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
objfile->GetModule()->ReportWarning(
"0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
@@ -2707,7 +2713,7 @@ void DWARFASTParserClang::ParseSingleMember(
}
}
- CompleteType(member_clang_type);
+ RequireCompleteType(member_clang_type);
field_decl = TypeSystemClang::AddFieldToRecordType(
class_clang_type, name, member_clang_type, accessibility,
@@ -3043,88 +3049,85 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die,
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
const dw_tag_t tag = die.Tag();
- switch (tag) {
- case DW_TAG_subrange_type: {
- DWARFAttributes attributes;
- const size_t num_child_attributes = die.GetAttributes(attributes);
- if (num_child_attributes > 0) {
- uint64_t num_elements = 0;
- uint64_t lower_bound = 0;
- uint64_t upper_bound = 0;
- bool upper_bound_valid = false;
- uint32_t i;
- for (i = 0; i < num_child_attributes; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- break;
+ if (tag != DW_TAG_subrange_type)
+ continue;
- case DW_AT_count:
- if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
- if (var_die.Tag() == DW_TAG_variable)
- if (exe_ctx) {
- if (auto frame = exe_ctx->GetFrameSP()) {
- Status error;
- lldb::VariableSP var_sp;
- auto valobj_sp = frame->GetValueForVariableExpressionPath(
- var_die.GetName(), eNoDynamicValues, 0, var_sp,
- error);
- if (valobj_sp) {
- num_elements = valobj_sp->GetValueAsUnsigned(0);
- break;
- }
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0) {
+ uint64_t num_elements = 0;
+ uint64_t lower_bound = 0;
+ uint64_t upper_bound = 0;
+ bool upper_bound_valid = false;
+ uint32_t i;
+ for (i = 0; i < num_child_attributes; ++i) {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ switch (attr) {
+ case DW_AT_name:
+ break;
+
+ case DW_AT_count:
+ if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
+ if (var_die.Tag() == DW_TAG_variable)
+ if (exe_ctx) {
+ if (auto frame = exe_ctx->GetFrameSP()) {
+ Status error;
+ lldb::VariableSP var_sp;
+ auto valobj_sp = frame->GetValueForVariableExpressionPath(
+ var_die.GetName(), eNoDynamicValues, 0, var_sp,
+ error);
+ if (valobj_sp) {
+ num_elements = valobj_sp->GetValueAsUnsigned(0);
+ break;
}
}
- } else
- num_elements = form_value.Unsigned();
- break;
+ }
+ } else
+ num_elements = form_value.Unsigned();
+ break;
- case DW_AT_bit_stride:
- array_info.bit_stride = form_value.Unsigned();
- break;
+ case DW_AT_bit_stride:
+ array_info.bit_stride = form_value.Unsigned();
+ break;
- case DW_AT_byte_stride:
- array_info.byte_stride = form_value.Unsigned();
- break;
+ case DW_AT_byte_stride:
+ array_info.byte_stride = form_value.Unsigned();
+ break;
- case DW_AT_lower_bound:
- lower_bound = form_value.Unsigned();
- break;
+ case DW_AT_lower_bound:
+ lower_bound = form_value.Unsigned();
+ break;
- case DW_AT_upper_bound:
- upper_bound_valid = true;
- upper_bound = form_value.Unsigned();
- break;
+ case DW_AT_upper_bound:
+ upper_bound_valid = true;
+ upper_bound = form_value.Unsigned();
+ break;
- default:
- case DW_AT_abstract_origin:
- case DW_AT_accessibility:
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_sibling:
- case DW_AT_threads_scaled:
- case DW_AT_type:
- case DW_AT_visibility:
- break;
- }
+ default:
+ case DW_AT_abstract_origin:
+ case DW_AT_accessibility:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_sibling:
+ case DW_AT_threads_scaled:
+ case DW_AT_type:
+ case DW_AT_visibility:
+ break;
}
}
+ }
- if (num_elements == 0) {
- if (upper_bound_valid && upper_bound >= lower_bound)
- num_elements = upper_bound - lower_bound + 1;
- }
-
- array_info.element_orders.push_back(num_elements);
+ if (num_elements == 0) {
+ if (upper_bound_valid && upper_bound >= lower_bound)
+ num_elements = upper_bound - lower_bound + 1;
}
- } break;
- default:
- break;
+
+ array_info.element_orders.push_back(num_elements);
}
}
return array_info;