diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 332 |
1 files changed, 141 insertions, 191 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index d4cc26a3c329..505ea29ca4d4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -132,6 +132,11 @@ public: } // namespace +bool IsStructOrClassTag(llvm::dwarf::Tag Tag) { + return Tag == llvm::dwarf::Tag::DW_TAG_class_type || + Tag == llvm::dwarf::Tag::DW_TAG_structure_type; +} + static PluginProperties &GetGlobalPluginProperties() { static PluginProperties g_settings; return g_settings; @@ -1977,7 +1982,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // (corresponding to .dwo) so we simply skip it. if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" && llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath()) - .endswith(dwo_module_spec.GetFileSpec().GetPath())) { + .ends_with(dwo_module_spec.GetFileSpec().GetPath())) { continue; } @@ -2591,177 +2596,157 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -void SymbolFileDWARF::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - Log *log = GetLog(DWARFLog::Lookups); +/// Split a name up into a basename and template parameters. +static bool SplitTemplateParams(llvm::StringRef fullname, + llvm::StringRef &basename, + llvm::StringRef &template_params) { + auto it = fullname.find('<'); + if (it == llvm::StringRef::npos) { + basename = fullname; + template_params = llvm::StringRef(); + return false; + } + basename = fullname.slice(0, it); + template_params = fullname.slice(it, fullname.size()); + return true; +} - if (log) { - if (parent_decl_ctx) - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "{1:p} (\"{2}\"), max_matches={3}, type_list)", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches); - else - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "NULL, max_matches={1}, type_list)", - name.GetCString(), max_matches); +static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) { + // We need to find any names in the context that have template parameters + // and strip them so the context can be matched when -gsimple-template-names + // is being used. Returns true if any of the context items were updated. + bool any_context_updated = false; + for (auto &context : match.GetContextRef()) { + llvm::StringRef basename, params; + if (SplitTemplateParams(context.name.GetStringRef(), basename, params)) { + context.name = ConstString(basename); + any_context_updated = true; + } } + return any_context_updated; +} +void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) return; - // Unlike FindFunctions(), FindTypes() following cannot produce false - // positives. - - const llvm::StringRef name_ref = name.GetStringRef(); - auto name_bracket_index = name_ref.find('<'); - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + bool have_index_match = false; + m_index->GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // With -gsimple-template-names, a templated type's DW_AT_name will not - // contain the template parameters. Make sure that if the original query - // didn't contain a '<', we filter out entries with template parameters. - if (name_bracket_index == llvm::StringRef::npos && - matching_type->IsTemplateType()) - return true; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + if (matching_type->IsTemplateType()) { + // We have to watch out for case where we lookup a type by basename and + // it matches a template with simple template names. Like looking up + // "Foo" and if we have simple template names then we will match + // "Foo<int>" and "Foo<double>" because all the DWARF has is "Foo" in + // the accelerator tables. The main case we see this in is when the + // expression parser is trying to parse "Foo<int>" and it will first do + // a lookup on just "Foo". We verify the type basename matches before + // inserting the type in the results. + auto CompilerTypeBasename = + matching_type->GetForwardCompilerType().GetTypeName(true); + if (CompilerTypeBasename != query.GetTypeBasename()) + return true; // Keep iterating over index types, basename mismatch. + } + have_index_match = true; + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; + // With -gsimple-template-names, a templated type's DW_AT_name will not // contain the template parameters. Try again stripping '<' and anything // after, filtering out entries with template parameters that don't match. - if (types.GetSize() < max_matches) { - if (name_bracket_index != llvm::StringRef::npos) { - const llvm::StringRef name_no_template_params = - name_ref.slice(0, name_bracket_index); - const llvm::StringRef template_params = - name_ref.slice(name_bracket_index, name_ref.size()); - m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match - - const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString(); - auto it = base_name.find('<'); - // If the candidate qualified name doesn't have '<', it doesn't have - // template params to compare. - if (it == llvm::StringRef::npos) - return true; - - // Filter out non-matching instantiations by comparing template params. - const llvm::StringRef base_name_template_params = - base_name.slice(it, base_name.size()); - - if (template_params != base_name_template_params) - return true; - - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + if (!have_index_match) { + // Create a type matcher with a compiler context that is tuned for + // -gsimple-template-names. We will use this for the index lookup and the + // context matching, but will use the original "match" to insert matches + // into if things match. The "match_simple" has a compiler context with + // all template parameters removed to allow the names and context to match. + // The UpdateCompilerContextForSimpleTemplateNames(...) will return true if + // it trims any context items down by removing template parameter names. + TypeQuery query_simple(query); + if (UpdateCompilerContextForSimpleTemplateNames(query_simple)) { + + // Copy our match's context and update the basename we are looking for + // so we can use this only to compare the context correctly. + m_index->GetTypes(query_simple.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query_simple.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. + + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + ConstString name = matching_type->GetQualifiedName(); + // We have found a type that still might not match due to template + // parameters. If we create a new TypeQuery that uses the new type's + // fully qualified name, we can find out if this type matches at all + // context levels. We can't use just the "match_simple" context + // because all template parameters were stripped off. The fully + // qualified name of the type will have the template parameters and + // will allow us to make sure it matches correctly. + TypeQuery die_query(name.GetStringRef(), + TypeQueryOptions::e_exact_match); + if (!query.ContextMatches(die_query.GetContextRef())) + return true; // Keep iterating over index types, context mismatch. + + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; } } // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. - if (types.GetSize() < max_matches) { - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) - sym_file->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); - } + UpdateExternalModuleListIfNeeded(); - if (log && types.GetSize()) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches, - types.GetSize()); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= NULL, max_matches={1}, type_list) => {2}", - name.GetCString(), max_matches, types.GetSize()); + for (const auto &pair : m_external_type_modules) { + if (ModuleSP external_module_sp = pair.second) { + external_module_sp->FindTypes(query, results); + if (results.Done(query)) + return; } } } -void SymbolFileDWARF::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (pattern.empty()) - return; - - ConstString name = pattern.back().name; - - if (!name) - return; - - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!languages[GetLanguageFamily(*die.GetCU())]) - return true; - - std::vector<CompilerContext> die_context = die.GetDeclContext(); - if (!contextMatches(die_context, pattern)) - return true; - - if (Type *matching_type = ResolveType(die, true, true)) { - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - } - return true; - }); - - // Next search through the reachable Clang modules. This only applies for - // DWARF objects compiled with -gmodules that haven't been processed by - // dsymutil. - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - external_module_sp->FindTypes(pattern, languages, searched_symbol_files, - types); -} - CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx, @@ -2947,29 +2932,18 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( m_index->GetCompleteObjCClass( type_name, must_be_implementation, [&](DWARFDIE type_die) { - bool try_resolving_type = false; - // Don't try and resolve the DIE we are looking for with the DIE // itself! - if (type_die != die) { - switch (type_die.Tag()) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - try_resolving_type = true; - break; - default: - break; - } - } - if (!try_resolving_type) + if (type_die == die || !IsStructOrClassTag(type_die.Tag())) return true; if (must_be_implementation && - type_die.Supports_DW_AT_APPLE_objc_complete_type()) - try_resolving_type = type_die.GetAttributeValueAsUnsigned( + type_die.Supports_DW_AT_APPLE_objc_complete_type()) { + const bool try_resolving_type = type_die.GetAttributeValueAsUnsigned( DW_AT_APPLE_objc_complete_type, 0); - if (!try_resolving_type) - return true; + if (!try_resolving_type) + return true; + } Type *resolved_type = ResolveType(type_die, false, true); if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) @@ -3128,36 +3102,12 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) { if (type_system && !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) return true; - bool try_resolving_type = false; - // Don't try and resolve the DIE we are looking for with the DIE - // itself! const dw_tag_t type_tag = type_die.Tag(); - // Make sure the tags match - if (type_tag == tag) { - // The tags match, lets try resolving this type - try_resolving_type = true; - } else { - // The tags don't match, but we need to watch our for a forward - // declaration for a struct and ("struct foo") ends up being a - // class ("class foo { ... };") or vice versa. - switch (type_tag) { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo - // { ... };" - try_resolving_type = (tag == DW_TAG_structure_type); - break; - case DW_TAG_structure_type: - // We had a "struct foo", see if we ended up with a "class foo - // { ... };" - try_resolving_type = (tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve using this type - // whose name matches.... - break; - } - } + // Resolve the type if both have the same tag or {class, struct} tags. + const bool try_resolving_type = + type_tag == tag || + (IsStructOrClassTag(type_tag) && IsStructOrClassTag(tag)); if (!try_resolving_type) { if (log) { |