/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "objfiles.h"
#include "gdbcmd.h"
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
#include "expression.h"
#include "language.h"
#include "demangle.h"
#include "addrmap.h"
#include "cli/cli-utils.h"
#include "cli/cli-style.h"
+#include "cli/cli-cmds.h"
#include "fnmatch.h"
#include "hashtab.h"
#include "typeprint.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
#include "block.h"
#include "dictionary.h"
/* See symtab.h. */
+call_site *
+compunit_symtab::find_call_site (CORE_ADDR pc) const
+{
+ if (m_call_site_htab == nullptr)
+ return nullptr;
+
+ CORE_ADDR delta
+ = this->objfile->section_offsets[COMPUNIT_BLOCK_LINE_SECTION (this)];
+ CORE_ADDR unrelocated_pc = pc - delta;
+
+ struct call_site call_site_local (unrelocated_pc, nullptr, nullptr);
+ void **slot
+ = htab_find_slot (m_call_site_htab, &call_site_local, NO_INSERT);
+ if (slot == nullptr)
+ return nullptr;
+
+ return (call_site *) *slot;
+}
+
+/* See symtab.h. */
+
+void
+compunit_symtab::set_call_site_htab (htab_t call_site_htab)
+{
+ gdb_assert (m_call_site_htab == nullptr);
+ m_call_site_htab = call_site_htab;
+}
+
+/* See symtab.h. */
+
struct symtab *
compunit_primary_filetab (const struct compunit_symtab *cust)
{
for (objfile *objfile : current_program_space->objfiles ())
{
- if (objfile->sf
- && objfile->sf->qf->map_symtabs_matching_filename (objfile,
- name,
- real_path.get (),
- callback))
+ if (objfile->map_symtabs_matching_filename (name, real_path.get (),
+ callback))
return;
}
}
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)? */
else if (physname[0] == 't' || physname[0] == 'Q')
{
/* The physname for template and qualified methods already includes
- the class name. */
+ the class name. */
xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
newname = NULL;
len = 0;
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;
}
\f
|| language == language_objc
|| language == language_fortran)
{
- symbol_set_demangled_name (this, NULL, obstack);
+ set_demangled_name (NULL, obstack);
}
else if (language == language_ada)
{
/* See symtab.h */
-char *
+gdb::unique_xmalloc_ptr<char>
symbol_find_demangled_name (struct general_symbol_info *gsymbol,
const char *mangled)
{
- char *demangled = NULL;
+ gdb::unique_xmalloc_ptr<char> demangled;
int i;
if (gsymbol->language () == language_unknown)
{
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;
}
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->m_language = l;
return demangled;
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. */
+ we can save some space by not storing the demangled name. */
if (!copy_name)
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';
- m_name = name;
- }
- symbol_set_demangled_name (this, 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;
}
if (!hash.has_value ())
hash = hash_demangled_name_entry (&entry);
slot = ((struct demangled_name_entry **)
- htab_find_slot_with_hash (per_bfd->demangled_names_hash.get (),
+ 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.
|| (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
- this copy because demangling needs a nullterminated string. */
+ to true if the string might not be nullterminated. We have to make
+ this copy because demangling needs a nullterminated string. */
gdb::string_view linkage_name_copy;
if (copy_name)
{
else
linkage_name_copy = linkage_name;
- /* 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. */
- gdb::unique_xmalloc_ptr<char> demangled_name
- (language_specific.demangled_name
- ? const_cast<char *> (language_specific.demangled_name)
- : symbol_find_demangled_name (this, linkage_name_copy.data ()));
+ if (demangled_name.get () == nullptr)
+ demangled_name
+ = 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
m_language = (*slot)->language;
m_name = (*slot)->mangled.data ();
- if ((*slot)->demangled != nullptr)
- symbol_set_demangled_name (this, (*slot)->demangled.get (),
- &per_bfd->storage_obstack);
- else
- symbol_set_demangled_name (this, NULL, &per_bfd->storage_obstack);
+ set_demangled_name ((*slot)->demangled.get (), &per_bfd->storage_obstack);
}
/* See symtab.h. */
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);
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);
/* See symtab.h. */
+struct obj_section *
+general_symbol_info::obj_section (const struct objfile *objfile) const
+{
+ if (section_index () >= 0)
+ return &objfile->sections[section_index ()];
+ return nullptr;
+}
+
+/* See symtab.h. */
+
bool
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);
+ = language_def (gsymbol->language ())->get_symbol_name_matcher (name);
return name_match (gsymbol->search_name (), name, NULL);
}
for (objfile *objfile : current_program_space->objfiles ())
{
- struct compunit_symtab *cust = NULL;
-
- if (objfile->sf)
- cust = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile, msymbol,
- pc, section, 0);
+ struct compunit_symtab *cust
+ = objfile->find_pc_sect_compunit_symtab (msymbol, pc, section, 0);
if (cust)
return;
}
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);
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;
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);
}
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;
/* If the cache hasn't been created yet, avoid creating one. */
cache = symbol_cache_key.get (pspace);
if (cache == NULL)
- printf_filtered (" empty, no stats available\n");
+ printf_filtered (" empty, no stats available\n");
else
symbol_cache_stats (cache);
}
msym = lookup_minimal_symbol_by_pc_name (addr, ginfo->linkage_name (),
objfile);
if (msym)
- ginfo->section = MSYMBOL_SECTION (msym);
+ ginfo->set_section_index (msym->section_index ());
else
{
/* Static, function-local variables do appear in the linker
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;
- if (obj_section_addr (s) - offset <= addr
- && addr < obj_section_endaddr (s) - offset)
+ if (s->addr () - offset <= addr && addr < s->endaddr () - offset)
{
- ginfo->section = idx;
+ ginfo->set_section_index (idx);
return;
}
}
section. If there is no allocated section, then it hardly
matters what we pick, so just pick zero. */
if (fallback == -1)
- ginfo->section = 0;
+ ginfo->set_section_index (0);
else
- ginfo->section = fallback;
+ ginfo->set_section_index (fallback);
}
}
if (objfile == NULL)
objfile = symbol_objfile (sym);
- if (SYMBOL_OBJ_SECTION (objfile, sym))
+ if (sym->obj_section (objfile) != nullptr)
return sym;
/* We should have an objfile by now. */
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;
lookup, so we can always binary search. */
if (lang == language_cplus)
{
- char *demangled_name = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+ gdb::unique_xmalloc_ptr<char> demangled_name
+ = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
if (demangled_name != NULL)
- return storage.set_malloc_ptr (demangled_name);
+ return storage.set_malloc_ptr (std::move (demangled_name));
/* 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<char> canon = cp_canonicalize_string (name);
+ if (canon != nullptr)
+ return storage.set_malloc_ptr (std::move (canon));
}
else if (lang == language_d)
{
- char *demangled_name = d_demangle (name, 0);
+ gdb::unique_xmalloc_ptr<char> demangled_name = d_demangle (name, 0);
if (demangled_name != NULL)
- return storage.set_malloc_ptr (demangled_name);
+ return storage.set_malloc_ptr (std::move (demangled_name));
}
else if (lang == language_go)
{
- char *demangled_name = go_demangle (name, 0);
+ gdb::unique_xmalloc_ptr<char> demangled_name
+ = language_def (language_go)->demangle_symbol (name, 0);
if (demangled_name != NULL)
- return storage.set_malloc_ptr (demangled_name);
+ return storage.set_malloc_ptr (std::move (demangled_name));
}
return name;
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.
lookup_language_this (const struct language_defn *lang,
const struct block *block)
{
- if (lang->la_name_of_this == NULL || block == NULL)
+ if (lang->name_of_this () == NULL || block == NULL)
return {};
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))",
- lang->la_name, host_address_to_string (block),
+ lang->name (), host_address_to_string (block),
objfile_debug_name (objfile));
}
{
struct symbol *sym;
- sym = block_lookup_symbol (block, lang->la_name_of_this,
+ sym = block_lookup_symbol (block, lang->name_of_this (),
symbol_name_match_type::SEARCH_NAME,
VAR_DOMAIN);
if (sym != NULL)
/* 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);
+ const char *t_field_name = type->field (i).name ();
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;
}
}
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",
/* 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->is_pointer_or_reference ())
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);
+ langdef->name_of_this ());
if (check_field (t, name, is_a_field_of_this))
{
/* Now do whatever is appropriate for LANGUAGE to look
up static and global variables. */
- result = langdef->la_lookup_symbol_nonlocal (langdef, name, block, domain);
+ result = langdef->lookup_symbol_nonlocal (name, block, domain);
if (result.symbol != NULL)
{
if (symbol_lookup_debug)
return (struct block_symbol) {sym, block};
if (language == language_cplus || language == language_fortran)
- {
- struct block_symbol blocksym
+ {
+ struct block_symbol blocksym
= cp_lookup_symbol_imports_or_template (scope, name, block,
domain);
- if (blocksym.symbol != NULL)
- return blocksym;
- }
+ if (blocksym.symbol != NULL)
+ return blocksym;
+ }
if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block))
break;
/* 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,
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)",
for (objfile *objfile : main_objfile->separate_debug_objfiles ())
{
struct block_symbol result
- = lookup_symbol_in_objfile (objfile, block_index, name, domain);
+ = lookup_symbol_in_objfile (objfile, block_index, name, domain);
if (result.symbol != nullptr)
return result;
name, domain_name (domain));
}
+ struct block_symbol other;
+ other.symbol = NULL;
for (compunit_symtab *cust : objfile->compunits ())
{
const struct blockvector *bv;
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)
const struct block *block;
struct block_symbol result;
- if (!objfile->sf)
- return {};
-
if (symbol_lookup_debug > 1)
{
fprintf_unfiltered (gdb_stdlog,
name, domain_name (domain));
}
- cust = objfile->sf->qf->lookup_symbol (objfile, block_index, name, domain);
+ cust = objfile->lookup_symbol (block_index, name, domain);
if (cust == NULL)
{
if (symbol_lookup_debug > 1)
return result;
}
-/* See symtab.h. */
+/* See language.h. */
struct block_symbol
-basic_lookup_symbol_nonlocal (const struct language_defn *langdef,
- const char *name,
- const struct block *block,
- const domain_enum domain)
+language_defn::lookup_symbol_nonlocal (const char *name,
+ const struct block *block,
+ const domain_enum domain) const
{
struct block_symbol result;
gdbarch = target_gdbarch ();
else
gdbarch = block_gdbarch (block);
- result.symbol = language_lookup_primitive_type_as_symbol (langdef,
+ result.symbol = language_lookup_primitive_type_as_symbol (this,
gdbarch, name);
result.block = NULL;
if (result.symbol != NULL)
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),"
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 ())
+ {
+ bool symbol_found_p;
+ enum language lang
+ = objfile->lookup_global_symbol_language (name, domain, &symbol_found_p);
+ if (symbol_found_p)
+ return lang;
+ }
+
+ return language_unknown;
+}
+
/* Private data to be used with lookup_symbol_global_iterator_cb. */
struct global_or_static_sym_lookup_data
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;
}
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
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
const struct block *block;
struct symbol *sym;
- if (!objfile->sf)
- return NULL;
- cust = objfile->sf->qf->lookup_symbol (objfile, block_index, name,
- STRUCT_DOMAIN);
+ cust = objfile->lookup_symbol (block_index, name, STRUCT_DOMAIN);
if (cust == NULL)
return NULL;
find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
{
struct compunit_symtab *best_cust = NULL;
- CORE_ADDR distance = 0;
+ CORE_ADDR best_cust_range = 0;
struct bound_minimal_symbol msymbol;
/* If we know that this is not a text address, return failure. This is
{
for (compunit_symtab *cust : obj_file->compunits ())
{
- const struct block *b;
- const struct blockvector *bv;
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust);
+ const struct block *global_block
+ = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ CORE_ADDR start = BLOCK_START (global_block);
+ CORE_ADDR end = BLOCK_END (global_block);
+ bool in_range_p = start <= pc && pc < end;
+ if (!in_range_p)
+ continue;
+
+ if (BLOCKVECTOR_MAP (bv))
+ {
+ if (addrmap_find (BLOCKVECTOR_MAP (bv), pc) == nullptr)
+ continue;
- bv = COMPUNIT_BLOCKVECTOR (cust);
- b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ return cust;
+ }
- if (BLOCK_START (b) <= pc
- && BLOCK_END (b) > pc
- && (distance == 0
- || BLOCK_END (b) - BLOCK_START (b) < distance))
+ CORE_ADDR range = end - start;
+ if (best_cust != nullptr
+ && range >= best_cust_range)
+ /* Cust doesn't have a smaller range than best_cust, skip it. */
+ continue;
+
+ /* For an objfile that has its functions reordered,
+ find_pc_psymtab will find the proper partial symbol table
+ and we simply return its corresponding symtab. */
+ /* In order to better support objfiles that contain both
+ stabs and coff debugging info, we continue on if a psymtab
+ can't be found. */
+ if ((obj_file->flags & OBJF_REORDERED) != 0)
{
- /* For an objfile that has its functions reordered,
- find_pc_psymtab will find the proper partial symbol table
- and we simply return its corresponding symtab. */
- /* In order to better support objfiles that contain both
- stabs and coff debugging info, we continue on if a psymtab
- can't be found. */
- if ((obj_file->flags & OBJF_REORDERED) && obj_file->sf)
- {
- struct compunit_symtab *result;
-
- result
- = obj_file->sf->qf->find_pc_sect_compunit_symtab (obj_file,
- msymbol,
- pc,
- section,
- 0);
- if (result != NULL)
- return result;
- }
- if (section != 0)
- {
- struct block_iterator iter;
- struct symbol *sym = NULL;
+ struct compunit_symtab *result;
+
+ result
+ = obj_file->find_pc_sect_compunit_symtab (msymbol,
+ pc,
+ section,
+ 0);
+ if (result != NULL)
+ return result;
+ }
+ if (section != 0)
+ {
+ struct symbol *sym = NULL;
+ struct block_iterator iter;
+
+ for (int b_index = GLOBAL_BLOCK;
+ b_index <= STATIC_BLOCK && sym == NULL;
+ ++b_index)
+ {
+ const struct block *b = BLOCKVECTOR_BLOCK (bv, b_index);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
fixup_symbol_section (sym, obj_file);
- if (matching_obj_sections (SYMBOL_OBJ_SECTION (obj_file,
- sym),
+ if (matching_obj_sections (sym->obj_section (obj_file),
section))
break;
}
- if (sym == NULL)
- continue; /* No symbol in this symtab matches
- section. */
}
- distance = BLOCK_END (b) - BLOCK_START (b);
- best_cust = cust;
+ if (sym == NULL)
+ continue; /* No symbol in this symtab matches
+ section. */
}
+
+ /* Cust is best found sofar, save it. */
+ best_cust = cust;
+ best_cust_range = range;
}
}
for (objfile *objf : current_program_space->objfiles ())
{
- struct compunit_symtab *result;
-
- if (!objf->sf)
- continue;
- result = objf->sf->qf->find_pc_sect_compunit_symtab (objf,
- msymbol,
- pc, section,
- 1);
+ struct compunit_symtab *result
+ = objf->find_pc_sect_compunit_symtab (msymbol, pc, section, 1);
if (result != NULL)
return result;
}
struct symbol *
find_symbol_at_address (CORE_ADDR address)
{
- for (objfile *objfile : current_program_space->objfiles ())
+ /* A helper function to search a given symtab for a symbol matching
+ ADDR. */
+ auto search_symtab = [] (compunit_symtab *symtab, CORE_ADDR addr) -> symbol *
{
- if (objfile->sf == NULL
- || objfile->sf->qf->find_compunit_symtab_by_address == NULL)
- continue;
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (symtab);
- struct compunit_symtab *symtab
- = objfile->sf->qf->find_compunit_symtab_by_address (objfile, address);
- if (symtab != NULL)
+ for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
{
- const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (symtab);
+ const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
- for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
- struct block_iterator iter;
- struct symbol *sym;
+ if (SYMBOL_CLASS (sym) == LOC_STATIC
+ && SYMBOL_VALUE_ADDRESS (sym) == addr)
+ return sym;
+ }
+ }
+ return nullptr;
+ };
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- if (SYMBOL_CLASS (sym) == LOC_STATIC
- && SYMBOL_VALUE_ADDRESS (sym) == address)
- return sym;
- }
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ /* If this objfile was read with -readnow, then we need to
+ search the symtabs directly. */
+ if ((objfile->flags & OBJF_READNOW) != 0)
+ {
+ for (compunit_symtab *symtab : objfile->compunits ())
+ {
+ struct symbol *sym = search_symtab (symtab, address);
+ if (sym != nullptr)
+ return sym;
+ }
+ }
+ else
+ {
+ struct compunit_symtab *symtab
+ = objfile->find_compunit_symtab_by_address (address);
+ if (symtab != NULL)
+ {
+ struct symbol *sym = search_symtab (symtab, address);
+ if (sym != nullptr)
+ return sym;
}
}
}
;
/* 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;
item = l->item; /* Get first line info. */
/* Is this file's first line closer than the first lines of other files?
- If so, record this file, and its first line, as best alternate. */
+ If so, record this file, and its first line, as best alternate. */
if (item->pc > pc && (!alt || item->pc < alt->pc))
alt = item;
prev = item - 1; /* Found a matching item. */
/* 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
- (pc >= start of the last line), then prev == item. If pc < start of
- the first line, prev will not be set. */
+ item points at the next line. If we ran off the end of the linetable
+ (pc >= start of the last line), then prev == item. If pc < start of
+ the first line, prev will not be set. */
/* Is this file's best line closer than the best in the other files?
- If so, record this file, and its best line, as best so far. Don't
- save prev if it represents the end of a function (i.e. line number
- 0) instead of a real line. */
+ If so, record this file, and its best line, as best so far. Don't
+ save prev if it represents the end of a function (i.e. line number
+ 0) instead of a real line. */
if (prev && prev->line && (!best || prev->pc > best->pc))
{
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 obj_section *section;
section = find_pc_overlay (pc);
- if (pc_in_unmapped_range (pc, section))
- pc = overlay_mapped_address (pc, section);
- return find_pc_sect_line (pc, section, notcurrent);
+ if (!pc_in_unmapped_range (pc, section))
+ return find_pc_sect_line (pc, section, notcurrent);
+
+ /* If the original PC was an unmapped address then we translate this to a
+ mapped address in order to lookup the sal. However, as the user
+ passed us an unmapped address it makes more sense to return a result
+ that has the pc and end fields translated to unmapped addresses. */
+ pc = overlay_mapped_address (pc, section);
+ symtab_and_line sal = find_pc_sect_line (pc, section, notcurrent);
+ sal.pc = overlay_unmapped_address (sal.pc, section);
+ sal.end = overlay_unmapped_address (sal.end, section);
+ return sal;
}
/* See symtab.h. */
if (best_index < 0 || !exact)
{
/* Didn't find an exact match. So we better keep looking for
- another symtab with the same name. In the case of xcoff,
- multiple csects for one source file (produced by IBM's FORTRAN
- compiler) produce multiple symtabs (this is unavoidable
- assuming csects can be at arbitrary places in memory and that
- the GLOBAL_BLOCK of a symtab has a begin and end address). */
+ another symtab with the same name. In the case of xcoff,
+ multiple csects for one source file (produced by IBM's FORTRAN
+ compiler) produce multiple symtabs (this is unavoidable
+ assuming csects can be at arbitrary places in memory and that
+ the GLOBAL_BLOCK of a symtab has a begin and end address). */
/* BEST is the smallest linenumber > LINE so far seen,
- or 0 if none has been seen so far.
- BEST_INDEX and BEST_LINETABLE identify the item for it. */
+ or 0 if none has been seen so far.
+ BEST_INDEX and BEST_LINETABLE identify the item for it. */
int best;
if (best_index >= 0)
best = 0;
for (objfile *objfile : current_program_space->objfiles ())
- {
- if (objfile->sf)
- objfile->sf->qf->expand_symtabs_with_fullname
- (objfile, symtab_to_fullname (sym_tab));
- }
+ objfile->expand_symtabs_with_fullname (symtab_to_fullname (sym_tab));
for (objfile *objfile : current_program_space->objfiles ())
{
{
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. */
&& (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))
fixup_symbol_section (sym, NULL);
symtab_and_line sal
= find_function_start_sal_1 (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)),
- SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym),
+ sym->obj_section (symbol_objfile (sym)),
funfirstline);
sal.symbol = sym;
return sal;
objfile = symbol_objfile (sym);
pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
- section = SYMBOL_OBJ_SECTION (objfile, sym);
+ section = sym->obj_section (objfile);
name = sym->linkage_name ();
}
else
{
struct bound_minimal_symbol msymbol
- = lookup_minimal_symbol_by_pc_section (sal->pc, sal->section);
+ = lookup_minimal_symbol_by_pc_section (sal->pc, sal->section);
if (msymbol.minsym == NULL)
return;
objfile = msymbol.objfile;
pc = BMSYMBOL_VALUE_ADDRESS (msymbol);
- section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
+ section = msymbol.minsym->obj_section (objfile);
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
/* Skip "first line" of function (which is actually its prologue). */
pc += gdbarch_deprecated_function_start_offset (gdbarch);
if (gdbarch_skip_entrypoint_p (gdbarch))
- pc = gdbarch_skip_entrypoint (gdbarch, pc);
+ pc = gdbarch_skip_entrypoint (gdbarch, pc);
if (skip)
pc = gdbarch_skip_prologue_noexcept (gdbarch, pc);
}
\f
-/* What part to match in a file name. */
+/* See class declaration. */
-struct filename_partial_match_opts
+info_sources_filter::info_sources_filter (match_on match_type,
+ const char *regexp)
+ : m_match_type (match_type),
+ m_regexp (regexp)
{
- /* Only match the directory name part. */
- bool dirname = false;
+ /* Setup the compiled regular expression M_C_REGEXP based on M_REGEXP. */
+ if (m_regexp != nullptr && *m_regexp != '\0')
+ {
+ gdb_assert (m_regexp != nullptr);
- /* Only match the basename part. */
- bool basename = false;
-};
+ int cflags = REG_NOSUB;
+#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+ cflags |= REG_ICASE;
+#endif
+ m_c_regexp.emplace (m_regexp, cflags, _("Invalid regexp"));
+ }
+}
+
+/* See class declaration. */
-/* Data structure to maintain printing state for output_source_filename. */
+bool
+info_sources_filter::matches (const char *fullname) const
+{
+ /* Does it match regexp? */
+ if (m_c_regexp.has_value ())
+ {
+ const char *to_match;
+ std::string dirname;
+
+ switch (m_match_type)
+ {
+ case match_on::DIRNAME:
+ dirname = ldirname (fullname);
+ to_match = dirname.c_str ();
+ break;
+ case match_on::BASENAME:
+ to_match = lbasename (fullname);
+ break;
+ case match_on::FULLNAME:
+ to_match = fullname;
+ break;
+ default:
+ gdb_assert_not_reached ("bad m_match_type");
+ }
+
+ if (m_c_regexp->exec (to_match, 0, NULL, 0) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+/* Data structure to maintain the state used for printing the results of
+ the 'info sources' command. */
struct output_source_filename_data
{
- /* Output only filenames matching REGEXP. */
- std::string regexp;
- gdb::optional<compiled_regex> c_regexp;
- /* Possibly only match a part of the filename. */
- filename_partial_match_opts partial_match;
+ /* Create an object for displaying the results of the 'info sources'
+ command to UIOUT. FILTER must remain valid and unchanged for the
+ lifetime of this object as this object retains a reference to FILTER. */
+ output_source_filename_data (struct ui_out *uiout,
+ const info_sources_filter &filter)
+ : m_filter (filter),
+ m_uiout (uiout)
+ { /* Nothing. */ }
+ DISABLE_COPY_AND_ASSIGN (output_source_filename_data);
- /* Cache of what we've seen so far. */
- struct filename_seen_cache *filename_seen_cache;
+ /* Reset enough state of this object so we can match against a new set of
+ files. The existing regular expression is retained though. */
+ void reset_output ()
+ {
+ m_first = true;
+ m_filename_seen_cache.clear ();
+ }
+
+ /* Worker for sources_info, outputs the file name formatted for either
+ cli or mi (based on the current_uiout). In cli mode displays
+ FULLNAME with a comma separating this name from any previously
+ printed name (line breaks are added at the comma). In MI mode
+ outputs a tuple containing DISP_NAME (the files display name),
+ FULLNAME, and EXPANDED_P (true when this file is from a fully
+ expanded symtab, otherwise false). */
+ void output (const char *disp_name, const char *fullname, bool expanded_p);
+
+ /* An overload suitable for use as a callback to
+ quick_symbol_functions::map_symbol_filenames. */
+ void operator() (const char *filename, const char *fullname)
+ {
+ /* The false here indicates that this file is from an unexpanded
+ symtab. */
+ output (filename, fullname, false);
+ }
+
+ /* Return true if at least one filename has been printed (after a call to
+ output) since either this object was created, or the last call to
+ reset_output. */
+ bool printed_filename_p () const
+ {
+ return !m_first;
+ }
+
+private:
/* Flag of whether we're printing the first one. */
- int first;
+ bool m_first = true;
+
+ /* Cache of what we've seen so far. */
+ filename_seen_cache m_filename_seen_cache;
+
+ /* How source filename should be filtered. */
+ const info_sources_filter &m_filter;
+
+ /* The object to which output is sent. */
+ struct ui_out *m_uiout;
};
-/* Slave routine for sources_info. Force line breaks at ,'s.
- NAME is the name to print.
- DATA contains the state for printing and watching for duplicates. */
+/* See comment in class declaration above. */
-static void
-output_source_filename (const char *name,
- struct output_source_filename_data *data)
+void
+output_source_filename_data::output (const char *disp_name,
+ const char *fullname,
+ bool expanded_p)
{
/* Since a single source file can result in several partial symbol
tables, we need to avoid printing it more than once. Note: if
situation. I'm not sure whether this can also happen for
symtabs; it doesn't hurt to check. */
- /* Was NAME already seen? */
- if (data->filename_seen_cache->seen (name))
- {
- /* Yes; don't print it again. */
- return;
- }
-
- /* Does it match data->regexp? */
- if (data->c_regexp.has_value ())
- {
- const char *to_match;
- std::string dirname;
+ /* Was NAME already seen? If so, then don't print it again. */
+ if (m_filename_seen_cache.seen (fullname))
+ return;
- if (data->partial_match.dirname)
- {
- dirname = ldirname (name);
- to_match = dirname.c_str ();
- }
- else if (data->partial_match.basename)
- to_match = lbasename (name);
- else
- to_match = name;
+ /* If the filter rejects this file then don't print it. */
+ if (!m_filter.matches (fullname))
+ return;
- if (data->c_regexp->exec (to_match, 0, NULL, 0) != 0)
- return;
- }
+ ui_out_emit_tuple ui_emitter (m_uiout, nullptr);
/* Print it and reset *FIRST. */
- if (! data->first)
- printf_filtered (", ");
- data->first = 0;
+ if (!m_first)
+ m_uiout->text (", ");
+ m_first = false;
wrap_here ("");
- fputs_styled (name, file_name_style.style (), gdb_stdout);
+ if (m_uiout->is_mi_like_p ())
+ {
+ m_uiout->field_string ("file", disp_name, file_name_style.style ());
+ if (fullname != nullptr)
+ m_uiout->field_string ("fullname", fullname,
+ file_name_style.style ());
+ m_uiout->field_string ("debug-fully-read",
+ (expanded_p ? "true" : "false"));
+ }
+ else
+ {
+ if (fullname == nullptr)
+ fullname = disp_name;
+ m_uiout->field_string ("fullname", fullname,
+ file_name_style.style ());
+ }
}
-/* A callback for map_partial_symbol_filenames. */
+/* For the 'info sources' command, what part of the file names should we be
+ matching the user supplied regular expression against? */
-static void
-output_partial_symbol_filename (const char *filename, const char *fullname,
- void *data)
+struct filename_partial_match_opts
{
- output_source_filename (fullname ? fullname : filename,
- (struct output_source_filename_data *) data);
-}
+ /* Only match the directory name part. */
+ bool dirname = false;
+
+ /* Only match the basename part. */
+ bool basename = false;
+};
using isrc_flag_option_def
= gdb::option::flag_option_def<filename_partial_match_opts>;
return {{info_sources_option_defs}, isrc_opts};
}
-/* Prints the header message for the source files that will be printed
- with the matching info present in DATA. SYMBOL_MSG is a message
- that tells what will or has been done with the symbols of the
- matching source files. */
-
-static void
-print_info_sources_header (const char *symbol_msg,
- const struct output_source_filename_data *data)
-{
- puts_filtered (symbol_msg);
- if (!data->regexp.empty ())
- {
- if (data->partial_match.dirname)
- printf_filtered (_("(dirname matching regular expression \"%s\")"),
- data->regexp.c_str ());
- else if (data->partial_match.basename)
- printf_filtered (_("(basename matching regular expression \"%s\")"),
- data->regexp.c_str ());
- else
- printf_filtered (_("(filename matching regular expression \"%s\")"),
- data->regexp.c_str ());
- }
- puts_filtered ("\n");
-}
-
/* Completer for "info sources". */
static void
return;
}
-static void
-info_sources_command (const char *args, int from_tty)
-{
- struct output_source_filename_data data;
-
- if (!have_full_symbols () && !have_partial_symbols ())
- {
- error (_("No symbol table is loaded. Use the \"file\" command."));
- }
-
- filename_seen_cache filenames_seen;
-
- auto group = make_info_sources_options_def_group (&data.partial_match);
-
- gdb::option::process_options
- (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
+/* See symtab.h. */
- if (args != NULL && *args != '\000')
- data.regexp = args;
+void
+info_sources_worker (struct ui_out *uiout,
+ bool group_by_objfile,
+ const info_sources_filter &filter)
+{
+ output_source_filename_data data (uiout, filter);
- data.filename_seen_cache = &filenames_seen;
- data.first = 1;
+ ui_out_emit_list results_emitter (uiout, "files");
+ gdb::optional<ui_out_emit_tuple> output_tuple;
+ gdb::optional<ui_out_emit_list> sources_list;
- if (data.partial_match.dirname && data.partial_match.basename)
- error (_("You cannot give both -basename and -dirname to 'info sources'."));
- if ((data.partial_match.dirname || data.partial_match.basename)
- && data.regexp.empty ())
- error (_("Missing REGEXP for 'info sources'."));
-
- if (data.regexp.empty ())
- data.c_regexp.reset ();
- else
- {
- int cflags = REG_NOSUB;
-#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
- cflags |= REG_ICASE;
-#endif
- data.c_regexp.emplace (data.regexp.c_str (), cflags,
- _("Invalid regexp"));
- }
-
- print_info_sources_header
- (_("Source files for which symbols have been read in:\n"), &data);
+ gdb_assert (group_by_objfile || uiout->is_mi_like_p ());
for (objfile *objfile : current_program_space->objfiles ())
{
+ if (group_by_objfile)
+ {
+ output_tuple.emplace (uiout, nullptr);
+ uiout->field_string ("filename", objfile_name (objfile));
+ uiout->text (":\n");
+ bool debug_fully_readin = !objfile->has_unexpanded_symtabs ();
+ if (uiout->is_mi_like_p ())
+ {
+ const char *debug_info_state;
+ if (objfile_has_symbols (objfile))
+ {
+ if (debug_fully_readin)
+ debug_info_state = "fully-read";
+ else
+ debug_info_state = "partially-read";
+ }
+ else
+ debug_info_state = "none";
+ current_uiout->field_string ("debug-info", debug_info_state);
+ }
+ else
+ {
+ if (!debug_fully_readin)
+ uiout->text ("(Full debug information has not yet been read "
+ "for this file.)\n");
+ if (!objfile_has_symbols (objfile))
+ uiout->text ("(Objfile has no debug information.)\n");
+ uiout->text ("\n");
+ }
+ sources_list.emplace (uiout, "sources");
+ }
+
for (compunit_symtab *cu : objfile->compunits ())
{
for (symtab *s : compunit_filetabs (cu))
{
+ const char *file = symtab_to_filename_for_display (s);
const char *fullname = symtab_to_fullname (s);
-
- output_source_filename (fullname, &data);
+ data.output (file, fullname, true);
}
}
+
+ if (group_by_objfile)
+ {
+ objfile->map_symbol_filenames (data, true /* need_fullname */);
+ if (data.printed_filename_p ())
+ uiout->text ("\n\n");
+ data.reset_output ();
+ sources_list.reset ();
+ output_tuple.reset ();
+ }
}
- printf_filtered ("\n\n");
- print_info_sources_header
- (_("Source files for which symbols will be read in on demand:\n"), &data);
+ if (!group_by_objfile)
+ {
+ data.reset_output ();
+ map_symbol_filenames (data, true /*need_fullname*/);
+ }
+}
+
+/* Implement the 'info sources' command. */
+
+static void
+info_sources_command (const char *args, int from_tty)
+{
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error (_("No symbol table is loaded. Use the \"file\" command."));
+
+ filename_partial_match_opts match_opts;
+ auto group = make_info_sources_options_def_group (&match_opts);
+ gdb::option::process_options
+ (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
+
+ if (match_opts.dirname && match_opts.basename)
+ error (_("You cannot give both -basename and -dirname to 'info sources'."));
+
+ const char *regex = nullptr;
+ if (args != NULL && *args != '\000')
+ regex = args;
+
+ if ((match_opts.dirname || match_opts.basename) && regex == nullptr)
+ error (_("Missing REGEXP for 'info sources'."));
+
+ info_sources_filter::match_on match_type;
+ if (match_opts.dirname)
+ match_type = info_sources_filter::match_on::DIRNAME;
+ else if (match_opts.basename)
+ match_type = info_sources_filter::match_on::BASENAME;
+ else
+ match_type = info_sources_filter::match_on::FULLNAME;
- filenames_seen.clear ();
- data.first = 1;
- map_symbol_filenames (output_partial_symbol_filename, &data,
- 1 /*need_fullname*/);
- printf_filtered ("\n");
+ info_sources_filter filter (match_type, regex);
+ info_sources_worker (current_uiout, true, filter);
}
/* Compare FILE against all the entries of FILENAMES. If BASENAMES is
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);
+ auto do_file_match = [&] (const char *filename, bool basenames)
+ {
+ return file_matches (filename, filenames, basenames);
+ };
+ gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher = nullptr;
+ if (!filenames.empty ())
+ file_matcher = do_file_match;
+
+ objfile->expand_symtabs_matching
+ (file_matcher,
+ &lookup_name_info::match_any (),
+ [&] (const char *symname)
+ {
+ return (!preg.has_value ()
+ || preg->exec (symname, 0, NULL, 0) == 0);
+ },
+ NULL,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ UNDEF_DOMAIN,
+ 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
members. We only want to skip enums
here. */
&& !(SYMBOL_CLASS (sym) == LOC_CONST
- && (TYPE_CODE (SYMBOL_TYPE (sym))
+ && (SYMBOL_TYPE (sym)->code ()
== TYPE_CODE_ENUM))
&& (!treg.has_value ()
|| treg_matches_sym_type_name (*treg, sym)))
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>. */
+ 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 (symbol_name_regexp, &opend);
if (*opname)
{
int fix = -1; /* -1 means ok; otherwise number of
- spaces needed. */
+ spaces needed. */
if (isalpha (*opname) || *opname == '_' || *opname == '$')
{
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)
+ if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_TYPEDEF)
typedef_print (SYMBOL_TYPE (sym), sym, &tmp_stream);
else
type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1);
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)
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 ()
- {
- xfree (type_regexp);
- }
+ std::string 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')
args = nullptr;
- symtab_symbol_info (opts.quiet, opts.exclude_minsyms, args, VARIABLES_DOMAIN,
- opts.type_regexp, from_tty);
+ symtab_symbol_info
+ (opts.quiet, opts.exclude_minsyms, args, VARIABLES_DOMAIN,
+ opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+ from_tty);
}
/* Implement the 'info functions' command. */
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')
args = nullptr;
- symtab_symbol_info (opts.quiet, opts.exclude_minsyms, args,
- FUNCTIONS_DOMAIN, opts.type_regexp, from_tty);
+ symtab_symbol_info
+ (opts.quiet, opts.exclude_minsyms, args, FUNCTIONS_DOMAIN,
+ opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+ from_tty);
}
/* Holds the -q option for the 'info types' command. */
{
const char *colon = strchr (regexp, ':');
+ /* Ignore the colon if it is part of a Windows drive. */
+ if (HAS_DRIVE_SPEC (regexp)
+ && (regexp[2] == '/' || regexp[2] == '\\'))
+ colon = strchr (STRIP_DRIVE_SPEC (regexp), ':');
+
if (colon && *(colon + 1) != ':')
{
int colon_index;
const language_defn *lang = language_def (symbol_language);
symbol_name_matcher_ftype *name_match
- = get_symbol_name_matcher (lang, lookup_name);
+ = lang->get_symbol_name_matcher (lookup_name);
return name_match (symbol_name, lookup_name, &match_res);
}
/* See symtab.h. */
-void
+bool
completion_list_add_name (completion_tracker &tracker,
language symbol_language,
const char *symname,
/* 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
tracker.add_completion (std::move (completion),
&match_res.match_for_lcd, text, word);
}
+
+ return true;
}
/* completion_list_add_name wrapper for struct symbol. */
const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, sym->language (),
- 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<char> 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. */
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++)
- if (TYPE_FIELD_NAME (t, j))
+ for (j = TYPE_N_BASECLASSES (t); j < t->num_fields (); j++)
+ if (t->field (j).name ())
completion_list_add_name (tracker, sym->language (),
- TYPE_FIELD_NAME (t, j),
+ t->field (j).name (),
lookup_name, text, word);
}
}
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:
CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym);
if (MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
{
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- msym_addr
- = gdbarch_convert_from_func_ptr_addr (gdbarch,
- msym_addr,
- current_top_target ());
+ struct gdbarch *gdbarch = objfile->arch ();
+ msym_addr = gdbarch_convert_from_func_ptr_addr
+ (gdbarch, msym_addr, current_inferior ()->top_target ());
}
if (msym_addr == address)
{
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);
if (mode == complete_symbol_mode::LINESPEC)
sym_text = text;
else
- {
- const char *p;
- char quote_found;
- const char *quote_pos = NULL;
+ {
+ const char *p;
+ char quote_found;
+ const char *quote_pos = NULL;
- /* First see if this is a quoted string. */
- quote_found = '\0';
- for (p = text; *p != '\0'; ++p)
- {
- if (quote_found != '\0')
- {
- if (*p == quote_found)
- /* Found close quote. */
- quote_found = '\0';
- else if (*p == '\\' && p[1] == quote_found)
- /* A backslash followed by the quote character
- doesn't end the string. */
- ++p;
- }
- else if (*p == '\'' || *p == '"')
- {
- quote_found = *p;
- quote_pos = p;
- }
- }
- if (quote_found == '\'')
- /* A string within single quotes can be a symbol, so complete on it. */
- sym_text = quote_pos + 1;
- else if (quote_found == '"')
- /* A double-quoted string is never a symbol, nor does it make sense
- to complete it any other way. */
- {
- return;
- }
- else
- {
- /* It is not a quoted string. Break it based on the characters
- which are in symbols. */
- while (p > text)
- {
- if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
- || p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
- --p;
- else
- break;
- }
- sym_text = p;
- }
- }
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ {
+ return;
+ }
+ else
+ {
+ /* It is not a quoted string. Break it based on the characters
+ which are in symbols. */
+ while (p > text)
+ {
+ if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
+ || p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
+ --p;
+ else
+ break;
+ }
+ sym_text = p;
+ }
+ }
lookup_name_info lookup_name (sym_text, name_match_type, true);
add_symtab_completions (symtab,
tracker, mode, lookup_name,
sym_text, word, code);
+ return true;
},
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
ALL_DOMAIN);
/* Search upwards from currently selected frame (so that we can
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);
}
/* Skip macros if we are completing a struct tag -- arguable but
usually what is expected. */
- if (current_language->la_macro_expansion == macro_expansion_c
+ if (current_language->macro_expansion () == macro_expansion_c
&& code == TYPE_CODE_UNDEF)
{
gdb::unique_xmalloc_ptr<struct macro_scope> scope;
}
}
-void
-default_collect_symbol_completion_matches (completion_tracker &tracker,
- complete_symbol_mode mode,
- symbol_name_match_type name_match_type,
- const char *text, const char *word,
- enum type_code code)
-{
- return default_collect_symbol_completion_matches_break_on (tracker, mode,
- name_match_type,
- text, word, "",
- code);
-}
-
/* Collect all symbols (regardless of class) which begin by matching
TEXT. */
symbol_name_match_type name_match_type,
const char *text, const char *word)
{
- current_language->la_collect_symbol_completion_matches (tracker, mode,
- name_match_type,
- text, word,
- TYPE_CODE_UNDEF);
+ current_language->collect_symbol_completion_matches (tracker, mode,
+ name_match_type,
+ text, word,
+ TYPE_CODE_UNDEF);
}
/* Like collect_symbol_completion_matches, but only collect
gdb_assert (code == TYPE_CODE_UNION
|| code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_ENUM);
- current_language->la_collect_symbol_completion_matches (tracker, mode,
- name_match_type,
- text, word, code);
+ current_language->collect_symbol_completion_matches (tracker, mode,
+ name_match_type,
+ text, word, code);
}
/* Like collect_symbol_completion_matches, but collects a list of
if (mode == complete_symbol_mode::LINESPEC)
sym_text = text;
else
- {
- const char *p;
- char quote_found;
- const char *quote_pos = NULL;
+ {
+ const char *p;
+ char quote_found;
+ const char *quote_pos = NULL;
- /* First see if this is a quoted string. */
- quote_found = '\0';
- for (p = text; *p != '\0'; ++p)
- {
- if (quote_found != '\0')
- {
- if (*p == quote_found)
- /* Found close quote. */
- quote_found = '\0';
- else if (*p == '\\' && p[1] == quote_found)
- /* A backslash followed by the quote character
- doesn't end the string. */
- ++p;
- }
- else if (*p == '\'' || *p == '"')
- {
- quote_found = *p;
- quote_pos = p;
- }
- }
- if (quote_found == '\'')
- /* A string within single quotes can be a symbol, so complete on it. */
- sym_text = quote_pos + 1;
- else if (quote_found == '"')
- /* A double-quoted string is never a symbol, nor does it make sense
- to complete it any other way. */
- {
- return;
- }
- else
- {
- /* Not a quoted string. */
- sym_text = language_search_unquoted_string (text, p);
- }
- }
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ {
+ return;
+ }
+ else
+ {
+ /* Not a quoted string. */
+ sym_text = language_search_unquoted_string (text, p);
+ }
+ }
lookup_name_info lookup_name (sym_text, name_match_type, true);
return 0;
}
-/* An object of this type is passed as the user_data argument to
+/* An object of this type is passed as the callback argument to
map_partial_symbol_filenames. */
struct add_partial_filename_data
{
const char *word;
int text_len;
completion_list *list;
+
+ void operator() (const char *filename, const char *fullname);
};
/* A callback for map_partial_symbol_filenames. */
-static void
-maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
- void *user_data)
+void
+add_partial_filename_data::operator() (const char *filename,
+ const char *fullname)
{
- struct add_partial_filename_data *data
- = (struct add_partial_filename_data *) user_data;
-
if (not_interesting_fname (filename))
return;
- if (!data->filename_seen_cache->seen (filename)
- && filename_ncmp (filename, data->text, data->text_len) == 0)
+ if (!filename_seen_cache->seen (filename)
+ && filename_ncmp (filename, text, text_len) == 0)
{
/* This file matches for a completion; add it to the
current list of matches. */
- add_filename_to_list (filename, data->text, data->word, data->list);
+ add_filename_to_list (filename, text, word, list);
}
else
{
const char *base_name = lbasename (filename);
if (base_name != filename
- && !data->filename_seen_cache->seen (base_name)
- && filename_ncmp (base_name, data->text, data->text_len) == 0)
- add_filename_to_list (base_name, data->text, data->word, data->list);
+ && !filename_seen_cache->seen (base_name)
+ && filename_ncmp (base_name, text, text_len) == 0)
+ add_filename_to_list (base_name, text, word, list);
}
}
datum.word = word;
datum.text_len = text_len;
datum.list = &list;
- map_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
- 0 /*need_fullname*/);
+ map_symbol_filenames (datum, false /*need_fullname*/);
return list;
}
/* 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);
}
"ARM/Thumb C/C++ Compiler, RVCT",
"ARM C/C++ Compiler, RVCT"
};
- int i;
if (producer == NULL)
return false;
- for (i = 0; i < ARRAY_SIZE (arm_idents); i++)
- if (startswith (producer, arm_idents[i]))
+ for (const char *ident : arm_idents)
+ if (startswith (producer, ident))
return true;
return false;
\f
-/* 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 *
{
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. */
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)
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 (minsym->value.address
- + ANOFFSET (objf->section_offsets, minsym->section));
+ + objf->section_offsets[minsym->section_index ()]);
}
\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>
struct info_modules_var_func_options
{
bool quiet = false;
- char *type_regexp = nullptr;
- char *module_regexp = nullptr;
-
- ~info_modules_var_func_options ()
- {
- xfree (type_regexp);
- xfree (module_regexp);
- }
+ std::string type_regexp;
+ std::string module_regexp;
};
/* The options used by 'info module variables' and 'info module functions'
if (args != nullptr && *args == '\0')
args = nullptr;
- info_module_subcommand (opts.quiet, opts.module_regexp, args,
- opts.type_regexp, FUNCTIONS_DOMAIN);
+ info_module_subcommand
+ (opts.quiet,
+ opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
+ opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+ FUNCTIONS_DOMAIN);
}
/* Implements the 'info module variables' command. */
if (args != nullptr && *args == '\0')
args = nullptr;
- info_module_subcommand (opts.quiet, opts.module_regexp, args,
- opts.type_regexp, VARIABLES_DOMAIN);
+ info_module_subcommand
+ (opts.quiet,
+ opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
+ opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+ VARIABLES_DOMAIN);
}
/* Command completer for 'info module ...' sub-commands. */
\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\
REGEXP is given. The optional flag -q disables printing of headers."));
set_cmd_completer_handle_brkchars (c, info_types_command_completer);
- const auto info_sources_opts = make_info_sources_options_def_group (nullptr);
+ const auto info_sources_opts
+ = make_info_sources_options_def_group (nullptr);
static std::string info_sources_help
= gdb::option::build_help (_("\
_("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, 0, &infolist);
c = add_cmd ("functions", class_info, info_module_functions_command, _("\
Display functions arranged by modules.\n\
_("Set a breakpoint for all functions matching REGEXP."));
add_setshow_enum_cmd ("multiple-symbols", no_class,
- multiple_symbols_modes, &multiple_symbols_mode,
- _("\
+ multiple_symbols_modes, &multiple_symbols_mode,
+ _("\
Set how the debugger handles ambiguities in expressions."), _("\
Show how the debugger handles ambiguities in expressions."), _("\
Valid values are \"ask\", \"all\", \"cancel\", and the default is \"all\"."),
- NULL, NULL, &setlist, &showlist);
+ NULL, NULL, &setlist, &showlist);
add_setshow_boolean_cmd ("basenames-may-differ", class_obscure,
&basenames_may_differ, _("\
_("Print symbol cache statistics for each program space."),
&maintenanceprintlist);
- add_cmd ("flush-symbol-cache", class_maintenance,
- maintenance_flush_symbol_cache,
- _("Flush the symbol cache for each program space."),
- &maintenancelist);
-
- gdb::observers::executable_changed.attach (symtab_observer_executable_changed);
- gdb::observers::new_objfile.attach (symtab_new_objfile_observer);
- gdb::observers::free_objfile.attach (symtab_free_objfile_observer);
+ cmd_list_element *maintenance_flush_symbol_cache_cmd
+ = add_cmd ("symbol-cache", class_maintenance,
+ maintenance_flush_symbol_cache,
+ _("Flush the symbol cache for each program space."),
+ &maintenanceflushlist);
+ c = add_alias_cmd ("flush-symbol-cache", maintenance_flush_symbol_cache_cmd,
+ class_maintenance, 0, &maintenancelist);
+ deprecate_cmd (c, "maintenancelist flush symbol-cache");
+
+ gdb::observers::executable_changed.attach (symtab_observer_executable_changed,
+ "symtab");
+ gdb::observers::new_objfile.attach (symtab_new_objfile_observer, "symtab");
+ gdb::observers::free_objfile.attach (symtab_free_objfile_observer, "symtab");
}