/* 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.
} 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. */
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
~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;
const char *name,
struct obstack *obstack)
{
- if (gsymbol->language == language_ada)
+ if (gsymbol->language () == language_ada)
{
if (name == NULL)
{
const char *
symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
{
- if (gsymbol->language == language_ada)
+ if (gsymbol->language () == language_ada)
{
if (!gsymbol->ada_mangled)
return NULL;
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);
+ symbol_set_demangled_name (this, 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));
}
}
/* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
The hash table code will round this up to the next prime number.
Choosing a much larger table size wastes memory, and saves only about
- 1% in symbol reading. */
+ 1% in symbol reading. However, if the minsym count is already
+ initialized (e.g. because symbol name setting was deferred to
+ a background thread) we can initialize the hashtable with a count
+ based on that, because we will almost certainly have at least that
+ many entries. If we have a nonzero number but less than 256,
+ we still stay with 256 to have some space for psymbols, etc. */
+
+ /* htab will expand the table when it is 3/4th full, so we account for that
+ here. +2 to round up. */
+ int minsym_based_count = (per_bfd->minimal_symbol_count + 2) / 3 * 4;
+ int count = std::max (per_bfd->minimal_symbol_count, minsym_based_count);
per_bfd->demangled_names_hash.reset (htab_create_alloc
- (256, hash_demangled_name_entry, eq_demangled_name_entry,
+ (count, hash_demangled_name_entry, eq_demangled_name_entry,
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);
return demangled;
if (language_sniff_from_mangled_name (lang, mangled, &demangled))
{
- gsymbol->language = l;
+ gsymbol->m_language = l;
return demangled;
}
}
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<hashval_t> 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 ());
+ symbol_set_demangled_name (this, NULL, &per_bfd->storage_obstack);
return;
}
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<char> demangled_name
+ (const_cast<char *> (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
else
linkage_name_copy = linkage_name;
- gdb::unique_xmalloc_ptr<char> 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
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 ();
+ symbol_set_demangled_name (this, (*slot)->demangled.get (),
+ &per_bfd->storage_obstack);
}
-/* Return the source code name of a symbol. In languages where
- demangling is necessary, this is the demangled name. */
+/* See symtab.h. */
const char *
-symbol_natural_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::natural_name () const
{
- switch (gsymbol->language)
+ switch (language ())
{
case language_cplus:
case language_d:
case language_go:
case language_objc:
case language_fortran:
- if (symbol_get_demangled_name (gsymbol) != NULL)
- return symbol_get_demangled_name (gsymbol);
+ if (symbol_get_demangled_name (this) != NULL)
+ return symbol_get_demangled_name (this);
break;
case language_ada:
- return ada_decode_symbol (gsymbol);
+ return ada_decode_symbol (this);
default:
break;
}
- return gsymbol->name;
+ return linkage_name ();
}
-/* Return the demangled name for a symbol based on the language for
- that symbol. If no demangled name exists, return NULL. */
+/* See symtab.h. */
const char *
-symbol_demangled_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::demangled_name () const
{
const char *dem_name = NULL;
- switch (gsymbol->language)
+ switch (language ())
{
case language_cplus:
case language_d:
case language_go:
case language_objc:
case language_fortran:
- dem_name = symbol_get_demangled_name (gsymbol);
+ dem_name = symbol_get_demangled_name (this);
break;
case language_ada:
- dem_name = ada_decode_symbol (gsymbol);
+ dem_name = ada_decode_symbol (this);
break;
default:
break;
return dem_name;
}
-/* Return the search name of a symbol---generally the demangled or
- linkage name of the symbol, depending on how it will be searched for.
- If there is no distinct demangled name, then returns the same value
- (same pointer) as SYMBOL_LINKAGE_NAME. */
+/* See symtab.h. */
const char *
-symbol_search_name (const struct general_symbol_info *gsymbol)
+general_symbol_info::search_name () const
{
- if (gsymbol->language == language_ada)
- return gsymbol->name;
+ if (language () == language_ada)
+ return linkage_name ();
else
- return symbol_natural_name (gsymbol);
+ return natural_name ();
}
/* See symtab.h. */
const lookup_name_info &name)
{
symbol_name_matcher_ftype *name_match
- = get_symbol_name_matcher (language_def (gsymbol->language), name);
- return name_match (symbol_search_name (gsymbol), name, NULL);
+ = get_symbol_name_matcher (language_def (gsymbol->language ()), name);
+ return name_match (gsymbol->search_name (), name, NULL);
}
\f
}
else
{
- slot_name = SYMBOL_SEARCH_NAME (slot->value.found.symbol);
+ slot_name = slot->value.found.symbol->search_name ();
slot_domain = SYMBOL_DOMAIN (slot->value.found.symbol);
}
/* It's important that we use the same comparison that was done
the first time through. If the slot records a found symbol,
then this means using the symbol name comparison function of
- the symbol's language with SYMBOL_SEARCH_NAME. See
+ the symbol's language with symbol->search_name (). See
dictionary.c. It also means using symbol_matches_domain for
found symbols. See block.c.
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;
}
}
&& 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)
{
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*
printf_filtered (" [%4u] = %s, %s %s\n", i,
host_address_to_string (context),
- SYMBOL_PRINT_NAME (found),
+ found->print_name (),
domain_name (SYMBOL_DOMAIN (found)));
break;
}
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
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
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;
return sym;
}
- fixup_section (&sym->ginfo, addr, objfile);
+ fixup_section (sym, addr, objfile);
return sym;
}
if (lookup_name.ignore_parameters () && lang == language_cplus)
{
gdb::unique_xmalloc_ptr<char> 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)
}
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);
}
{
/* 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;
if (symbol_lookup_debug > 1)
{
fprintf_unfiltered (gdb_stdlog, " = %s (%s, block %s)\n",
- SYMBOL_PRINT_NAME (sym),
+ sym->print_name (),
host_address_to_string (sym),
host_address_to_string (block));
}
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
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};
if (MSYMBOL_TYPE (msymbol.minsym) == mst_solib_trampoline)
{
struct bound_minimal_symbol mfunsym
- = lookup_minimal_symbol_text (MSYMBOL_LINKAGE_NAME (msymbol.minsym),
+ = lookup_minimal_symbol_text (msymbol.minsym->linkage_name (),
NULL);
if (mfunsym.minsym == NULL)
* but the "break" still works, and the warning is annoying.
* So I commented out the warning. RT */
/* warning ("In stub for %s; unable to find real function/line info",
- SYMBOL_LINKAGE_NAME (msymbol)); */
+ msymbol->linkage_name ()); */
;
/* fall through */
else if (BMSYMBOL_VALUE_ADDRESS (mfunsym)
/* Avoid infinite recursion */
/* See above comment about why warning is commented out. */
/* warning ("In stub for %s; unable to find real function/line info",
- SYMBOL_LINKAGE_NAME (msymbol)); */
+ msymbol->linkage_name ()); */
;
/* 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;
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
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;
}
else
{
+ val.is_stmt = best->is_stmt;
val.symtab = best_symtab;
val.line = best->line;
val.pc = best->pc;
{
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;
{
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. */
objfile = symbol_objfile (sym);
pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
section = SYMBOL_OBJ_SECTION (objfile, sym);
- name = SYMBOL_LINKAGE_NAME (sym);
+ name = sym->linkage_name ();
}
else
{
objfile = msymbol.objfile;
pc = BMSYMBOL_VALUE_ADDRESS (msymbol);
section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
- name = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
+ name = msymbol.minsym->linkage_name ();
}
gdbarch = get_objfile_arch (objfile);
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<const char *> &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,
if (sym_a.block != sym_b.block)
return sym_a.block - sym_b.block;
- return strcmp (SYMBOL_PRINT_NAME (sym_a.symbol),
- SYMBOL_PRINT_NAME (sym_b.symbol));
+ return strcmp (sym_a.symbol->print_name (), sym_b.symbol->print_name ());
}
/* Returns true if the type_name of symbol_type of SYM matches TREG.
{
fprintf_unfiltered (gdb_stdlog,
"treg_matches_sym_type_name\n sym %s\n",
- SYMBOL_NATURAL_NAME (sym));
+ sym->natural_name ());
}
sym_type = SYMBOL_TYPE (sym);
return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
}
+/* See symtab.h. */
-/* Sort the symbols in RESULT and remove duplicates. */
+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;
+ }
+}
-static void
-sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
+/* See symtab.h. */
+
+bool
+global_symbol_searcher::expand_symtabs
+ (objfile *objfile, const gdb::optional<compiled_regex> &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<compiled_regex> &preg,
+ const gdb::optional<compiled_regex> &treg,
+ std::set<symbol_search> *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
+ && (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))))
+ {
+ 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. */
+
+bool
+global_symbol_searcher::add_matching_msymbols
+ (objfile *objfile, const gdb::optional<compiled_regex> &preg,
+ std::vector<symbol_search> *results) const
+{
+ enum search_domain kind = m_kind;
+
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ QUIT;
+
+ if (msymbol->created_by_gdb)
+ continue;
- 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
+ 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;
+ }
+ }
+ }
+ }
+ }
- Within each file the results are sorted locally; each symtab's global and
- static blocks are separately alphabetized.
- Duplicate entries are removed.
+ return true;
+}
- When EXCLUDE_MINSYMS is false then matching minsyms are also returned,
- otherwise they are excluded. */
+/* See symtab.h. */
std::vector<symbol_search>
-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<symbol_search> result;
gdb::optional<compiled_regex> preg;
gdb::optional<compiled_regex> 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 <TYPENAME> or <OPERATOR>. */
const char *opend;
- const char *opname = operator_chars (regexp, &opend);
+ const char *opname = operator_chars (symbol_name_regexp, &opend);
if (*opname)
{
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 (msymbol), 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 (msymbol),
- VAR_DOMAIN)
- .symbol == NULL))
- found_misc = 1;
- }
- }
- }
- }
+ treg.emplace (m_symbol_type_regexp, cflags,
+ _("Invalid regexp"));
}
+ bool found_msymbol = false;
+ std::set<symbol_search> 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 (SYMBOL_NATURAL_NAME (sym), 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<symbol_search> 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 (msymbol), 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 (msymbol),
- 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
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);
+ 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
- ? "" : SYMBOL_PRINT_NAME (sym)),
- gdb_stdout, 0);
+ ? "" : sym->print_name ()),
+ &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", SYMBOL_PRINT_NAME (sym));
+ 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
printf_filtered (_("%ps %ps\n"),
styled_string (address_style.style (), tmp),
- styled_string (sym_style,
- MSYMBOL_PRINT_NAME (msymbol.minsym)));
+ styled_string (sym_style, msymbol.minsym->print_name ()));
}
/* This is the guts of the commands "info functions", "info types", and
if (regexp != nullptr && *regexp == '\0')
regexp = nullptr;
- /* Must make sure that if we're interrupted, symbols gets freed. */
- std::vector<symbol_search> 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<symbol_search> symbols = spec.search ();
if (!quiet)
{
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);
}
/* 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<info_print_options> {
+static const gdb::option::option_def info_vars_funcs_options_defs[] = {
+ gdb::option::boolean_option_def<info_vars_funcs_options> {
"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<info_print_options> {
+ gdb::option::boolean_option_def<info_vars_funcs_options> {
"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<info_print_options> {
+ gdb::option::string_option_def<info_vars_funcs_options> {
"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 */
}
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;
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')
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')
from_tty);
}
-/* Breakpoint all functions matching regular expression. */
-
-void
-rbreak_command_wrapper (char *regexp, int from_tty)
-{
- rbreak_command (regexp, from_tty);
-}
-
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, ':');
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<symbol_search> 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<symbol_search> symbols = spec.search ();
scoped_rbreak_breakpoints finalize;
for (const symbol_search &p : symbols)
const char *fullname = symtab_to_fullname (symtab);
string = string_printf ("%s:'%s'", fullname,
- SYMBOL_LINKAGE_NAME (p.symbol));
+ p.symbol->linkage_name ());
break_command (&string[0], from_tty);
print_symbol_info (FUNCTIONS_DOMAIN, p.symbol, p.block, NULL);
}
else
{
string = string_printf ("'%s'",
- MSYMBOL_LINKAGE_NAME (p.msymbol.minsym));
+ p.msymbol.minsym->linkage_name ());
break_command (&string[0], from_tty);
printf_filtered ("<function, no debug info> %s;\n",
- MSYMBOL_PRINT_NAME (p.msymbol.minsym));
+ p.msymbol.minsym->print_name ());
}
}
}
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
- SYMBOL_NATURAL_NAME (sym),
+ completion_list_add_name (tracker, sym->language (),
+ sym->natural_name (),
lookup_name, text, word);
+
+ /* 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. */
+ std::string str
+ = cp_canonicalize_string_no_typedefs (sym->natural_name ());
+ if (!str.empty ())
+ tracker.remove_completion (str.c_str ());
+ }
}
/* completion_list_add_name wrapper for struct minimal_symbol. */
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym),
- MSYMBOL_NATURAL_NAME (sym),
+ completion_list_add_name (tracker, sym->language (),
+ sym->natural_name (),
lookup_name, text, word);
}
const char *method, *category, *selector;
char *tmp2 = NULL;
- method = MSYMBOL_NATURAL_NAME (msymbol);
+ method = msymbol->natural_name ();
/* Is it a method? */
if ((method[0] != '-') && (method[0] != '+'))
if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); 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);
}
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
return {};
- lookup_name_info lookup_name (SYMBOL_SEARCH_NAME (sym),
+ lookup_name_info lookup_name (sym->search_name (),
symbol_name_match_type::SEARCH_NAME);
struct objfile *objfile = symbol_objfile (sym);
/* 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);
}
\f
-/* Helper function to initialize the fields of an objfile-owned symbol.
- It assumed that *SYM is already all zeroes. */
-
-static void
-initialize_objfile_symbol_1 (struct symbol *sym)
-{
- SYMBOL_OBJFILE_OWNED (sym) = 1;
- SYMBOL_SECTION (sym) = -1;
-}
-
/* Initialize the symbol SYM, and mark it as being owned by an objfile. */
void
initialize_objfile_symbol (struct symbol *sym)
{
- memset (sym, 0, sizeof (*sym));
- initialize_objfile_symbol_1 (sym);
+ SYMBOL_OBJFILE_OWNED (sym) = 1;
+ SYMBOL_SECTION (sym) = -1;
}
/* Allocate and initialize a new 'struct symbol' on OBJFILE's
struct symbol *
allocate_symbol (struct objfile *objfile)
{
- struct symbol *result;
+ struct symbol *result = new (&objfile->objfile_obstack) symbol ();
- result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
- initialize_objfile_symbol_1 (result);
+ initialize_objfile_symbol (result);
return result;
}
{
struct template_symbol *result;
- result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
- initialize_objfile_symbol_1 (result);
+ result = new (&objfile->objfile_obstack) template_symbol ();
+ initialize_objfile_symbol (result);
return result;
}
gdb_assert (sym->maybe_copied);
gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC);
- const char *linkage_name = SYMBOL_LINKAGE_NAME (sym);
+ const char *linkage_name = sym->linkage_name ();
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)
return BMSYMBOL_VALUE_ADDRESS (minsym);
}
- return sym->ginfo.value.address;
+ return sym->value.address;
}
/* See symtab.h. */
gdb_assert (minsym->maybe_copied);
gdb_assert ((objf->flags & OBJF_MAINLINE) == 0);
- const char *linkage_name = MSYMBOL_LINKAGE_NAME (minsym);
+ const char *linkage_name = minsym->linkage_name ();
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);
return BMSYMBOL_VALUE_ADDRESS (found);
}
}
- return (minsym->value.address
- + ANOFFSET (objf->section_offsets, minsym->section));
+ return minsym->value.address + objf->section_offsets[minsym->section];
}
\f
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<module_symbol_search>
std::vector<module_symbol_search> results;
/* Search for all modules matching MODULE_REGEXP. */
- std::vector<symbol_search> 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<symbol_search> 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<symbol_search> 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<symbol_search> symbols = spec2.search ();
/* Now iterate over all MODULES, checking to see which items from
SYMBOLS are in each module. */
/* This is a module. */
gdb_assert (p.symbol != nullptr);
- std::string prefix = SYMBOL_PRINT_NAME (p.symbol);
+ std::string prefix = p.symbol->print_name ();
prefix += "::";
for (const symbol_search &q : symbols)
if (q.symbol == nullptr)
continue;
- if (strncmp (SYMBOL_PRINT_NAME (q.symbol), prefix.c_str (),
+ if (strncmp (q.symbol->print_name (), prefix.c_str (),
prefix.size ()) != 0)
continue;
if (last_module_symbol != p.symbol)
{
printf_filtered ("\n");
- printf_filtered (_("Module \"%s\":\n"),
- SYMBOL_PRINT_NAME (p.symbol));
+ printf_filtered (_("Module \"%s\":\n"), p.symbol->print_name ());
last_module_symbol = p.symbol;
last_filename = "";
}
\f
+void _initialize_symtab ();
void
-_initialize_symtab (void)
+_initialize_symtab ()
{
cmd_list_element *c;
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,
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,
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\
_("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\