X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsymtab.c;h=791ce11a7372c11583eec384b5d44bf13d4366ea;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=711f8ef196a784e2a0ba84c7210f9a6b8b560310;hpb=adce99fe6988c7d5543ef5b996acac57a117372b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/symtab.c b/gdb/symtab.c index 711f8ef196..791ce11a73 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1,6 +1,6 @@ /* Symbol table lookup for the GNU debugger, GDB. - Copyright (C) 1986-2019 Free Software Foundation, Inc. + Copyright (C) 1986-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -183,6 +183,16 @@ struct symbol_cache_slot } value; }; +/* Clear out SLOT. */ + +static void +symbol_cache_clear_slot (struct symbol_cache_slot *slot) +{ + if (slot->state == SYMBOL_SLOT_NOT_FOUND) + xfree (slot->value.not_found.name); + slot->state = SYMBOL_SLOT_UNUSED; +} + /* Symbols don't specify global vs static block. So keep them in separate caches. */ @@ -201,6 +211,19 @@ struct block_symbol_cache struct symbol_cache_slot symbols[1]; }; +/* Clear all slots of BSC and free BSC. */ + +static void +destroy_block_symbol_cache (struct block_symbol_cache *bsc) +{ + if (bsc != nullptr) + { + for (unsigned int i = 0; i < bsc->size; i++) + symbol_cache_clear_slot (&bsc->symbols[i]); + xfree (bsc); + } +} + /* The symbol cache. Searching for symbols in the static and global blocks over multiple objfiles @@ -217,8 +240,8 @@ struct symbol_cache ~symbol_cache () { - xfree (global_symbols); - xfree (static_symbols); + destroy_block_symbol_cache (global_symbols); + destroy_block_symbol_cache (static_symbols); } struct block_symbol_cache *global_symbols = nullptr; @@ -572,7 +595,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) struct fn_field *method = &f[signature_id]; const char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id); const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id); - const char *newname = TYPE_NAME (type); + const char *newname = type->name (); /* Does the form of physname indicate that it is the full mangled name of a constructor (not just the args)? */ @@ -644,44 +667,27 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) return (mangled_name); } -/* Set the demangled name of GSYMBOL to NAME. NAME must be already - correctly allocated. */ +/* See symtab.h. */ void -symbol_set_demangled_name (struct general_symbol_info *gsymbol, - const char *name, - struct obstack *obstack) +general_symbol_info::set_demangled_name (const char *name, + struct obstack *obstack) { - if (gsymbol->language == language_ada) + if (language () == language_ada) { if (name == NULL) { - gsymbol->ada_mangled = 0; - gsymbol->language_specific.obstack = obstack; + ada_mangled = 0; + language_specific.obstack = obstack; } else { - gsymbol->ada_mangled = 1; - gsymbol->language_specific.demangled_name = name; + ada_mangled = 1; + language_specific.demangled_name = name; } } else - gsymbol->language_specific.demangled_name = name; -} - -/* Return the demangled name of GSYMBOL. */ - -const char * -symbol_get_demangled_name (const struct general_symbol_info *gsymbol) -{ - if (gsymbol->language == language_ada) - { - if (!gsymbol->ada_mangled) - return NULL; - /* Fall through. */ - } - - return gsymbol->language_specific.demangled_name; + language_specific.demangled_name = name; } @@ -689,28 +695,26 @@ symbol_get_demangled_name (const struct general_symbol_info *gsymbol) depending upon the language for the symbol. */ void -symbol_set_language (struct general_symbol_info *gsymbol, - enum language language, - struct obstack *obstack) +general_symbol_info::set_language (enum language language, + struct obstack *obstack) { - gsymbol->language = language; - if (gsymbol->language == language_cplus - || gsymbol->language == language_d - || gsymbol->language == language_go - || gsymbol->language == language_objc - || gsymbol->language == language_fortran) + m_language = language; + if (language == language_cplus + || language == language_d + || language == language_go + || language == language_objc + || language == language_fortran) { - symbol_set_demangled_name (gsymbol, NULL, obstack); + set_demangled_name (NULL, obstack); } - else if (gsymbol->language == language_ada) + else if (language == language_ada) { - gdb_assert (gsymbol->ada_mangled == 0); - gsymbol->language_specific.obstack = obstack; + gdb_assert (ada_mangled == 0); + language_specific.obstack = obstack; } else { - memset (&gsymbol->language_specific, 0, - sizeof (gsymbol->language_specific)); + memset (&language_specific, 0, sizeof (language_specific)); } } @@ -787,27 +791,23 @@ create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd) free_demangled_name_entry, xcalloc, xfree)); } -/* Try to determine the demangled name for a symbol, based on the - language of that symbol. If the language is set to language_auto, - it will attempt to find any demangling algorithm that works and - then set the language appropriately. The returned name is allocated - by the demangler and should be xfree'd. */ +/* See symtab.h */ -static char * +char * symbol_find_demangled_name (struct general_symbol_info *gsymbol, const char *mangled) { char *demangled = NULL; int i; - if (gsymbol->language == language_unknown) - gsymbol->language = language_auto; + if (gsymbol->language () == language_unknown) + gsymbol->m_language = language_auto; - if (gsymbol->language != language_auto) + if (gsymbol->language () != language_auto) { - const struct language_defn *lang = language_def (gsymbol->language); + const struct language_defn *lang = language_def (gsymbol->language ()); - language_sniff_from_mangled_name (lang, mangled, &demangled); + lang->sniff_from_mangled_name (mangled, &demangled); return demangled; } @@ -816,9 +816,9 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol, enum language l = (enum language) i; const struct language_defn *lang = language_def (l); - if (language_sniff_from_mangled_name (lang, mangled, &demangled)) + if (lang->sniff_from_mangled_name (mangled, &demangled)) { - gsymbol->language = l; + gsymbol->m_language = l; return demangled; } } @@ -838,28 +838,24 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol, so the pointer can be discarded after calling this function. */ void -symbol_set_names (struct general_symbol_info *gsymbol, - gdb::string_view linkage_name, bool copy_name, - struct objfile_per_bfd_storage *per_bfd) +general_symbol_info::compute_and_set_names (gdb::string_view linkage_name, + bool copy_name, + objfile_per_bfd_storage *per_bfd, + gdb::optional hash) { struct demangled_name_entry **slot; - if (gsymbol->language == language_ada) + if (language () == language_ada) { /* In Ada, we do the symbol lookups using the mangled name, so we can save some space by not storing the demangled name. */ if (!copy_name) - gsymbol->name = linkage_name.data (); + m_name = linkage_name.data (); else - { - char *name = (char *) obstack_alloc (&per_bfd->storage_obstack, - linkage_name.length () + 1); - - memcpy (name, linkage_name.data (), linkage_name.length ()); - name[linkage_name.length ()] = '\0'; - gsymbol->name = name; - } - symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack); + m_name = obstack_strndup (&per_bfd->storage_obstack, + linkage_name.data (), + linkage_name.length ()); + set_demangled_name (NULL, &per_bfd->storage_obstack); return; } @@ -868,15 +864,27 @@ symbol_set_names (struct general_symbol_info *gsymbol, create_demangled_names_hash (per_bfd); struct demangled_name_entry entry (linkage_name); + if (!hash.has_value ()) + hash = hash_demangled_name_entry (&entry); slot = ((struct demangled_name_entry **) - htab_find_slot (per_bfd->demangled_names_hash.get (), - &entry, INSERT)); + htab_find_slot_with_hash (per_bfd->demangled_names_hash.get (), + &entry, *hash, INSERT)); + + /* The const_cast is safe because the only reason it is already + initialized is if we purposefully set it from a background + thread to avoid doing the work here. However, it is still + allocated from the heap and needs to be freed by us, just + like if we called symbol_find_demangled_name here. If this is + nullptr, we call symbol_find_demangled_name below, but we put + this smart pointer here to be sure that we don't leak this name. */ + gdb::unique_xmalloc_ptr demangled_name + (const_cast (language_specific.demangled_name)); /* If this name is not in the hash table, add it. */ if (*slot == NULL /* A C version of the symbol may have already snuck into the table. This happens to, e.g., main.init (__go_init_main). Cope. */ - || (gsymbol->language == language_go && (*slot)->demangled == nullptr)) + || (language () == language_go && (*slot)->demangled == nullptr)) { /* A 0-terminated copy of the linkage name. Callers must set COPY_NAME to true if the string might not be nullterminated. We have to make @@ -894,8 +902,9 @@ symbol_set_names (struct general_symbol_info *gsymbol, else linkage_name_copy = linkage_name; - gdb::unique_xmalloc_ptr demangled_name_ptr - (symbol_find_demangled_name (gsymbol, linkage_name_copy.data ())); + if (demangled_name.get () == nullptr) + demangled_name.reset + (symbol_find_demangled_name (this, linkage_name_copy.data ())); /* Suppose we have demangled_name==NULL, copy_name==0, and linkage_name_copy==linkage_name. In this case, we already have the @@ -929,19 +938,14 @@ symbol_set_names (struct general_symbol_info *gsymbol, new (*slot) demangled_name_entry (gdb::string_view (mangled_ptr, linkage_name.length ())); } - (*slot)->demangled = std::move (demangled_name_ptr); - (*slot)->language = gsymbol->language; + (*slot)->demangled = std::move (demangled_name); + (*slot)->language = language (); } - else if (gsymbol->language == language_unknown - || gsymbol->language == language_auto) - gsymbol->language = (*slot)->language; + else if (language () == language_unknown || language () == language_auto) + m_language = (*slot)->language; - gsymbol->name = (*slot)->mangled.data (); - if ((*slot)->demangled != nullptr) - symbol_set_demangled_name (gsymbol, (*slot)->demangled.get (), - &per_bfd->storage_obstack); - else - symbol_set_demangled_name (gsymbol, NULL, &per_bfd->storage_obstack); + m_name = (*slot)->mangled.data (); + set_demangled_name ((*slot)->demangled.get (), &per_bfd->storage_obstack); } /* See symtab.h. */ @@ -949,22 +953,23 @@ symbol_set_names (struct general_symbol_info *gsymbol, const char * general_symbol_info::natural_name () const { - switch (language) + switch (language ()) { case language_cplus: case language_d: case language_go: case language_objc: case language_fortran: - if (symbol_get_demangled_name (this) != NULL) - return symbol_get_demangled_name (this); + case language_rust: + if (language_specific.demangled_name != nullptr) + return language_specific.demangled_name; break; case language_ada: return ada_decode_symbol (this); default: break; } - return name; + return linkage_name (); } /* See symtab.h. */ @@ -974,14 +979,15 @@ general_symbol_info::demangled_name () const { const char *dem_name = NULL; - switch (language) + switch (language ()) { case language_cplus: case language_d: case language_go: case language_objc: case language_fortran: - dem_name = symbol_get_demangled_name (this); + case language_rust: + dem_name = language_specific.demangled_name; break; case language_ada: dem_name = ada_decode_symbol (this); @@ -997,8 +1003,8 @@ general_symbol_info::demangled_name () const const char * general_symbol_info::search_name () const { - if (language == language_ada) - return name; + if (language () == language_ada) + return linkage_name (); else return natural_name (); } @@ -1010,7 +1016,7 @@ symbol_matches_search_name (const struct general_symbol_info *gsymbol, const lookup_name_info &name) { symbol_name_matcher_ftype *name_match - = get_symbol_name_matcher (language_def (gsymbol->language), name); + = get_symbol_name_matcher (language_def (gsymbol->language ()), name); return name_match (gsymbol->search_name (), name, NULL); } @@ -1190,8 +1196,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot, if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name)) return 0; - if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym), - slot_domain, domain)) + if (!symbol_matches_domain (sym->language (), slot_domain, domain)) return 0; } } @@ -1228,8 +1233,8 @@ resize_symbol_cache (struct symbol_cache *cache, unsigned int new_size) && new_size == 0)) return; - xfree (cache->global_symbols); - xfree (cache->static_symbols); + destroy_block_symbol_cache (cache->global_symbols); + destroy_block_symbol_cache (cache->static_symbols); if (new_size == 0) { @@ -1271,9 +1276,7 @@ get_symbol_cache (struct program_space *pspace) static void set_symbol_cache_size (unsigned int new_size) { - struct program_space *pspace; - - ALL_PSPACES (pspace) + for (struct program_space *pspace : program_spaces) { struct symbol_cache *cache = symbol_cache_key.get (pspace); @@ -1367,16 +1370,6 @@ symbol_cache_lookup (struct symbol_cache *cache, return {}; } -/* Clear out SLOT. */ - -static void -symbol_cache_clear_slot (struct symbol_cache_slot *slot) -{ - if (slot->state == SYMBOL_SLOT_NOT_FOUND) - xfree (slot->value.not_found.name); - slot->state = SYMBOL_SLOT_UNUSED; -} - /* Mark SYMBOL as found in SLOT. OBJFILE_CONTEXT is the current objfile when the lookup was done, or NULL if it's not needed to distinguish lookups (STATIC_BLOCK). It is *not* @@ -1531,9 +1524,7 @@ symbol_cache_dump (const struct symbol_cache *cache) static void maintenance_print_symbol_cache (const char *args, int from_tty) { - struct program_space *pspace; - - ALL_PSPACES (pspace) + for (struct program_space *pspace : program_spaces) { struct symbol_cache *cache; @@ -1557,9 +1548,7 @@ maintenance_print_symbol_cache (const char *args, int from_tty) static void maintenance_flush_symbol_cache (const char *args, int from_tty) { - struct program_space *pspace; - - ALL_PSPACES (pspace) + for (struct program_space *pspace : program_spaces) { symbol_cache_flush (pspace); } @@ -1602,9 +1591,7 @@ symbol_cache_stats (struct symbol_cache *cache) static void maintenance_print_symbol_cache_statistics (const char *args, int from_tty) { - struct program_space *pspace; - - ALL_PSPACES (pspace) + for (struct program_space *pspace : program_spaces) { struct symbol_cache *cache; @@ -1654,7 +1641,8 @@ fixup_section (struct general_symbol_info *ginfo, e.g. on PowerPC64, where the minimal symbol for a function will point to the function descriptor, while the debug symbol will point to the actual function code. */ - msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->name, objfile); + msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->linkage_name (), + objfile); if (msym) ginfo->section = MSYMBOL_SECTION (msym); else @@ -1671,11 +1659,10 @@ fixup_section (struct general_symbol_info *ginfo, So, instead, search the section table when lookup by name has failed. The ``addr'' and ``endaddr'' fields may have already - been relocated. If so, the relocation offset (i.e. the - ANOFFSET value) needs to be subtracted from these values when - performing the comparison. We unconditionally subtract it, - because, when no relocation has been performed, the ANOFFSET - value will simply be zero. + been relocated. If so, the relocation offset needs to be + subtracted from these values when performing the comparison. + We unconditionally subtract it, because, when no relocation + has been performed, the value will simply be zero. The address of the symbol whose section we're fixing up HAS NOT BEEN adjusted (relocated) yet. It can't have been since @@ -1701,7 +1688,7 @@ fixup_section (struct general_symbol_info *ginfo, ALL_OBJFILE_OSECTIONS (objfile, s) { int idx = s - objfile->sections; - CORE_ADDR offset = ANOFFSET (objfile->section_offsets, idx); + CORE_ADDR offset = objfile->section_offsets[idx]; if (fallback == -1) fallback = idx; @@ -1779,7 +1766,7 @@ demangle_for_lookup_info::demangle_for_lookup_info if (lookup_name.ignore_parameters () && lang == language_cplus) { gdb::unique_xmalloc_ptr without_params - = cp_remove_params_if_any (lookup_name.name ().c_str (), + = cp_remove_params_if_any (lookup_name.c_str (), lookup_name.completion_mode ()); if (without_params != NULL) @@ -1792,9 +1779,9 @@ demangle_for_lookup_info::demangle_for_lookup_info } if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME) - m_demangled_name = lookup_name.name (); + m_demangled_name = lookup_name.c_str (); else - m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (), + m_demangled_name = demangle_for_lookup (lookup_name.c_str (), lang, storage); } @@ -1805,7 +1792,7 @@ lookup_name_info::match_any () { /* Lookup any symbol that "" would complete. I.e., this matches all symbol names. */ - static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL, + static const lookup_name_info lookup_name ("", symbol_name_match_type::FULL, true); return lookup_name; @@ -1843,9 +1830,9 @@ demangle_for_lookup (const char *name, enum language lang, /* If we were given a non-mangled name, canonicalize it according to the language (so far only for C++). */ - std::string canon = cp_canonicalize_string (name); - if (!canon.empty ()) - return storage.swap_string (canon); + gdb::unique_xmalloc_ptr canon = cp_canonicalize_string (name); + if (canon != nullptr) + return storage.set_malloc_ptr (std::move (canon)); } else if (lang == language_d) { @@ -1868,7 +1855,7 @@ demangle_for_lookup (const char *name, enum language lang, unsigned int search_name_hash (enum language language, const char *search_name) { - return language_def (language)->la_search_name_hash (search_name); + return language_def (language)->search_name_hash (search_name); } /* See symtab.h. @@ -1930,7 +1917,7 @@ lookup_language_this (const struct language_defn *lang, if (symbol_lookup_debug > 1) { - struct objfile *objfile = lookup_objfile_from_block (block); + struct objfile *objfile = block_objfile (block); fprintf_unfiltered (gdb_stdlog, "lookup_language_this (%s, %s (objfile %s))", @@ -1979,14 +1966,14 @@ check_field (struct type *type, const char *name, /* The type may be a stub. */ type = check_typedef (type); - for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) + for (i = type->num_fields () - 1; i >= TYPE_N_BASECLASSES (type); i--) { const char *t_field_name = TYPE_FIELD_NAME (type, i); if (t_field_name && (strcmp_iw (t_field_name, name) == 0)) { is_a_field_of_this->type = type; - is_a_field_of_this->field = &TYPE_FIELD (type, i); + is_a_field_of_this->field = &type->field (i); return 1; } } @@ -2025,7 +2012,8 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type, if (symbol_lookup_debug) { - struct objfile *objfile = lookup_objfile_from_block (block); + struct objfile *objfile = (block == nullptr + ? nullptr : block_objfile (block)); fprintf_unfiltered (gdb_stdlog, "lookup_symbol_aux (%s, %s (objfile %s), %s, %s)\n", @@ -2075,11 +2063,11 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type, /* I'm not really sure that type of this can ever be typedefed; just be safe. */ t = check_typedef (t); - if (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (t)) + if (t->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (t)) t = TYPE_TARGET_TYPE (t); - if (TYPE_CODE (t) != TYPE_CODE_STRUCT - && TYPE_CODE (t) != TYPE_CODE_UNION) + if (t->code () != TYPE_CODE_STRUCT + && t->code () != TYPE_CODE_UNION) error (_("Internal error: `%s' is not an aggregate"), langdef->la_name_of_this); @@ -2170,32 +2158,6 @@ lookup_local_symbol (const char *name, /* See symtab.h. */ -struct objfile * -lookup_objfile_from_block (const struct block *block) -{ - if (block == NULL) - return NULL; - - block = block_global_block (block); - /* Look through all blockvectors. */ - for (objfile *obj : current_program_space->objfiles ()) - { - for (compunit_symtab *cust : obj->compunits ()) - if (block == BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), - GLOBAL_BLOCK)) - { - if (obj->separate_debug_objfile_backlink) - obj = obj->separate_debug_objfile_backlink; - - return obj; - } - } - - return NULL; -} - -/* See symtab.h. */ - struct symbol * lookup_symbol_in_block (const char *name, symbol_name_match_type match_type, const struct block *block, @@ -2205,7 +2167,8 @@ lookup_symbol_in_block (const char *name, symbol_name_match_type match_type, if (symbol_lookup_debug > 1) { - struct objfile *objfile = lookup_objfile_from_block (block); + struct objfile *objfile = (block == nullptr + ? nullptr : block_objfile (block)); fprintf_unfiltered (gdb_stdlog, "lookup_symbol_in_block (%s, %s (objfile %s), %s)", @@ -2274,6 +2237,8 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile, name, domain_name (domain)); } + struct block_symbol other; + other.symbol = NULL; for (compunit_symtab *cust : objfile->compunits ()) { const struct blockvector *bv; @@ -2284,18 +2249,36 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile, block = BLOCKVECTOR_BLOCK (bv, block_index); result.symbol = block_lookup_symbol_primary (block, name, domain); result.block = block; - if (result.symbol != NULL) + if (result.symbol == NULL) + continue; + if (best_symbol (result.symbol, domain)) { - if (symbol_lookup_debug > 1) + other = result; + break; + } + if (symbol_matches_domain (result.symbol->language (), + SYMBOL_DOMAIN (result.symbol), domain)) + { + struct symbol *better + = better_symbol (other.symbol, result.symbol, domain); + if (better != other.symbol) { - fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n", - host_address_to_string (result.symbol), - host_address_to_string (block)); + other.symbol = better; + other.block = block; } - result.symbol = fixup_symbol_section (result.symbol, objfile); - return result; + } + } + if (other.symbol != NULL) + { + if (symbol_lookup_debug > 1) + { + fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n", + host_address_to_string (other.symbol), + host_address_to_string (other.block)); } + other.symbol = fixup_symbol_section (other.symbol, objfile); + return other; } if (symbol_lookup_debug > 1) @@ -2475,7 +2458,8 @@ lookup_symbol_in_static_block (const char *name, if (symbol_lookup_debug) { - struct objfile *objfile = lookup_objfile_from_block (static_block); + struct objfile *objfile = (block == nullptr + ? nullptr : block_objfile (block)); fprintf_unfiltered (gdb_stdlog, "lookup_symbol_in_static_block (%s, %s (objfile %s)," @@ -2549,6 +2533,33 @@ lookup_symbol_in_objfile (struct objfile *objfile, enum block_enum block_index, return result; } +/* Find the language for partial symbol with NAME. */ + +static enum language +find_quick_global_symbol_language (const char *name, const domain_enum domain) +{ + for (objfile *objfile : current_program_space->objfiles ()) + { + if (objfile->sf && objfile->sf->qf + && objfile->sf->qf->lookup_global_symbol_language) + continue; + return language_unknown; + } + + for (objfile *objfile : current_program_space->objfiles ()) + { + bool symbol_found_p; + enum language lang + = objfile->sf->qf->lookup_global_symbol_language (objfile, name, domain, + &symbol_found_p); + if (!symbol_found_p) + continue; + return lang; + } + + return language_unknown; +} + /* Private data to be used with lookup_symbol_global_iterator_cb. */ struct global_or_static_sym_lookup_data @@ -2628,7 +2639,7 @@ lookup_global_or_static_symbol (const char *name, lookup_data.block_index = block_index; lookup_data.domain = domain; gdbarch_iterate_over_objfiles_in_search_order - (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (), + (objfile != NULL ? objfile->arch () : target_gdbarch (), lookup_symbol_global_or_static_iterator_cb, &lookup_data, objfile); result = lookup_data.result; } @@ -2660,17 +2671,30 @@ lookup_global_symbol (const char *name, global block first. This yields "more expected" behavior, and is needed to support 'FILENAME'::VARIABLE lookups. */ const struct block *global_block = block_global_block (block); + symbol *sym = NULL; if (global_block != nullptr) { - symbol *sym = lookup_symbol_in_block (name, - symbol_name_match_type::FULL, - global_block, domain); - if (sym != nullptr) + sym = lookup_symbol_in_block (name, + symbol_name_match_type::FULL, + global_block, domain); + if (sym != NULL && best_symbol (sym, domain)) return { sym, global_block }; } - struct objfile *objfile = lookup_objfile_from_block (block); - return lookup_global_or_static_symbol (name, GLOBAL_BLOCK, objfile, domain); + struct objfile *objfile = nullptr; + if (block != nullptr) + { + objfile = block_objfile (block); + if (objfile->separate_debug_objfile_backlink != nullptr) + objfile = objfile->separate_debug_objfile_backlink; + } + + block_symbol bs + = lookup_global_or_static_symbol (name, GLOBAL_BLOCK, objfile, domain); + if (better_symbol (sym, bs.symbol, domain) == sym) + return { sym, global_block }; + else + return bs; } bool @@ -2698,7 +2722,7 @@ symbol_matches_domain (enum language symbol_language, struct type * lookup_transparent_type (const char *name) { - return current_language->la_lookup_transparent_type (name); + return current_language->lookup_transparent_type (name); } /* A helper for basic_lookup_transparent_type that interfaces with the @@ -2827,8 +2851,7 @@ iterate_over_symbols (const struct block *block, ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym) { - if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), - SYMBOL_DOMAIN (sym), domain)) + if (symbol_matches_domain (sym->language (), SYMBOL_DOMAIN (sym), domain)) { struct block_symbol block_sym = {sym, block}; @@ -3148,7 +3171,17 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) ; /* fall through */ else - return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0); + { + /* Detect an obvious case of infinite recursion. If this + should occur, we'd like to know about it, so error out, + fatally. */ + if (BMSYMBOL_VALUE_ADDRESS (mfunsym) == pc) + internal_error (__FILE__, __LINE__, + _("Infinite recursion detected in find_pc_sect_line;" + "please file a bug report")); + + return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0); + } } symtab_and_line val; @@ -3204,7 +3237,12 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) struct linetable_entry *last = item + len; item = std::upper_bound (first, last, pc, pc_compare); if (item != first) - prev = item - 1; /* Found a matching item. */ + { + /* Found a matching item. Skip backwards over any end of + sequence markers. */ + for (prev = item - 1; prev->line == 0 && prev != first; prev--) + /* Nothing. */; + } /* At this point, prev points at the line whose start addr is <= pc, and item points at the next line. If we ran off the end of the linetable @@ -3221,6 +3259,23 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) best = prev; best_symtab = iter_s; + /* If during the binary search we land on a non-statement entry, + scan backward through entries at the same address to see if + there is an entry marked as is-statement. In theory this + duplication should have been removed from the line table + during construction, this is just a double check. If the line + table has had the duplication removed then this should be + pretty cheap. */ + if (!best->is_stmt) + { + struct linetable_entry *tmp = best; + while (tmp > first && (tmp - 1)->pc == tmp->pc + && (tmp - 1)->line != 0 && !tmp->is_stmt) + --tmp; + if (tmp->is_stmt) + best = tmp; + } + /* Discard BEST_END if it's before the PC of the current BEST. */ if (best_end <= best->pc) best_end = 0; @@ -3251,6 +3306,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) } else { + val.is_stmt = best->is_stmt; val.symtab = best_symtab; val.line = best->line; val.pc = best->pc; @@ -3419,7 +3475,8 @@ find_pcs_for_symtab_line (struct symtab *symtab, int line, { struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx]; - if (*best_item == NULL || item->line < (*best_item)->line) + if (*best_item == NULL + || (item->line < (*best_item)->line && item->is_stmt)) *best_item = item; break; @@ -3530,6 +3587,10 @@ find_line_common (struct linetable *l, int lineno, { struct linetable_entry *item = &(l->item[i]); + /* Ignore non-statements. */ + if (!item->is_stmt) + continue; + if (item->line == lineno) { /* Return the first (lowest address) entry which matches. */ @@ -3572,7 +3633,7 @@ find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section, && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab)) || SYMTAB_LANGUAGE (sal.symtab) == language_asm)) { - struct gdbarch *gdbarch = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab)); + struct gdbarch *gdbarch = SYMTAB_OBJFILE (sal.symtab)->arch (); sal.pc = func_addr; if (gdbarch_skip_entrypoint_p (gdbarch)) @@ -3731,7 +3792,7 @@ skip_prologue_sal (struct symtab_and_line *sal) name = msymbol.minsym->linkage_name (); } - gdbarch = get_objfile_arch (objfile); + gdbarch = objfile->arch (); /* Process the prologue in two passes. In the first pass try to skip the prologue (SKIP is true) and verify there is a real need for it (indicated @@ -4344,31 +4405,28 @@ info_sources_command (const char *args, int from_tty) printf_filtered ("\n"); } -/* Compare FILE against all the NFILES entries of FILES. If BASENAMES is - non-zero compare only lbasename of FILES. */ +/* Compare FILE against all the entries of FILENAMES. If BASENAMES is + true compare only lbasename of FILENAMES. */ -static int -file_matches (const char *file, const char *files[], int nfiles, int basenames) +static bool +file_matches (const char *file, const std::vector &filenames, + bool basenames) { - int i; + if (filenames.empty ()) + return true; - if (file != NULL && nfiles != 0) + for (const char *name : filenames) { - for (i = 0; i < nfiles; i++) - { - if (compare_filenames_for_search (file, (basenames - ? lbasename (files[i]) - : files[i]))) - return 1; - } + name = (basenames ? lbasename (name) : name); + if (compare_filenames_for_search (file, name)) + return true; } - else if (nfiles == 0) - return 1; - return 0; + + return false; } -/* Helper function for sort_search_symbols_remove_dups and qsort. Can only - sort symbols, not minimal symbols. */ +/* Helper function for std::sort on symbol_search objects. Can only sort + symbols, not minimal symbols. */ int symbol_search::compare_search_syms (const symbol_search &sym_a, @@ -4429,79 +4487,255 @@ treg_matches_sym_type_name (const compiled_regex &treg, return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0; } +/* See symtab.h. */ + +bool +global_symbol_searcher::is_suitable_msymbol + (const enum search_domain kind, const minimal_symbol *msymbol) +{ + switch (MSYMBOL_TYPE (msymbol)) + { + case mst_data: + case mst_bss: + case mst_file_data: + case mst_file_bss: + return kind == VARIABLES_DOMAIN; + case mst_text: + case mst_file_text: + case mst_solib_trampoline: + case mst_text_gnu_ifunc: + return kind == FUNCTIONS_DOMAIN; + default: + return false; + } +} -/* Sort the symbols in RESULT and remove duplicates. */ +/* See symtab.h. */ -static void -sort_search_symbols_remove_dups (std::vector *result) +bool +global_symbol_searcher::expand_symtabs + (objfile *objfile, const gdb::optional &preg) const +{ + enum search_domain kind = m_kind; + bool found_msymbol = false; + + if (objfile->sf) + objfile->sf->qf->expand_symtabs_matching + (objfile, + [&] (const char *filename, bool basenames) + { + return file_matches (filename, filenames, basenames); + }, + &lookup_name_info::match_any (), + [&] (const char *symname) + { + return (!preg.has_value () + || preg->exec (symname, 0, NULL, 0) == 0); + }, + NULL, + kind); + + /* Here, we search through the minimal symbol tables for functions and + variables that match, and force their symbols to be read. This is in + particular necessary for demangled variable names, which are no longer + put into the partial symbol tables. The symbol will then be found + during the scan of symtabs later. + + For functions, find_pc_symtab should succeed if we have debug info for + the function, for variables we have to call + lookup_symbol_in_objfile_from_linkage_name to determine if the + variable has debug info. If the lookup fails, set found_msymbol so + that we will rescan to print any matching symbols without debug info. + We only search the objfile the msymbol came from, we no longer search + all objfiles. In large programs (1000s of shared libs) searching all + objfiles is not worth the pain. */ + if (filenames.empty () + && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN)) + { + for (minimal_symbol *msymbol : objfile->msymbols ()) + { + QUIT; + + if (msymbol->created_by_gdb) + continue; + + if (is_suitable_msymbol (kind, msymbol)) + { + if (!preg.has_value () + || preg->exec (msymbol->natural_name (), 0, + NULL, 0) == 0) + { + /* An important side-effect of these lookup functions is + to expand the symbol table if msymbol is found, later + in the process we will add matching symbols or + msymbols to the results list, and that requires that + the symbols tables are expanded. */ + if (kind == FUNCTIONS_DOMAIN + ? (find_pc_compunit_symtab + (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) + == NULL) + : (lookup_symbol_in_objfile_from_linkage_name + (objfile, msymbol->linkage_name (), + VAR_DOMAIN) + .symbol == NULL)) + found_msymbol = true; + } + } + } + } + + return found_msymbol; +} + +/* See symtab.h. */ + +bool +global_symbol_searcher::add_matching_symbols + (objfile *objfile, + const gdb::optional &preg, + const gdb::optional &treg, + std::set *result_set) const { - std::sort (result->begin (), result->end ()); - result->erase (std::unique (result->begin (), result->end ()), - result->end ()); + enum search_domain kind = m_kind; + + /* Add matching symbols (if not already present). */ + for (compunit_symtab *cust : objfile->compunits ()) + { + const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust); + + for (block_enum block : { GLOBAL_BLOCK, STATIC_BLOCK }) + { + struct block_iterator iter; + struct symbol *sym; + const struct block *b = BLOCKVECTOR_BLOCK (bv, block); + + ALL_BLOCK_SYMBOLS (b, iter, sym) + { + struct symtab *real_symtab = symbol_symtab (sym); + + QUIT; + + /* Check first sole REAL_SYMTAB->FILENAME. It does + not need to be a substring of symtab_to_fullname as + it may contain "./" etc. */ + if ((file_matches (real_symtab->filename, filenames, false) + || ((basenames_may_differ + || file_matches (lbasename (real_symtab->filename), + filenames, true)) + && file_matches (symtab_to_fullname (real_symtab), + filenames, false))) + && ((!preg.has_value () + || preg->exec (sym->natural_name (), 0, + NULL, 0) == 0) + && ((kind == VARIABLES_DOMAIN + && SYMBOL_CLASS (sym) != LOC_TYPEDEF + && SYMBOL_CLASS (sym) != LOC_UNRESOLVED + && SYMBOL_CLASS (sym) != LOC_BLOCK + /* LOC_CONST can be used for more than + just enums, e.g., c++ static const + members. We only want to skip enums + here. */ + && !(SYMBOL_CLASS (sym) == LOC_CONST + && (SYMBOL_TYPE (sym)->code () + == TYPE_CODE_ENUM)) + && (!treg.has_value () + || treg_matches_sym_type_name (*treg, sym))) + || (kind == FUNCTIONS_DOMAIN + && SYMBOL_CLASS (sym) == LOC_BLOCK + && (!treg.has_value () + || treg_matches_sym_type_name (*treg, + sym))) + || (kind == TYPES_DOMAIN + && SYMBOL_CLASS (sym) == LOC_TYPEDEF + && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN) + || (kind == MODULES_DOMAIN + && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN + && SYMBOL_LINE (sym) != 0)))) + { + if (result_set->size () < m_max_search_results) + { + /* Match, insert if not already in the results. */ + symbol_search ss (block, sym); + if (result_set->find (ss) == result_set->end ()) + result_set->insert (ss); + } + else + return false; + } + } + } + } + + return true; } -/* Search the symbol table for matches to the regular expression REGEXP, - returning the results. +/* See symtab.h. */ - Only symbols of KIND are searched: - VARIABLES_DOMAIN - search all symbols, excluding functions, type names, - and constants (enums). - if T_REGEXP is not NULL, only returns var that have - a type matching regular expression T_REGEXP. - FUNCTIONS_DOMAIN - search all functions - TYPES_DOMAIN - search all type names - ALL_DOMAIN - an internal error for this function +bool +global_symbol_searcher::add_matching_msymbols + (objfile *objfile, const gdb::optional &preg, + std::vector *results) const +{ + enum search_domain kind = m_kind; - Within each file the results are sorted locally; each symtab's global and - static blocks are separately alphabetized. - Duplicate entries are removed. + for (minimal_symbol *msymbol : objfile->msymbols ()) + { + QUIT; - When EXCLUDE_MINSYMS is false then matching minsyms are also returned, - otherwise they are excluded. */ + if (msymbol->created_by_gdb) + continue; + + if (is_suitable_msymbol (kind, msymbol)) + { + if (!preg.has_value () + || preg->exec (msymbol->natural_name (), 0, + NULL, 0) == 0) + { + /* For functions we can do a quick check of whether the + symbol might be found via find_pc_symtab. */ + if (kind != FUNCTIONS_DOMAIN + || (find_pc_compunit_symtab + (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) + == NULL)) + { + if (lookup_symbol_in_objfile_from_linkage_name + (objfile, msymbol->linkage_name (), + VAR_DOMAIN).symbol == NULL) + { + /* Matching msymbol, add it to the results list. */ + if (results->size () < m_max_search_results) + results->emplace_back (GLOBAL_BLOCK, msymbol, objfile); + else + return false; + } + } + } + } + } + + return true; +} + +/* See symtab.h. */ std::vector -search_symbols (const char *regexp, enum search_domain kind, - const char *t_regexp, - int nfiles, const char *files[], - bool exclude_minsyms) +global_symbol_searcher::search () const { - const struct blockvector *bv; - const struct block *b; - int i = 0; - struct block_iterator iter; - struct symbol *sym; - int found_misc = 0; - static const enum minimal_symbol_type types[] - = {mst_data, mst_text, mst_unknown}; - static const enum minimal_symbol_type types2[] - = {mst_bss, mst_file_text, mst_unknown}; - static const enum minimal_symbol_type types3[] - = {mst_file_data, mst_solib_trampoline, mst_unknown}; - static const enum minimal_symbol_type types4[] - = {mst_file_bss, mst_text_gnu_ifunc, mst_unknown}; - enum minimal_symbol_type ourtype; - enum minimal_symbol_type ourtype2; - enum minimal_symbol_type ourtype3; - enum minimal_symbol_type ourtype4; - std::vector result; gdb::optional preg; gdb::optional treg; - gdb_assert (kind != ALL_DOMAIN); - - ourtype = types[kind]; - ourtype2 = types2[kind]; - ourtype3 = types3[kind]; - ourtype4 = types4[kind]; + gdb_assert (m_kind != ALL_DOMAIN); - if (regexp != NULL) + if (m_symbol_name_regexp != NULL) { + const char *symbol_name_regexp = m_symbol_name_regexp; + /* Make sure spacing is right for C++ operators. This is just a courtesy to make the matching less sensitive to how many spaces the user leaves between 'operator' and or . */ const char *opend; - const char *opname = operator_chars (regexp, &opend); + const char *opname = operator_chars (symbol_name_regexp, &opend); if (*opname) { @@ -4526,245 +4760,80 @@ search_symbols (const char *regexp, enum search_domain kind, char *tmp = (char *) alloca (8 + fix + strlen (opname) + 1); sprintf (tmp, "operator%.*s%s", fix, " ", opname); - regexp = tmp; + symbol_name_regexp = tmp; } } int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off ? REG_ICASE : 0); - preg.emplace (regexp, cflags, _("Invalid regexp")); + preg.emplace (symbol_name_regexp, cflags, + _("Invalid regexp")); } - if (t_regexp != NULL) + if (m_symbol_type_regexp != NULL) { int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off ? REG_ICASE : 0); - treg.emplace (t_regexp, cflags, _("Invalid regexp")); - } - - /* Search through the partial symtabs *first* for all symbols - matching the regexp. That way we don't have to reproduce all of - the machinery below. */ - expand_symtabs_matching ([&] (const char *filename, bool basenames) - { - return file_matches (filename, files, nfiles, - basenames); - }, - lookup_name_info::match_any (), - [&] (const char *symname) - { - return (!preg.has_value () - || preg->exec (symname, - 0, NULL, 0) == 0); - }, - NULL, - kind); - - /* Here, we search through the minimal symbol tables for functions - and variables that match, and force their symbols to be read. - This is in particular necessary for demangled variable names, - which are no longer put into the partial symbol tables. - The symbol will then be found during the scan of symtabs below. - - For functions, find_pc_symtab should succeed if we have debug info - for the function, for variables we have to call - lookup_symbol_in_objfile_from_linkage_name to determine if the variable - has debug info. - If the lookup fails, set found_misc so that we will rescan to print - any matching symbols without debug info. - We only search the objfile the msymbol came from, we no longer search - all objfiles. In large programs (1000s of shared libs) searching all - objfiles is not worth the pain. */ - - if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN)) - { - for (objfile *objfile : current_program_space->objfiles ()) - { - for (minimal_symbol *msymbol : objfile->msymbols ()) - { - QUIT; - - if (msymbol->created_by_gdb) - continue; - - if (MSYMBOL_TYPE (msymbol) == ourtype - || MSYMBOL_TYPE (msymbol) == ourtype2 - || MSYMBOL_TYPE (msymbol) == ourtype3 - || MSYMBOL_TYPE (msymbol) == ourtype4) - { - if (!preg.has_value () - || preg->exec (msymbol->natural_name (), 0, - NULL, 0) == 0) - { - /* Note: An important side-effect of these - lookup functions is to expand the symbol - table if msymbol is found, for the benefit of - the next loop on compunits. */ - if (kind == FUNCTIONS_DOMAIN - ? (find_pc_compunit_symtab - (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) - == NULL) - : (lookup_symbol_in_objfile_from_linkage_name - (objfile, msymbol->linkage_name (), VAR_DOMAIN) - .symbol == NULL)) - found_misc = 1; - } - } - } - } + treg.emplace (m_symbol_type_regexp, cflags, + _("Invalid regexp")); } + bool found_msymbol = false; + std::set result_set; for (objfile *objfile : current_program_space->objfiles ()) { - for (compunit_symtab *cust : objfile->compunits ()) - { - bv = COMPUNIT_BLOCKVECTOR (cust); - for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++) - { - b = BLOCKVECTOR_BLOCK (bv, i); - ALL_BLOCK_SYMBOLS (b, iter, sym) - { - struct symtab *real_symtab = symbol_symtab (sym); - - QUIT; - - /* Check first sole REAL_SYMTAB->FILENAME. It does - not need to be a substring of symtab_to_fullname as - it may contain "./" etc. */ - if ((file_matches (real_symtab->filename, files, nfiles, 0) - || ((basenames_may_differ - || file_matches (lbasename (real_symtab->filename), - files, nfiles, 1)) - && file_matches (symtab_to_fullname (real_symtab), - files, nfiles, 0))) - && ((!preg.has_value () - || preg->exec (sym->natural_name (), 0, - NULL, 0) == 0) - && ((kind == VARIABLES_DOMAIN - && SYMBOL_CLASS (sym) != LOC_TYPEDEF - && SYMBOL_CLASS (sym) != LOC_UNRESOLVED - && SYMBOL_CLASS (sym) != LOC_BLOCK - /* LOC_CONST can be used for more than - just enums, e.g., c++ static const - members. We only want to skip enums - here. */ - && !(SYMBOL_CLASS (sym) == LOC_CONST - && (TYPE_CODE (SYMBOL_TYPE (sym)) - == TYPE_CODE_ENUM)) - && (!treg.has_value () - || treg_matches_sym_type_name (*treg, sym))) - || (kind == FUNCTIONS_DOMAIN - && SYMBOL_CLASS (sym) == LOC_BLOCK - && (!treg.has_value () - || treg_matches_sym_type_name (*treg, - sym))) - || (kind == TYPES_DOMAIN - && SYMBOL_CLASS (sym) == LOC_TYPEDEF - && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN) - || (kind == MODULES_DOMAIN - && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN - && SYMBOL_LINE (sym) != 0)))) - { - /* match */ - result.emplace_back (i, sym); - } - } - } - } - } + /* Expand symtabs within objfile that possibly contain matching + symbols. */ + found_msymbol |= expand_symtabs (objfile, preg); - if (!result.empty ()) - sort_search_symbols_remove_dups (&result); + /* Find matching symbols within OBJFILE and add them in to the + RESULT_SET set. Use a set here so that we can easily detect + duplicates as we go, and can therefore track how many unique + matches we have found so far. */ + if (!add_matching_symbols (objfile, preg, treg, &result_set)) + break; + } - /* If there are no eyes, avoid all contact. I mean, if there are - no debug symbols, then add matching minsyms. But if the user wants - to see symbols matching a type regexp, then never give a minimal symbol, - as we assume that a minimal symbol does not have a type. */ + /* Convert the result set into a sorted result list, as std::set is + defined to be sorted then no explicit call to std::sort is needed. */ + std::vector result (result_set.begin (), result_set.end ()); - if ((found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN)) - && !exclude_minsyms + /* If there are no debug symbols, then add matching minsyms. But if the + user wants to see symbols matching a type regexp, then never give a + minimal symbol, as we assume that a minimal symbol does not have a + type. */ + if ((found_msymbol || (filenames.empty () && m_kind == VARIABLES_DOMAIN)) + && !m_exclude_minsyms && !treg.has_value ()) { + gdb_assert (m_kind == VARIABLES_DOMAIN || m_kind == FUNCTIONS_DOMAIN); for (objfile *objfile : current_program_space->objfiles ()) - { - for (minimal_symbol *msymbol : objfile->msymbols ()) - { - QUIT; - - if (msymbol->created_by_gdb) - continue; - - if (MSYMBOL_TYPE (msymbol) == ourtype - || MSYMBOL_TYPE (msymbol) == ourtype2 - || MSYMBOL_TYPE (msymbol) == ourtype3 - || MSYMBOL_TYPE (msymbol) == ourtype4) - { - if (!preg.has_value () - || preg->exec (msymbol->natural_name (), 0, - NULL, 0) == 0) - { - /* For functions we can do a quick check of whether the - symbol might be found via find_pc_symtab. */ - if (kind != FUNCTIONS_DOMAIN - || (find_pc_compunit_symtab - (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) - == NULL)) - { - if (lookup_symbol_in_objfile_from_linkage_name - (objfile, msymbol->linkage_name (), VAR_DOMAIN) - .symbol == NULL) - { - /* match */ - result.emplace_back (i, msymbol, objfile); - } - } - } - } - } - } + if (!add_matching_msymbols (objfile, preg, &result)) + break; } return result; } -/* Helper function for symtab_symbol_info, this function uses - the data returned from search_symbols() to print information - regarding the match to gdb_stdout. If LAST is not NULL, - print file and line number information for the symbol as - well. Skip printing the filename if it matches LAST. */ +/* See symtab.h. */ -static void -print_symbol_info (enum search_domain kind, - struct symbol *sym, - int block, const char *last) +std::string +symbol_to_info_string (struct symbol *sym, int block, + enum search_domain kind) { - scoped_switch_to_sym_language_if_auto l (sym); - struct symtab *s = symbol_symtab (sym); - - if (last != NULL) - { - const char *s_filename = symtab_to_filename_for_display (s); - - if (filename_cmp (last, s_filename) != 0) - { - printf_filtered (_("\nFile %ps:\n"), - styled_string (file_name_style.style (), - s_filename)); - } + std::string str; - if (SYMBOL_LINE (sym) != 0) - printf_filtered ("%d:\t", SYMBOL_LINE (sym)); - else - puts_filtered ("\t"); - } + gdb_assert (block == GLOBAL_BLOCK || block == STATIC_BLOCK); if (kind != TYPES_DOMAIN && block == STATIC_BLOCK) - printf_filtered ("static "); + str += "static "; /* Typedef that is not a C++ class. */ if (kind == TYPES_DOMAIN && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN) { + string_file tmp_stream; + /* FIXME: For C (and C++) we end up with a difference in output here between how a typedef is printed, and non-typedefs are printed. The TYPEDEF_PRINT code places a ";" at the end in an attempt to @@ -4773,29 +4842,70 @@ print_symbol_info (enum search_domain kind, For the struct printing case below, things are worse, we force printing of the ";" in this function, which is going to be wrong for languages that don't require a ";" between statements. */ - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_TYPEDEF) - typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout); + if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_TYPEDEF) + typedef_print (SYMBOL_TYPE (sym), sym, &tmp_stream); else - type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1); - printf_filtered ("\n"); + type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1); + str += tmp_stream.string (); } /* variable, func, or typedef-that-is-c++-class. */ else if (kind < TYPES_DOMAIN || (kind == TYPES_DOMAIN && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN)) { + string_file tmp_stream; + type_print (SYMBOL_TYPE (sym), (SYMBOL_CLASS (sym) == LOC_TYPEDEF ? "" : sym->print_name ()), - gdb_stdout, 0); + &tmp_stream, 0); - printf_filtered (";\n"); + str += tmp_stream.string (); + str += ";"; } /* Printing of modules is currently done here, maybe at some future point we might want a language specific method to print the module symbol so that we can customise the output more. */ else if (kind == MODULES_DOMAIN) - printf_filtered ("%s\n", sym->print_name ()); + str += sym->print_name (); + + return str; +} + +/* Helper function for symbol info commands, for example 'info functions', + 'info variables', etc. KIND is the kind of symbol we searched for, and + BLOCK is the type of block the symbols was found in, either GLOBAL_BLOCK + or STATIC_BLOCK. SYM is the symbol we found. If LAST is not NULL, + print file and line number information for the symbol as well. Skip + printing the filename if it matches LAST. */ + +static void +print_symbol_info (enum search_domain kind, + struct symbol *sym, + int block, const char *last) +{ + scoped_switch_to_sym_language_if_auto l (sym); + struct symtab *s = symbol_symtab (sym); + + if (last != NULL) + { + const char *s_filename = symtab_to_filename_for_display (s); + + if (filename_cmp (last, s_filename) != 0) + { + printf_filtered (_("\nFile %ps:\n"), + styled_string (file_name_style.style (), + s_filename)); + } + + if (SYMBOL_LINE (sym) != 0) + printf_filtered ("%d:\t", SYMBOL_LINE (sym)); + else + puts_filtered ("\t"); + } + + std::string str = symbol_to_info_string (sym, block, kind); + printf_filtered ("%s\n", str.c_str ()); } /* This help function for symtab_symbol_info() prints information @@ -4804,7 +4914,7 @@ print_symbol_info (enum search_domain kind, static void print_msymbol_info (struct bound_minimal_symbol msymbol) { - struct gdbarch *gdbarch = get_objfile_arch (msymbol.objfile); + struct gdbarch *gdbarch = msymbol.objfile->arch (); char *tmp; if (gdbarch_addr_bit (gdbarch) <= 32) @@ -4844,10 +4954,10 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms, if (regexp != nullptr && *regexp == '\0') regexp = nullptr; - /* Must make sure that if we're interrupted, symbols gets freed. */ - std::vector symbols = search_symbols (regexp, kind, - t_regexp, 0, NULL, - exclude_minsyms); + global_symbol_searcher spec (kind, regexp); + spec.set_symbol_type_regexp (t_regexp); + spec.set_exclude_minsyms (exclude_minsyms); + std::vector symbols = spec.search (); if (!quiet) { @@ -4904,13 +5014,13 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms, and 'info functions' commands. These correspond to the -q, -t, and -n options. */ -struct info_print_options +struct info_vars_funcs_options { bool quiet = false; bool exclude_minsyms = false; char *type_regexp = nullptr; - ~info_print_options () + ~info_vars_funcs_options () { xfree (type_regexp); } @@ -4919,24 +5029,25 @@ struct info_print_options /* The options used by the 'info variables' and 'info functions' commands. */ -static const gdb::option::option_def info_print_options_defs[] = { - gdb::option::boolean_option_def { +static const gdb::option::option_def info_vars_funcs_options_defs[] = { + gdb::option::boolean_option_def { "q", - [] (info_print_options *opt) { return &opt->quiet; }, + [] (info_vars_funcs_options *opt) { return &opt->quiet; }, nullptr, /* show_cmd_cb */ nullptr /* set_doc */ }, - gdb::option::boolean_option_def { + gdb::option::boolean_option_def { "n", - [] (info_print_options *opt) { return &opt->exclude_minsyms; }, + [] (info_vars_funcs_options *opt) { return &opt->exclude_minsyms; }, nullptr, /* show_cmd_cb */ nullptr /* set_doc */ }, - gdb::option::string_option_def { + gdb::option::string_option_def { "t", - [] (info_print_options *opt) { return &opt->type_regexp; }, + [] (info_vars_funcs_options *opt) { return &opt->type_regexp; + }, nullptr, /* show_cmd_cb */ nullptr /* set_doc */ } @@ -4946,20 +5057,20 @@ static const gdb::option::option_def info_print_options_defs[] = { functions'. */ static gdb::option::option_def_group -make_info_print_options_def_group (info_print_options *opts) +make_info_vars_funcs_options_def_group (info_vars_funcs_options *opts) { - return {{info_print_options_defs}, opts}; + return {{info_vars_funcs_options_defs}, opts}; } /* Command completer for 'info variables' and 'info functions'. */ static void -info_print_command_completer (struct cmd_list_element *ignore, - completion_tracker &tracker, - const char *text, const char * /* word */) +info_vars_funcs_command_completer (struct cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char * /* word */) { const auto group - = make_info_print_options_def_group (nullptr); + = make_info_vars_funcs_options_def_group (nullptr); if (gdb::option::complete_options (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group)) return; @@ -4973,8 +5084,8 @@ info_print_command_completer (struct cmd_list_element *ignore, static void info_variables_command (const char *args, int from_tty) { - info_print_options opts; - auto grp = make_info_print_options_def_group (&opts); + info_vars_funcs_options opts; + auto grp = make_info_vars_funcs_options_def_group (&opts); gdb::option::process_options (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp); if (args != nullptr && *args == '\0') @@ -4989,8 +5100,9 @@ info_variables_command (const char *args, int from_tty) static void info_functions_command (const char *args, int from_tty) { - info_print_options opts; - auto grp = make_info_print_options_def_group (&opts); + info_vars_funcs_options opts; + + auto grp = make_info_vars_funcs_options_def_group (&opts); gdb::option::process_options (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp); if (args != nullptr && *args == '\0') @@ -5078,11 +5190,9 @@ static void rbreak_command (const char *regexp, int from_tty) { std::string string; - const char **files = NULL; - const char *file_name; - int nfiles = 0; + const char *file_name = nullptr; - if (regexp) + if (regexp != nullptr) { const char *colon = strchr (regexp, ':'); @@ -5098,17 +5208,14 @@ rbreak_command (const char *regexp, int from_tty) while (isspace (local_name[colon_index])) local_name[colon_index--] = 0; file_name = local_name; - files = &file_name; - nfiles = 1; regexp = skip_spaces (colon + 1); } } - std::vector symbols = search_symbols (regexp, - FUNCTIONS_DOMAIN, - NULL, - nfiles, files, - false); + global_symbol_searcher spec (FUNCTIONS_DOMAIN, regexp); + if (file_name != nullptr) + spec.filenames.push_back (file_name); + std::vector symbols = spec.search (); scoped_rbreak_breakpoints finalize; for (const symbol_search &p : symbols) @@ -5153,7 +5260,7 @@ compare_symbol_name (const char *symbol_name, language symbol_language, /* See symtab.h. */ -void +bool completion_list_add_name (completion_tracker &tracker, language symbol_language, const char *symname, @@ -5165,7 +5272,7 @@ completion_list_add_name (completion_tracker &tracker, /* Clip symbols that cannot match. */ if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res)) - return; + return false; /* Refresh SYMNAME from the match string. It's potentially different depending on language. (E.g., on Ada, the match may be @@ -5189,6 +5296,8 @@ completion_list_add_name (completion_tracker &tracker, tracker.add_completion (std::move (completion), &match_res.match_for_lcd, text, word); } + + return true; } /* completion_list_add_name wrapper for struct symbol. */ @@ -5199,9 +5308,31 @@ completion_list_add_symbol (completion_tracker &tracker, const lookup_name_info &lookup_name, const char *text, const char *word) { - completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym), - sym->natural_name (), - lookup_name, text, word); + if (!completion_list_add_name (tracker, sym->language (), + sym->natural_name (), + lookup_name, text, word)) + return; + + /* C++ function symbols include the parameters within both the msymbol + name and the symbol name. The problem is that the msymbol name will + describe the parameters in the most basic way, with typedefs stripped + out, while the symbol name will represent the types as they appear in + the program. This means we will see duplicate entries in the + completion tracker. The following converts the symbol name back to + the msymbol name and removes the msymbol name from the completion + tracker. */ + if (sym->language () == language_cplus + && SYMBOL_DOMAIN (sym) == VAR_DOMAIN + && SYMBOL_CLASS (sym) == LOC_BLOCK) + { + /* The call to canonicalize returns the empty string if the input + string is already in canonical form, thanks to this we don't + remove the symbol we just added above. */ + gdb::unique_xmalloc_ptr str + = cp_canonicalize_string_no_typedefs (sym->natural_name ()); + if (str != nullptr) + tracker.remove_completion (str.get ()); + } } /* completion_list_add_name wrapper for struct minimal_symbol. */ @@ -5212,7 +5343,7 @@ completion_list_add_msymbol (completion_tracker &tracker, const lookup_name_info &lookup_name, const char *text, const char *word) { - completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym), + completion_list_add_name (tracker, sym->language (), sym->natural_name (), lookup_name, text, word); } @@ -5340,13 +5471,13 @@ completion_list_add_fields (completion_tracker &tracker, if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) { struct type *t = SYMBOL_TYPE (sym); - enum type_code c = TYPE_CODE (t); + enum type_code c = t->code (); int j; if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT) - for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++) + for (j = TYPE_N_BASECLASSES (t); j < t->num_fields (); j++) if (TYPE_FIELD_NAME (t, j)) - completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym), + completion_list_add_name (tracker, sym->language (), TYPE_FIELD_NAME (t, j), lookup_name, text, word); } @@ -5357,7 +5488,7 @@ completion_list_add_fields (completion_tracker &tracker, bool symbol_is_function_or_method (symbol *sym) { - switch (TYPE_CODE (SYMBOL_TYPE (sym))) + switch (SYMBOL_TYPE (sym)->code ()) { case TYPE_CODE_FUNC: case TYPE_CODE_METHOD: @@ -5408,7 +5539,7 @@ find_gnu_ifunc (const symbol *sym) CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym); if (MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc) { - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); msym_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, msym_addr, @@ -5457,7 +5588,7 @@ add_symtab_completions (struct compunit_symtab *cust, if (code == TYPE_CODE_UNDEF || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN - && TYPE_CODE (SYMBOL_TYPE (sym)) == code)) + && SYMBOL_TYPE (sym)->code () == code)) completion_list_add_symbol (tracker, sym, lookup_name, text, word); @@ -5608,7 +5739,7 @@ default_collect_symbol_completion_matches_break_on sym_text, word); } else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN - && TYPE_CODE (SYMBOL_TYPE (sym)) == code) + && SYMBOL_TYPE (sym)->code () == code) completion_list_add_symbol (tracker, sym, lookup_name, sym_text, word); } @@ -6029,6 +6160,16 @@ find_main_name (void) /* The languages above didn't identify the name of the main procedure. Fallback to "main". */ + + /* Try to find language for main in psymtabs. */ + enum language lang + = find_quick_global_symbol_language ("main", VAR_DOMAIN); + if (lang != language_unknown) + { + set_main_name ("main", lang); + return; + } + set_main_name ("main", language_unknown); } @@ -6201,42 +6342,6 @@ initialize_ordinary_address_classes (void) -/* Initialize the symbol SYM, and mark it as being owned by an objfile. */ - -void -initialize_objfile_symbol (struct symbol *sym) -{ - SYMBOL_OBJFILE_OWNED (sym) = 1; - SYMBOL_SECTION (sym) = -1; -} - -/* Allocate and initialize a new 'struct symbol' on OBJFILE's - obstack. */ - -struct symbol * -allocate_symbol (struct objfile *objfile) -{ - struct symbol *result = new (&objfile->objfile_obstack) symbol (); - - initialize_objfile_symbol (result); - - return result; -} - -/* Allocate and initialize a new 'struct template_symbol' on OBJFILE's - obstack. */ - -struct template_symbol * -allocate_template_symbol (struct objfile *objfile) -{ - struct template_symbol *result; - - result = new (&objfile->objfile_obstack) template_symbol (); - initialize_objfile_symbol (result); - - return result; -} - /* See symtab.h. */ struct objfile * @@ -6253,7 +6358,7 @@ symbol_arch (const struct symbol *symbol) { if (!SYMBOL_OBJFILE_OWNED (symbol)) return symbol->owner.arch; - return get_objfile_arch (SYMTAB_OBJFILE (symbol->owner.symtab)); + return SYMTAB_OBJFILE (symbol->owner.symtab)->arch (); } /* See symtab.h. */ @@ -6286,6 +6391,9 @@ get_symbol_address (const struct symbol *sym) for (objfile *objfile : current_program_space->objfiles ()) { + if (objfile->separate_debug_objfile_backlink != nullptr) + continue; + bound_minimal_symbol minsym = lookup_minimal_symbol_linkage (linkage_name, objfile); if (minsym.minsym != nullptr) @@ -6306,7 +6414,8 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym) for (objfile *objfile : current_program_space->objfiles ()) { - if ((objfile->flags & OBJF_MAINLINE) != 0) + if (objfile->separate_debug_objfile_backlink == nullptr + && (objfile->flags & OBJF_MAINLINE) != 0) { bound_minimal_symbol found = lookup_minimal_symbol_linkage (linkage_name, objfile); @@ -6314,8 +6423,7 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym) return BMSYMBOL_VALUE_ADDRESS (found); } } - return (minsym->value.address - + ANOFFSET (objf->section_offsets, minsym->section)); + return minsym->value.address + objf->section_offsets[minsym->section]; } @@ -6324,15 +6432,6 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym) static struct cmd_list_element *info_module_cmdlist = NULL; -/* Implement the 'info module' command, just displays some help text for - the available sub-commands. */ - -static void -info_module_command (const char *args, int from_tty) -{ - help_list (info_module_cmdlist, "info module ", class_info, gdb_stdout); -} - /* See symtab.h. */ std::vector @@ -6342,17 +6441,17 @@ search_module_symbols (const char *module_regexp, const char *regexp, std::vector results; /* Search for all modules matching MODULE_REGEXP. */ - std::vector modules = search_symbols (module_regexp, - MODULES_DOMAIN, - NULL, 0, NULL, - true); + global_symbol_searcher spec1 (MODULES_DOMAIN, module_regexp); + spec1.set_exclude_minsyms (true); + std::vector modules = spec1.search (); /* Now search for all symbols of the required KIND matching the required regular expressions. We figure out which ones are in which modules below. */ - std::vector symbols = search_symbols (regexp, kind, - type_regexp, 0, - NULL, true); + global_symbol_searcher spec2 (kind, regexp); + spec2.set_symbol_type_regexp (type_regexp); + spec2.set_exclude_minsyms (true); + std::vector symbols = spec2.search (); /* Now iterate over all MODULES, checking to see which items from SYMBOLS are in each module. */ @@ -6628,8 +6727,9 @@ info_module_var_func_command_completer (struct cmd_list_element *ignore, +void _initialize_symtab (); void -_initialize_symtab (void) +_initialize_symtab () { cmd_list_element *c; @@ -6642,7 +6742,7 @@ Usage: info variables [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the global and static variables.\n"), _("global and static variables"), true)); - set_cmd_completer_handle_brkchars (c, info_print_command_completer); + set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer); if (dbx_commands) { c = add_com ("whereis", class_info, info_variables_command, @@ -6652,7 +6752,7 @@ Usage: whereis [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the global and static variables.\n"), _("global and static variables"), true)); - set_cmd_completer_handle_brkchars (c, info_print_command_completer); + set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer); } c = add_info ("functions", info_functions_command, @@ -6662,7 +6762,7 @@ Usage: info functions [-q] [-n] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the functions.\n"), _("functions"), true)); - set_cmd_completer_handle_brkchars (c, info_print_command_completer); + set_cmd_completer_handle_brkchars (c, info_vars_funcs_command_completer); c = add_info ("types", info_types_command, _("\ All type names, or those matching REGEXP.\n\ @@ -6690,10 +6790,10 @@ Options:\n\ _("All module names, or those matching REGEXP.")); set_cmd_completer_handle_brkchars (c, info_types_command_completer); - add_prefix_cmd ("module", class_info, info_module_command, _("\ + add_basic_prefix_cmd ("module", class_info, _("\ Print information about modules."), - &info_module_cmdlist, "info module ", - 0, &infolist); + &info_module_cmdlist, "info module ", + 0, &infolist); c = add_cmd ("functions", class_info, info_module_functions_command, _("\ Display functions arranged by modules.\n\