diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 0f7100dfc94..9b61f19b072 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -13048,7 +13048,12 @@ ada_add_global_exceptions (compiled_regex *preg, }, NULL, SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK, - SEARCH_VAR_DOMAIN); + SEARCH_VAR_DOMAIN, + [&] (enum language lang) + { + /* Try to skip non-Ada CUs. */ + return lang == language_ada; + }); /* Iterate over all objfiles irrespective of scope or linker namespaces so we get all exceptions anywhere in the progspace. */ diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h index 802e8567d09..0873e7dce1d 100644 --- a/gdb/dwarf2/cooked-index.h +++ b/gdb/dwarf2/cooked-index.h @@ -778,7 +778,9 @@ struct cooked_index_functions : public dwarf2_base_index_functions gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) override; + domain_search_flags domain, + gdb::function_view lang_matcher) + override; struct compunit_symtab *find_pc_sect_compunit_symtab (struct objfile *objfile, bound_minimal_symbol msymbol, diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c index 8cd665cee37..701cdecf392 100644 --- a/gdb/dwarf2/read-gdb-index.c +++ b/gdb/dwarf2/read-gdb-index.c @@ -158,7 +158,9 @@ struct dwarf2_gdb_index : public dwarf2_base_index_functions gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) override; + domain_search_flags domain, + gdb::function_view lang_matcher) + override; }; /* This dumps minimal information about the index. @@ -187,7 +189,8 @@ dw2_expand_marked_cus gdb::function_view file_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags kind) + domain_search_flags kind, + gdb::function_view lang_matcher) { offset_type vec_len, vec_idx; bool global_seen = false; @@ -268,7 +271,7 @@ dw2_expand_marked_cus dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index); if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, - expansion_notify)) + expansion_notify, lang_matcher)) return false; } @@ -283,7 +286,8 @@ dwarf2_gdb_index::expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) + domain_search_flags domain, + gdb::function_view lang_matcher) { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); @@ -300,7 +304,8 @@ dwarf2_gdb_index::expand_symtabs_matching if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, - expansion_notify)) + expansion_notify, + lang_matcher)) return false; } return true; @@ -316,10 +321,11 @@ dwarf2_gdb_index::expand_symtabs_matching [&] (offset_type idx) { if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher, - expansion_notify, search_flags, domain)) + expansion_notify, search_flags, domain, + lang_matcher)) return false; return true; - }, per_objfile); + }, per_objfile, lang_matcher); return result; } diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index bbd6bfbaf45..ca27391a6f5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -1644,7 +1644,9 @@ struct readnow_functions : public dwarf2_base_index_functions gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) override + domain_search_flags domain, + gdb::function_view lang_matcher) + override { return true; } @@ -2296,7 +2298,8 @@ dw2_expand_symtabs_matching_symbol const lookup_name_info &lookup_name_in, gdb::function_view symbol_matcher, gdb::function_view match_callback, - dwarf2_per_objfile *per_objfile) + dwarf2_per_objfile *per_objfile, + gdb::function_view lang_matcher) { lookup_name_info lookup_name_without_params = lookup_name_in.make_ignore_params (); @@ -2332,6 +2335,8 @@ dw2_expand_symtabs_matching_symbol for (int i = 0; i < nr_languages; i++) { enum language lang_e = (enum language) i; + if (lang_matcher != nullptr && !lang_matcher (lang_e)) + continue; const language_defn *lang = language_def (lang_e); symbol_name_matcher_ftype *name_matcher @@ -2489,7 +2494,7 @@ check_match (const char *file, int line, if (expected_str == NULL || strcmp (expected_str, matched_name) != 0) mismatch (expected_str, matched_name); return true; - }, per_objfile); + }, per_objfile, nullptr); const char *expected_str = expected_it == expected_end ? NULL : *expected_it++; @@ -2850,19 +2855,29 @@ dw2_expand_symtabs_matching_one (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, gdb::function_view file_matcher, - gdb::function_view expansion_notify) + gdb::function_view expansion_notify, + gdb::function_view lang_matcher) { - if (file_matcher == NULL || per_cu->mark) + if (file_matcher != nullptr && !per_cu->mark) + return true; + + if (lang_matcher != nullptr) { - bool symtab_was_null = !per_objfile->symtab_set_p (per_cu); - - compunit_symtab *symtab - = dw2_instantiate_symtab (per_cu, per_objfile, false); - gdb_assert (symtab != nullptr); - - if (expansion_notify != NULL && symtab_was_null) - return expansion_notify (symtab); + /* Try to skip CUs with non-matching language. */ + per_cu->ensure_lang (per_objfile); + if (!per_cu->maybe_multi_language () + && !lang_matcher (per_cu->lang ())) + return true; } + + bool symtab_was_null = !per_objfile->symtab_set_p (per_cu); + compunit_symtab *symtab + = dw2_instantiate_symtab (per_cu, per_objfile, false); + gdb_assert (symtab != nullptr); + + if (expansion_notify != NULL && symtab_was_null) + return expansion_notify (symtab); + return true; } @@ -16619,7 +16634,8 @@ cooked_index_functions::expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) + domain_search_flags domain, + gdb::function_view lang_matcher) { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); @@ -16638,7 +16654,8 @@ cooked_index_functions::expand_symtabs_matching if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, - expansion_notify)) + expansion_notify, + lang_matcher)) return false; } return true; @@ -16663,8 +16680,42 @@ cooked_index_functions::expand_symtabs_matching symbol_name_match_type match_type = lookup_name_without_params.match_type (); + std::bitset unique_styles_used; + if (lang_matcher != nullptr) + for (unsigned iter = 0; iter < nr_languages; ++iter) + { + enum language lang = (enum language) iter; + if (!lang_matcher (lang)) + continue; + + switch (lang) + { + case language_cplus: + case language_rust: + unique_styles_used[language_cplus] = true; + break; + case language_d: + case language_go: + unique_styles_used[language_d] = true; + break; + case language_ada: + unique_styles_used[language_ada] = true; + break; + default: + unique_styles_used[language_c] = true; + } + + if (unique_styles_used.count () + == sizeof (unique_styles) / sizeof (unique_styles[0])) + break; + } + for (enum language lang : unique_styles) { + if (lang_matcher != nullptr + && !unique_styles_used.test (lang)) + continue; + std::vector name_vec = lookup_name_without_params.split_name (lang); std::vector name_str_vec (name_vec.begin (), name_vec.end ()); @@ -16695,6 +16746,15 @@ cooked_index_functions::expand_symtabs_matching || !entry->matches (domain)) continue; + if (lang_matcher != nullptr) + { + /* Try to skip CUs with non-matching language. */ + entry->per_cu->ensure_lang (per_objfile); + if (!entry->per_cu->maybe_multi_language () + && !lang_matcher (entry->per_cu->lang ())) + continue; + } + /* We've found the base name of the symbol; now walk its parentage chain, ensuring that each component matches. */ @@ -16763,7 +16823,7 @@ cooked_index_functions::expand_symtabs_matching if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile, file_matcher, - expansion_notify)) + expansion_notify, nullptr)) return false; } } @@ -21463,6 +21523,24 @@ dwarf2_per_cu_data::set_lang (enum language lang, gdb_assert (old_dw == 0 || old_dw == dw_lang); } +/* See read.h. */ + +void +dwarf2_per_cu_data::ensure_lang (dwarf2_per_objfile *per_objfile) +{ + if (lang (false) != language_unknown) + return; + + cutu_reader reader (this, per_objfile); + if (reader.dummy_p) + { + set_lang (language_minimal, (dwarf_source_language)0); + return; + } + + prepare_one_comp_unit (reader.cu, reader.comp_unit_die, language_minimal); +} + /* A helper function for dwarf2_find_containing_comp_unit that returns the index of the result, and that searches a vector. It will return a result even if the offset in question does not actually @@ -21626,6 +21704,14 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, cu->language_defn = language_def (lang); + /* Initialize the lto_artificial field. */ + attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu); + if (attr != nullptr + && cu->producer != nullptr + && strcmp (attr->as_string (), "") == 0 + && producer_is_gcc (cu->producer, nullptr, nullptr)) + cu->per_cu->lto_artificial = true; + switch (comp_unit_die->tag) { case DW_TAG_compile_unit: diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index b23972b7a4e..7c42017c3d6 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -102,6 +102,7 @@ struct dwarf2_per_cu_data is_dwz (false), reading_dwo_directly (false), tu_read (false), + lto_artificial (false), queued (false), m_header_read_in (false), mark (false), @@ -148,6 +149,11 @@ public: This flag is only valid if is_debug_types is true. */ unsigned int tu_read : 1; + /* Non-zero if the CU is produced by GCC and has name "". GCC + uses this to indicate that the CU does not correspond to a single source + file. GCC produces this type of CU during LTO. */ + unsigned int lto_artificial : 1; + /* Wrap the following in struct packed instead of bitfields to avoid data races when the bitfields end up on the same memory location (per C++ memory model). */ @@ -324,6 +330,9 @@ public: return l; } + /* Make sure that m_lang != language_unknown. */ + void ensure_lang (dwarf2_per_objfile *per_objfile); + /* Return the language of this CU, as a DWARF DW_LANG_* value. This may be 0 in some situations. */ dwarf_source_language dw_lang () const @@ -335,6 +344,22 @@ public: situation LANG would be set by the importing CU. */ void set_lang (enum language lang, dwarf_source_language dw_lang); + /* Return true if the CU may be a multi-language CU. */ + + bool maybe_multi_language () const + { + enum language lang = this->lang (); + + if (!lto_artificial) + /* Assume multi-language CUs are generated only by GCC LTO. */ + return false; + + /* If GCC mixes different languages in an artificial LTO CU, it labels it C. + The exception to this is when it mixes C and C++, which it labels it C++. + For now, we don't consider the latter a multi-language CU. */ + return lang == language_c; + } + /* Free any cached file names. */ void free_cached_file_names (); }; @@ -867,7 +892,8 @@ extern bool dw2_expand_symtabs_matching_one (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, gdb::function_view file_matcher, - gdb::function_view expansion_notify); + gdb::function_view expansion_notify, + gdb::function_view lang_matcher); /* Helper for dw2_expand_symtabs_matching that works with a mapped_index_base instead of the containing objfile. This is split @@ -881,7 +907,8 @@ extern bool dw2_expand_symtabs_matching_symbol const lookup_name_info &lookup_name_in, gdb::function_view symbol_matcher, gdb::function_view match_callback, - dwarf2_per_objfile *per_objfile); + dwarf2_per_objfile *per_objfile, + gdb::function_view lang_matcher); /* If FILE_MATCHER is non-NULL, set all the dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 8b1e89cfe64..d92570a00bd 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -597,7 +597,9 @@ public: gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain); + domain_search_flags domain, + gdb::function_view lang_matcher + = nullptr); /* See quick_symbol_functions. */ struct compunit_symtab * diff --git a/gdb/psymtab.c b/gdb/psymtab.c index e25c3ab33ec..f8c83d9b17f 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -893,7 +893,9 @@ psymbol_functions::expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) + domain_search_flags domain, + gdb::function_view + lang_matcher ATTRIBUTE_UNUSED) { /* Clear the search flags. */ for (partial_symtab *ps : partial_symbols (objfile)) diff --git a/gdb/psymtab.h b/gdb/psymtab.h index a81526cddee..b23aadbf26a 100644 --- a/gdb/psymtab.h +++ b/gdb/psymtab.h @@ -633,7 +633,9 @@ struct psymbol_functions : public quick_symbol_functions gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags kind) override; + domain_search_flags kind, + gdb::function_view lang_matcher) + override; struct compunit_symtab *find_pc_sect_compunit_symtab (struct objfile *objfile, bound_minimal_symbol msymbol, CORE_ADDR pc, diff --git a/gdb/quick-symbol.h b/gdb/quick-symbol.h index d6de7340065..0d76e1860ed 100644 --- a/gdb/quick-symbol.h +++ b/gdb/quick-symbol.h @@ -46,6 +46,11 @@ typedef bool (expand_symtabs_file_matcher_ftype) (const char *filename, typedef bool (expand_symtabs_symbol_matcher_ftype) (const char *name); +/* Callback for quick_symbol_functions->expand_symtabs_matching + to match a language. */ + +typedef bool (expand_symtabs_lang_matcher_ftype) (enum language lang); + /* Callback for quick_symbol_functions->expand_symtabs_matching to be called after a symtab has been expanded. If this returns true, more symtabs are checked; if it returns false, iteration @@ -122,6 +127,10 @@ struct quick_symbol_functions /* Expand all symbol tables in OBJFILE matching some criteria. + If LANG_MATCHER returns false, expansion of the symbol table may be + skipped. It may also not be skipped, which the caller needs to take into + account. + FILE_MATCHER is called for each file in OBJFILE. The file name is passed to it. If the matcher returns false, the file is skipped. If FILE_MATCHER is NULL the file is not skipped. If @@ -154,7 +163,9 @@ struct quick_symbol_functions gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) = 0; + domain_search_flags domain, + gdb::function_view lang_matcher + = nullptr) = 0; /* Return the comp unit from OBJFILE that contains PC and SECTION. Return NULL if there is no such compunit. This diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c index 0eccda21f39..6bf8dc3cd82 100644 --- a/gdb/symfile-debug.c +++ b/gdb/symfile-debug.c @@ -376,7 +376,8 @@ objfile::expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) + domain_search_flags domain, + gdb::function_view lang_matcher) { /* This invariant is documented in quick-functions.h. */ gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); @@ -393,7 +394,8 @@ objfile::expand_symtabs_matching for (const auto &iter : qf) if (!iter->expand_symtabs_matching (this, file_matcher, lookup_name, symbol_matcher, expansion_notify, - search_flags, domain)) + search_flags, domain, + lang_matcher)) return false; return true; } diff --git a/gdb/symfile.c b/gdb/symfile.c index 2292ecaf344..1502fdbe500 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -3759,7 +3759,8 @@ expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags domain) + domain_search_flags domain, + gdb::function_view lang_matcher) { for (objfile *objfile : current_program_space->objfiles ()) if (!objfile->expand_symtabs_matching (file_matcher, @@ -3767,7 +3768,8 @@ expand_symtabs_matching symbol_matcher, expansion_notify, search_flags, - domain)) + domain, + lang_matcher)) return false; return true; } diff --git a/gdb/symfile.h b/gdb/symfile.h index 508ba48d161..74187c82f97 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -352,7 +352,9 @@ bool expand_symtabs_matching gdb::function_view symbol_matcher, gdb::function_view expansion_notify, block_search_flags search_flags, - domain_search_flags kind); + domain_search_flags kind, + gdb::function_view lang_matcher + = nullptr); void map_symbol_filenames (gdb::function_view fun, bool need_fullname);