/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "cli/cli-utils.h"
#include "fnmatch.h"
#include "hashtab.h"
+#include "typeprint.h"
#include "gdb_obstack.h"
#include "block.h"
#include <ctype.h>
#include "cp-abi.h"
#include "cp-support.h"
-#include "observer.h"
+#include "observable.h"
#include "solist.h"
#include "macrotab.h"
#include "macroscope.h"
#include "filename-seen-cache.h"
#include "arch-utils.h"
#include <algorithm>
+#include "common/pathstuff.h"
/* Forward declarations for local functions. */
static struct block_symbol
lookup_symbol_aux (const char *name,
+ symbol_name_match_type match_type,
const struct block *block,
const domain_enum domain,
enum language language,
static
struct block_symbol lookup_local_symbol (const char *name,
+ symbol_name_match_type match_type,
const struct block *block,
const domain_enum domain,
enum language language);
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_no_tag (type);
+ const char *newname = TYPE_NAME (type);
/* Does the form of physname indicate that it is the full mangled name
of a constructor (not just the args)? */
{
char *demangled = NULL;
int i;
- int recognized;
if (gsymbol->language == language_unknown)
gsymbol->language = language_auto;
else
linkage_name_copy = linkage_name;
+ /* Set the symbol language. */
+ char *demangled_name_ptr
+ = symbol_find_demangled_name (gsymbol, linkage_name_copy);
+ gdb::unique_xmalloc_ptr<char> demangled_name (demangled_name_ptr);
+
entry.mangled = linkage_name_copy;
slot = ((struct demangled_name_entry **)
htab_find_slot (per_bfd->demangled_names_hash,
|| (gsymbol->language == language_go
&& (*slot)->demangled[0] == '\0'))
{
- char *demangled_name = symbol_find_demangled_name (gsymbol,
- linkage_name_copy);
- int demangled_len = demangled_name ? strlen (demangled_name) : 0;
+ int demangled_len = demangled_name ? strlen (demangled_name.get ()) : 0;
/* Suppose we have demangled_name==NULL, copy_name==0, and
linkage_name_copy==linkage_name. In this case, we already have the
}
if (demangled_name != NULL)
- {
- strcpy ((*slot)->demangled, demangled_name);
- xfree (demangled_name);
- }
+ strcpy ((*slot)->demangled, demangled_name.get());
else
(*slot)->demangled[0] = '\0';
}
else
return symbol_natural_name (gsymbol);
}
+
+/* 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);
+ return name_match (symbol_search_name (gsymbol), name, NULL);
+}
+
\f
/* Return 1 if the two sections are the same, or if they could
}
else if (slot_name != NULL && name != NULL)
{
- /* 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 strcmp_iw on SYMBOL_SEARCH_NAME. See dictionary.c.
- It also means using symbol_matches_domain for found symbols.
- See block.c.
+ /* 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
+ dictionary.c. It also means using symbol_matches_domain for
+ found symbols. See block.c.
If the slot records a not-found symbol, then require a precise match.
We could still be lax with whitespace like strcmp_iw though. */
else
{
struct symbol *sym = slot->value.found.symbol;
+ lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- if (strcmp_iw (slot_name, name) != 0)
+ if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
return 0;
+
if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym),
slot_domain, domain))
return 0;
addr = SYMBOL_VALUE_ADDRESS (sym);
break;
case LOC_BLOCK:
- addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
break;
default:
return sym;
}
+/* See symtab.h. */
+
+demangle_for_lookup_info::demangle_for_lookup_info
+ (const lookup_name_info &lookup_name, language lang)
+{
+ demangle_result_storage storage;
+
+ 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 (),
+ lookup_name.completion_mode ());
+
+ if (without_params != NULL)
+ {
+ if (lookup_name.match_type () != symbol_name_match_type::SEARCH_NAME)
+ m_demangled_name = demangle_for_lookup (without_params.get (),
+ lang, storage);
+ return;
+ }
+ }
+
+ if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
+ m_demangled_name = lookup_name.name ();
+ else
+ m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
+ lang, storage);
+}
+
+/* See symtab.h. */
+
+const lookup_name_info &
+lookup_name_info::match_any ()
+{
+ /* Lookup any symbol that "" would complete. I.e., this matches all
+ symbol names. */
+ static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
+ true);
+
+ return lookup_name;
+}
+
/* Compute the demangled form of NAME as used by the various symbol
lookup functions. The result can either be the input NAME
directly, or a pointer to a buffer owned by the STORAGE object.
demangle_result_storage storage;
const char *modified_name = demangle_for_lookup (name, lang, storage);
- return lookup_symbol_aux (modified_name, block, domain, lang,
+ return lookup_symbol_aux (modified_name,
+ symbol_name_match_type::FULL,
+ block, domain, lang,
is_a_field_of_this);
}
/* See symtab.h. */
struct block_symbol
+lookup_symbol_search_name (const char *search_name, const struct block *block,
+ domain_enum domain)
+{
+ return lookup_symbol_aux (search_name, symbol_name_match_type::SEARCH_NAME,
+ block, domain, language_asm, NULL);
+}
+
+/* See symtab.h. */
+
+struct block_symbol
lookup_language_this (const struct language_defn *lang,
const struct block *block)
{
{
struct symbol *sym;
- sym = block_lookup_symbol (block, lang->la_name_of_this, VAR_DOMAIN);
+ sym = block_lookup_symbol (block, lang->la_name_of_this,
+ symbol_name_match_type::SEARCH_NAME,
+ VAR_DOMAIN);
if (sym != NULL)
{
if (symbol_lookup_debug > 1)
(e.g., demangled name) of the symbol that we're looking for. */
static struct block_symbol
-lookup_symbol_aux (const char *name, const struct block *block,
+lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
+ const struct block *block,
const domain_enum domain, enum language language,
struct field_of_this_result *is_a_field_of_this)
{
/* Search specified block and its superiors. Don't search
STATIC_BLOCK or GLOBAL_BLOCK. */
- result = lookup_local_symbol (name, block, domain, language);
+ result = lookup_local_symbol (name, match_type, block, domain, language);
if (result.symbol != NULL)
{
if (symbol_lookup_debug)
Don't search STATIC_BLOCK or GLOBAL_BLOCK. */
static struct block_symbol
-lookup_local_symbol (const char *name, const struct block *block,
+lookup_local_symbol (const char *name,
+ symbol_name_match_type match_type,
+ const struct block *block,
const domain_enum domain,
enum language language)
{
while (block != static_block)
{
- sym = lookup_symbol_in_block (name, block, domain);
+ sym = lookup_symbol_in_block (name, match_type, block, domain);
if (sym != NULL)
return (struct block_symbol) {sym, block};
if (language == language_cplus || language == language_fortran)
{
- struct block_symbol sym
+ struct block_symbol blocksym
= cp_lookup_symbol_imports_or_template (scope, name, block,
domain);
- if (sym.symbol != NULL)
- return sym;
+ if (blocksym.symbol != NULL)
+ return blocksym;
}
if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block))
/* See symtab.h. */
struct symbol *
-lookup_symbol_in_block (const char *name, const struct block *block,
+lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
+ const struct block *block,
const domain_enum domain)
{
struct symbol *sym;
domain_name (domain));
}
- sym = block_lookup_symbol (block, name, domain);
+ sym = block_lookup_symbol (block, name, match_type, domain);
if (sym)
{
if (symbol_lookup_debug > 1)
bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
- result.symbol = block_lookup_symbol (block, name, domain);
+ result.symbol = block_lookup_symbol (block, name,
+ symbol_name_match_type::FULL, domain);
if (result.symbol == NULL)
error_in_psymtab_expansion (block_index, name, cust);
domain_name (domain));
}
- sym = lookup_symbol_in_block (name, static_block, domain);
+ sym = lookup_symbol_in_block (name,
+ symbol_name_match_type::FULL,
+ static_block, domain);
if (symbol_lookup_debug)
{
fprintf_unfiltered (gdb_stdlog,
search continues. */
void
-iterate_over_symbols (const struct block *block, const char *name,
+iterate_over_symbols (const struct block *block,
+ const lookup_name_info &name,
const domain_enum domain,
gdb::function_view<symbol_found_callback_ftype> callback)
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
{
- if (!callback (sym))
+ struct block_symbol block_sym = {sym, block};
+
+ if (!callback (&block_sym))
return;
}
}
{
return find_pc_sect_compunit_symtab (pc, find_pc_mapped_section (pc));
}
+
+/* See symtab.h. */
+
+struct symbol *
+find_symbol_at_address (CORE_ADDR address)
+{
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf == NULL
+ || objfile->sf->qf->find_compunit_symtab_by_address == NULL)
+ continue;
+
+ struct compunit_symtab *symtab
+ = objfile->sf->qf->find_compunit_symtab_by_address (objfile, address);
+ if (symtab != NULL)
+ {
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (symtab);
+
+ for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ if (SYMBOL_CLASS (sym) == LOC_STATIC
+ && SYMBOL_VALUE_ADDRESS (sym) == address)
+ return sym;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
\f
/* Find the source file and line number for a given PC value and SECTION.
find the one whose first PC is closer than that of the next line in this
symtab. */
-/* If it's worth the effort, we could be using a binary search. */
-
struct symtab_and_line
find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
{
struct symtab *iter_s;
struct linetable *l;
int len;
- int i;
struct linetable_entry *item;
const struct blockvector *bv;
struct bound_minimal_symbol msymbol;
if (item->pc > pc && (!alt || item->pc < alt->pc))
alt = item;
- for (i = 0; i < len; i++, item++)
- {
- /* Leave prev pointing to the linetable entry for the last line
- that started at or before PC. */
- if (item->pc > pc)
- break;
+ auto pc_compare = [](const CORE_ADDR & comp_pc,
+ const struct linetable_entry & lhs)->bool
+ {
+ return comp_pc < lhs.pc;
+ };
- prev = item;
- }
+ struct linetable_entry *first = item;
+ 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. */
/* 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
}
/* If another line (denoted by ITEM) is in the linetable and its
- PC is after BEST's PC, but before the current BEST_END, then
+ PC is after BEST's PC, but before the current BEST_END, then
use ITEM's PC as the new best_end. */
- if (best && i < len && item->pc > best->pc
- && (best_end == 0 || best_end > item->pc))
+ if (best && item < last && item->pc > best->pc
+ && (best_end == 0 || best_end > item->pc))
best_end = item->pc;
}
return sal.symtab != 0;
}
-/* Given a function symbol SYM, find the symtab and line for the start
- of the function.
- If the argument FUNFIRSTLINE is nonzero, we want the first line
- of real code inside the function.
- This function should return SALs matching those from minsym_found,
- otherwise false multiple-locations breakpoints could be placed. */
+/* Helper for find_function_start_sal. Does most of the work, except
+ setting the sal's symbol. */
-struct symtab_and_line
-find_function_start_sal (struct symbol *sym, int funfirstline)
+static symtab_and_line
+find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section,
+ bool funfirstline)
{
- fixup_symbol_section (sym, NULL);
-
- obj_section *section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
- symtab_and_line sal
- = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
- sal.symbol = sym;
+ symtab_and_line sal = find_pc_sect_line (func_addr, section, 0);
if (funfirstline && sal.symtab != NULL
&& (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
|| SYMTAB_LANGUAGE (sal.symtab) == language_asm))
{
- struct gdbarch *gdbarch = symbol_arch (sym);
+ struct gdbarch *gdbarch = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
- sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ sal.pc = func_addr;
if (gdbarch_skip_entrypoint_p (gdbarch))
sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
return sal;
}
/* We always should have a line for the function start address.
- If we don't, something is odd. Create a plain SAL refering
+ If we don't, something is odd. Create a plain SAL referring
just the PC and hope that skip_prologue_sal (if requested)
can find a line number for after the prologue. */
- if (sal.pc < BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))
+ if (sal.pc < func_addr)
{
sal = {};
sal.pspace = current_program_space;
- sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ sal.pc = func_addr;
sal.section = section;
- sal.symbol = sym;
}
if (funfirstline)
return sal;
}
+/* See symtab.h. */
+
+symtab_and_line
+find_function_start_sal (CORE_ADDR func_addr, obj_section *section,
+ bool funfirstline)
+{
+ symtab_and_line sal
+ = find_function_start_sal_1 (func_addr, section, funfirstline);
+
+ /* find_function_start_sal_1 does a linetable search, so it finds
+ the symtab and linenumber, but not a symbol. Fill in the
+ function symbol too. */
+ sal.symbol = find_pc_sect_containing_function (sal.pc, sal.section);
+
+ return sal;
+}
+
+/* See symtab.h. */
+
+symtab_and_line
+find_function_start_sal (symbol *sym, bool funfirstline)
+{
+ 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),
+ funfirstline);
+ sal.symbol = sym;
+ return sal;
+}
+
+
/* Given a function start address FUNC_ADDR and SYMTAB, find the first
address for that function that has an entry in SYMTAB's line info
table. If such an entry cannot be found, return FUNC_ADDR
fixup_symbol_section (sym, NULL);
objfile = symbol_objfile (sym);
- pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
section = SYMBOL_OBJ_SECTION (objfile, sym);
name = SYMBOL_LINKAGE_NAME (sym);
}
/* Check if gdbarch_skip_prologue left us in mid-line, and the next
line is still part of the same function. */
if (skip && start_sal.pc != pc
- && (sym ? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
+ && (sym ? (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
&& start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
: (lookup_minimal_symbol_by_pc_section (start_sal.end, section).minsym
== lookup_minimal_symbol_by_pc_section (pc, section).minsym)))
symbol *
find_function_alias_target (bound_minimal_symbol msymbol)
{
- if (!msymbol_is_text (msymbol.minsym))
+ CORE_ADDR func_addr;
+ if (!msymbol_is_function (msymbol.objfile, msymbol.minsym, &func_addr))
return NULL;
- CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
- symbol *sym = find_pc_function (addr);
+ symbol *sym = find_pc_function (func_addr);
if (sym != NULL
&& SYMBOL_CLASS (sym) == LOC_BLOCK
- && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == addr)
+ && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == func_addr)
return sym;
return NULL;
SYMBOL_PRINT_NAME (sym_b.symbol));
}
+/* Returns true if the type_name of symbol_type of SYM matches TREG.
+ If SYM has no symbol_type or symbol_name, returns false. */
+
+bool
+treg_matches_sym_type_name (const compiled_regex &treg,
+ const struct symbol *sym)
+{
+ struct type *sym_type;
+ std::string printed_sym_type_name;
+
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "treg_matches_sym_type_name\n sym %s\n",
+ SYMBOL_NATURAL_NAME (sym));
+ }
+
+ sym_type = SYMBOL_TYPE (sym);
+ if (sym_type == NULL)
+ return false;
+
+ {
+ scoped_switch_to_sym_language_if_auto l (sym);
+
+ printed_sym_type_name = type_to_string (sym_type);
+ }
+
+
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ " sym_type_name %s\n",
+ printed_sym_type_name.c_str ());
+ }
+
+
+ if (printed_sym_type_name.empty ())
+ return false;
+
+ return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
+}
+
+
/* Sort the symbols in RESULT and remove duplicates. */
static void
Only symbols of KIND are searched:
VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
- and constants (enums)
+ 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
std::vector<symbol_search>
search_symbols (const char *regexp, enum search_domain kind,
+ const char *t_regexp,
int nfiles, const char *files[])
{
struct compunit_symtab *cust;
enum minimal_symbol_type ourtype4;
std::vector<symbol_search> result;
gdb::optional<compiled_regex> preg;
+ gdb::optional<compiled_regex> treg;
gdb_assert (kind <= TYPES_DOMAIN);
and <TYPENAME> or <OPERATOR>. */
const char *opend;
const char *opname = operator_chars (regexp, &opend);
- int errcode;
if (*opname)
{
preg.emplace (regexp, cflags, _("Invalid regexp"));
}
+ if (t_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. */
return file_matches (filename, files, nfiles,
basenames);
},
+ lookup_name_info::match_any (),
[&] (const char *symname)
{
- return (!preg || preg->exec (symname,
- 0, NULL, 0) == 0);
+ return (!preg.has_value ()
+ || preg->exec (symname,
+ 0, NULL, 0) == 0);
},
NULL,
kind);
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg
+ if (!preg.has_value ()
|| preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
{
files, nfiles, 1))
&& file_matches (symtab_to_fullname (real_symtab),
files, nfiles, 0)))
- && ((!preg
+ && ((!preg.has_value ()
|| preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
We only want to skip enums here. */
&& !(SYMBOL_CLASS (sym) == LOC_CONST
&& (TYPE_CODE (SYMBOL_TYPE (sym))
- == TYPE_CODE_ENUM)))
- || (kind == FUNCTIONS_DOMAIN
- && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ == 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))))
{
sort_search_symbols_remove_dups (&result);
/* If there are no eyes, avoid all contact. I mean, if there are
- no debug symbols, then add matching minsyms. */
+ 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_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
+ if ((found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
+ && !treg.has_value ())
{
ALL_MSYMBOLS (objfile, msymbol)
{
|| MSYMBOL_TYPE (msymbol) == ourtype3
|| MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
- NULL, 0) == 0)
+ 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. */
/* Helper function for symtab_symbol_info, this function uses
the data returned from search_symbols() to print information
- regarding the match to gdb_stdout. */
+ 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. */
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);
- const char *s_filename = symtab_to_filename_for_display (s);
- if (last == NULL || filename_cmp (last, s_filename) != 0)
+ if (last != NULL)
{
- fputs_filtered ("\nFile ", gdb_stdout);
- fputs_filtered (s_filename, gdb_stdout);
- fputs_filtered (":\n", gdb_stdout);
+ const char *s_filename = symtab_to_filename_for_display (s);
+
+ if (filename_cmp (last, s_filename) != 0)
+ {
+ fputs_filtered ("\nFile ", gdb_stdout);
+ fputs_filtered (s_filename, gdb_stdout);
+ fputs_filtered (":\n", gdb_stdout);
+ }
+
+ if (SYMBOL_LINE (sym) != 0)
+ printf_filtered ("%d:\t", SYMBOL_LINE (sym));
+ else
+ puts_filtered ("\t");
}
if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
matches. */
static void
-symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty)
+symtab_symbol_info (bool quiet,
+ const char *regexp, enum search_domain kind,
+ const char *t_regexp, int from_tty)
{
static const char * const classnames[] =
{"variable", "function", "type"};
- const char *last_filename = NULL;
+ const char *last_filename = "";
int first = 1;
gdb_assert (kind <= TYPES_DOMAIN);
/* Must make sure that if we're interrupted, symbols gets freed. */
- std::vector<symbol_search> symbols = search_symbols (regexp, kind, 0, NULL);
+ std::vector<symbol_search> symbols = search_symbols (regexp, kind,
+ t_regexp, 0, NULL);
- if (regexp != NULL)
- printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
- classnames[kind], regexp);
- else
- printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+ if (!quiet)
+ {
+ if (regexp != NULL)
+ {
+ if (t_regexp != NULL)
+ printf_filtered
+ (_("All %ss matching regular expression \"%s\""
+ " with type matching regulation expression \"%s\":\n"),
+ classnames[kind], regexp, t_regexp);
+ else
+ printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+ classnames[kind], regexp);
+ }
+ else
+ {
+ if (t_regexp != NULL)
+ printf_filtered
+ (_("All defined %ss"
+ " with type matching regulation expression \"%s\" :\n"),
+ classnames[kind], t_regexp);
+ else
+ printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+ }
+ }
for (const symbol_search &p : symbols)
{
{
if (first)
{
- printf_filtered (_("\nNon-debugging symbols:\n"));
+ if (!quiet)
+ printf_filtered (_("\nNon-debugging symbols:\n"));
first = 0;
}
print_msymbol_info (p.msymbol);
}
static void
-info_variables_command (const char *regexp, int from_tty)
+info_variables_command (const char *args, int from_tty)
{
- symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty);
+ std::string regexp;
+ std::string t_regexp;
+ bool quiet = false;
+
+ while (args != NULL
+ && extract_info_print_args (&args, &quiet, ®exp, &t_regexp))
+ ;
+
+ if (args != NULL)
+ report_unrecognized_option_error ("info variables", args);
+
+ symtab_symbol_info (quiet,
+ regexp.empty () ? NULL : regexp.c_str (),
+ VARIABLES_DOMAIN,
+ t_regexp.empty () ? NULL : t_regexp.c_str (),
+ from_tty);
}
+
static void
-info_functions_command (const char *regexp, int from_tty)
+info_functions_command (const char *args, int from_tty)
{
- symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
+ std::string regexp;
+ std::string t_regexp;
+ bool quiet = false;
+
+ while (args != NULL
+ && extract_info_print_args (&args, &quiet, ®exp, &t_regexp))
+ ;
+
+ if (args != NULL)
+ report_unrecognized_option_error ("info functions", args);
+
+ symtab_symbol_info (quiet,
+ regexp.empty () ? NULL : regexp.c_str (),
+ FUNCTIONS_DOMAIN,
+ t_regexp.empty () ? NULL : t_regexp.c_str (),
+ from_tty);
}
static void
info_types_command (const char *regexp, int from_tty)
{
- symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
+ symtab_symbol_info (false, regexp, TYPES_DOMAIN, NULL, from_tty);
}
/* Breakpoint all functions matching regular expression. */
std::vector<symbol_search> symbols = search_symbols (regexp,
FUNCTIONS_DOMAIN,
+ NULL,
nfiles, files);
scoped_rbreak_breakpoints finalize;
string = string_printf ("%s:'%s'", fullname,
SYMBOL_LINKAGE_NAME (p.symbol));
break_command (&string[0], from_tty);
- print_symbol_info (FUNCTIONS_DOMAIN,
- p.symbol,
- p.block,
- symtab_to_filename_for_display (symtab));
+ print_symbol_info (FUNCTIONS_DOMAIN, p.symbol, p.block, NULL);
}
else
{
}
\f
-/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN.
-
- Either sym_text[sym_text_len] != '(' and then we search for any
- symbol starting with SYM_TEXT text.
-
- Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to
- be terminated at that point. Partial symbol tables do not have parameters
- information. */
+/* Evaluate if SYMNAME matches LOOKUP_NAME. */
static int
-compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
+compare_symbol_name (const char *symbol_name, language symbol_language,
+ const lookup_name_info &lookup_name,
+ completion_match_result &match_res)
{
- int (*ncmp) (const char *, const char *, size_t);
-
- ncmp = (case_sensitivity == case_sensitive_on ? strncmp : strncasecmp);
+ const language_defn *lang = language_def (symbol_language);
- if (ncmp (name, sym_text, sym_text_len) != 0)
- return 0;
-
- if (sym_text[sym_text_len] == '(')
- {
- /* User searches for `name(someth...'. Require NAME to be terminated.
- Normally psymtabs and gdbindex have no parameter types so '\0' will be
- present but accept even parameters presence. In this case this
- function is in fact strcmp_iw but whitespace skipping is not supported
- for tab completion. */
+ symbol_name_matcher_ftype *name_match
+ = get_symbol_name_matcher (lang, lookup_name);
- if (name[sym_text_len] != '\0' && name[sym_text_len] != '(')
- return 0;
- }
-
- return 1;
+ return name_match (symbol_name, lookup_name, &match_res);
}
-/* Test to see if the symbol specified by SYMNAME (which is already
- demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
- characters. If so, add it to the current completion list. */
+/* See symtab.h. */
-static void
+void
completion_list_add_name (completion_tracker &tracker,
+ language symbol_language,
const char *symname,
- const char *sym_text, int sym_text_len,
+ const lookup_name_info &lookup_name,
const char *text, const char *word)
{
+ completion_match_result &match_res
+ = tracker.reset_completion_match_result ();
+
/* Clip symbols that cannot match. */
- if (!compare_symbol_name (symname, sym_text, sym_text_len))
+ if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res))
return;
+ /* Refresh SYMNAME from the match string. It's potentially
+ different depending on language. (E.g., on Ada, the match may be
+ the encoded symbol name wrapped in "<>"). */
+ symname = match_res.match.match ();
+ gdb_assert (symname != NULL);
+
/* We have a match for a completion, so add SYMNAME to the current list
of matches. Note that the name is moved to freshly malloc'd space. */
{
- char *newobj;
-
- if (word == sym_text)
- {
- newobj = (char *) xmalloc (strlen (symname) + 5);
- strcpy (newobj, symname);
- }
- else if (word > sym_text)
- {
- /* Return some portion of symname. */
- newobj = (char *) xmalloc (strlen (symname) + 5);
- strcpy (newobj, symname + (word - sym_text));
- }
- else
- {
- /* Return some of SYM_TEXT plus symname. */
- newobj = (char *) xmalloc (strlen (symname) + (sym_text - word) + 5);
- strncpy (newobj, word, sym_text - word);
- newobj[sym_text - word] = '\0';
- strcat (newobj, symname);
- }
-
- gdb::unique_xmalloc_ptr<char> completion (newobj);
-
- tracker.add_completion (std::move (completion));
+ gdb::unique_xmalloc_ptr<char> completion
+ = make_completion_match_str (symname, text, word);
+
+ /* Here we pass the match-for-lcd object to add_completion. Some
+ languages match the user text against substrings of symbol
+ names in some cases. E.g., in C++, "b push_ba" completes to
+ "std::vector::push_back", "std::string::push_back", etc., and
+ in this case we want the completion lowest common denominator
+ to be "push_back" instead of "std::". */
+ tracker.add_completion (std::move (completion),
+ &match_res.match_for_lcd, text, word);
}
}
static void
completion_list_add_symbol (completion_tracker &tracker,
symbol *sym,
- const char *sym_text, int sym_text_len,
+ const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, SYMBOL_NATURAL_NAME (sym),
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+ SYMBOL_NATURAL_NAME (sym),
+ lookup_name, text, word);
}
/* completion_list_add_name wrapper for struct minimal_symbol. */
static void
completion_list_add_msymbol (completion_tracker &tracker,
minimal_symbol *sym,
- const char *sym_text, int sym_text_len,
+ const lookup_name_info &lookup_name,
const char *text, const char *word)
{
- completion_list_add_name (tracker, MSYMBOL_NATURAL_NAME (sym),
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym),
+ MSYMBOL_NATURAL_NAME (sym),
+ lookup_name, text, word);
}
+
/* ObjC: In case we are completing on a selector, look as the msymbol
again and feed all the selectors into the mill. */
static void
completion_list_objc_symbol (completion_tracker &tracker,
struct minimal_symbol *msymbol,
- const char *sym_text, int sym_text_len,
+ const lookup_name_info &lookup_name,
const char *text, const char *word)
{
static char *tmp = NULL;
if ((method[0] != '-') && (method[0] != '+'))
return;
- if (sym_text[0] == '[')
+ if (text[0] == '[')
/* Complete on shortened method method. */
- completion_list_add_name (tracker, method + 1,
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, language_objc,
+ method + 1,
+ lookup_name,
+ text, word);
while ((strlen (method) + 1) >= tmplen)
{
memcpy (tmp, method, (category - method));
tmp[category - method] = ' ';
memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
- completion_list_add_name (tracker, tmp,
- sym_text, sym_text_len, text, word);
- if (sym_text[0] == '[')
- completion_list_add_name (tracker, tmp + 1,
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, language_objc, tmp,
+ lookup_name, text, word);
+ if (text[0] == '[')
+ completion_list_add_name (tracker, language_objc, tmp + 1,
+ lookup_name, text, word);
}
if (selector != NULL)
if (tmp2 != NULL)
*tmp2 = '\0';
- completion_list_add_name (tracker, tmp,
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, language_objc, tmp,
+ lookup_name, text, word);
}
}
static void
completion_list_add_fields (completion_tracker &tracker,
struct symbol *sym,
- const char *sym_text, int sym_text_len,
+ const lookup_name_info &lookup_name,
const char *text, const char *word)
{
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
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, TYPE_FIELD_NAME (t, j),
- sym_text, sym_text_len, text, word);
+ completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+ TYPE_FIELD_NAME (t, j),
+ lookup_name, text, word);
+ }
+}
+
+/* See symtab.h. */
+
+bool
+symbol_is_function_or_method (symbol *sym)
+{
+ switch (TYPE_CODE (SYMBOL_TYPE (sym)))
+ {
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* See symtab.h. */
+
+bool
+symbol_is_function_or_method (minimal_symbol *msymbol)
+{
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_text:
+ case mst_text_gnu_ifunc:
+ case mst_solib_trampoline:
+ case mst_file_text:
+ return true;
+ default:
+ return false;
}
}
+/* See symtab.h. */
+
+bound_minimal_symbol
+find_gnu_ifunc (const symbol *sym)
+{
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ return {};
+
+ lookup_name_info lookup_name (SYMBOL_SEARCH_NAME (sym),
+ symbol_name_match_type::SEARCH_NAME);
+ struct objfile *objfile = symbol_objfile (sym);
+
+ CORE_ADDR address = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
+ minimal_symbol *ifunc = NULL;
+
+ iterate_over_minimal_symbols (objfile, lookup_name,
+ [&] (minimal_symbol *minsym)
+ {
+ if (MSYMBOL_TYPE (minsym) == mst_text_gnu_ifunc
+ || MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
+ {
+ 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 ());
+ }
+ if (msym_addr == address)
+ {
+ ifunc = minsym;
+ return true;
+ }
+ }
+ return false;
+ });
+
+ if (ifunc != NULL)
+ return {ifunc, objfile};
+ return {};
+}
+
/* Add matching symbols from SYMTAB to the current completion list. */
static void
add_symtab_completions (struct compunit_symtab *cust,
completion_tracker &tracker,
- const char *sym_text, int sym_text_len,
+ complete_symbol_mode mode,
+ const lookup_name_info &lookup_name,
const char *text, const char *word,
enum type_code code)
{
b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), i);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
+ if (completion_skip_symbol (mode, sym))
+ continue;
+
if (code == TYPE_CODE_UNDEF
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
completion_list_add_symbol (tracker, sym,
- sym_text, sym_text_len,
+ lookup_name,
text, word);
}
}
void
default_collect_symbol_completion_matches_break_on
- (completion_tracker &tracker,
- complete_symbol_mode mode,
+ (completion_tracker &tracker, complete_symbol_mode mode,
+ symbol_name_match_type name_match_type,
const char *text, const char *word,
const char *break_on, enum type_code code)
{
struct block_iterator iter;
/* The symbol we are completing on. Points in same buffer as text. */
const char *sym_text;
- /* Length of sym_text. */
- int sym_text_len;
/* Now look for the symbol we are supposed to complete on. */
if (mode == complete_symbol_mode::LINESPEC)
}
}
- sym_text_len = strlen (sym_text);
-
- /* Prepare SYM_TEXT_LEN for compare_symbol_name. */
-
- if (current_language->la_language == language_cplus
- || current_language->la_language == language_fortran)
- {
- /* These languages may have parameters entered by user but they are never
- present in the partial symbol tables. */
-
- const char *cs = (const char *) memchr (sym_text, '(', sym_text_len);
-
- if (cs)
- sym_text_len = cs - sym_text;
- }
- gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
+ lookup_name_info lookup_name (sym_text, name_match_type, true);
/* At this point scan through the misc symbol vectors and add each
symbol you find to the list. Eventually we want to ignore
{
QUIT;
- completion_list_add_msymbol (tracker,
- msymbol, sym_text, sym_text_len,
- text, word);
+ if (completion_skip_symbol (mode, msymbol))
+ continue;
+
+ completion_list_add_msymbol (tracker, msymbol, lookup_name,
+ sym_text, word);
- completion_list_objc_symbol (tracker,
- msymbol, sym_text, sym_text_len,
- text, word);
+ completion_list_objc_symbol (tracker, msymbol, lookup_name,
+ sym_text, word);
}
}
/* Add completions for all currently loaded symbol tables. */
ALL_COMPUNITS (objfile, cust)
- add_symtab_completions (cust, tracker,
- sym_text, sym_text_len, text, word, code);
+ add_symtab_completions (cust, tracker, mode, lookup_name,
+ sym_text, word, code);
/* Look through the partial symtabs for all symbols which begin by
matching SYM_TEXT. Expand all CUs that you find to the list. */
expand_symtabs_matching (NULL,
- [&] (const char *name) /* symbol matcher */
- {
- return compare_symbol_name (name,
- sym_text,
- sym_text_len);
- },
+ lookup_name,
+ NULL,
[&] (compunit_symtab *symtab) /* expansion notify */
{
add_symtab_completions (symtab,
- tracker,
- sym_text, sym_text_len,
- text, word, code);
+ tracker, mode, lookup_name,
+ sym_text, word, code);
},
ALL_DOMAIN);
{
if (code == TYPE_CODE_UNDEF)
{
- completion_list_add_symbol (tracker, sym,
- sym_text, sym_text_len, text,
- word);
- completion_list_add_fields (tracker, sym,
- sym_text, sym_text_len, text,
- word);
+ completion_list_add_symbol (tracker, sym, lookup_name,
+ sym_text, word);
+ completion_list_add_fields (tracker, sym, lookup_name,
+ sym_text, word);
}
else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code)
- completion_list_add_symbol (tracker, sym,
- sym_text, sym_text_len, text,
- word);
+ completion_list_add_symbol (tracker, sym, lookup_name,
+ sym_text, word);
}
/* Stop when we encounter an enclosing function. Do not stop for
{
if (surrounding_static_block != NULL)
ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
- completion_list_add_fields (tracker, sym,
- sym_text, sym_text_len, text, word);
+ completion_list_add_fields (tracker, sym, lookup_name,
+ sym_text, word);
if (surrounding_global_block != NULL)
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
- completion_list_add_fields (tracker, sym,
- sym_text, sym_text_len, text, word);
+ completion_list_add_fields (tracker, sym, lookup_name,
+ sym_text, word);
}
/* Skip macros if we are completing a struct tag -- arguable but
if (current_language->la_macro_expansion == macro_expansion_c
&& code == TYPE_CODE_UNDEF)
{
- struct macro_scope *scope;
+ gdb::unique_xmalloc_ptr<struct macro_scope> scope;
/* This adds a macro's name to the current completion list. */
auto add_macro_name = [&] (const char *macro_name,
macro_source_file *,
int)
{
- completion_list_add_name (tracker, macro_name,
- sym_text, sym_text_len,
- text, word);
+ completion_list_add_name (tracker, language_c, macro_name,
+ lookup_name, sym_text, word);
};
/* Add any macros visible in the default scope. Note that this
completion time. */
scope = default_macro_scope ();
if (scope)
- {
- macro_for_each_in_scope (scope->file, scope->line,
- add_macro_name);
- xfree (scope);
- }
+ macro_for_each_in_scope (scope->file, scope->line,
+ add_macro_name);
/* User-defined macros are always visible. */
macro_for_each (macro_user_macros, add_macro_name);
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);
}
void
collect_symbol_completion_matches (completion_tracker &tracker,
complete_symbol_mode mode,
+ 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);
}
enum type_code code)
{
complete_symbol_mode mode = complete_symbol_mode::EXPRESSION;
+ symbol_name_match_type name_match_type = symbol_name_match_type::EXPRESSION;
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);
}
void
collect_file_symbol_completion_matches (completion_tracker &tracker,
complete_symbol_mode mode,
+ symbol_name_match_type name_match_type,
const char *text, const char *word,
const char *srcfile)
{
/* The symbol we are completing on. Points in same buffer as text. */
const char *sym_text;
- /* Length of sym_text. */
- int sym_text_len;
/* Now look for the symbol we are supposed to complete on.
FIXME: This should be language-specific. */
}
}
- sym_text_len = strlen (sym_text);
+ lookup_name_info lookup_name (sym_text, name_match_type, true);
/* Go through symtabs for SRCFILE and check the externs and statics
for symbols which match. */
iterate_over_symtabs (srcfile, [&] (symtab *s)
{
add_symtab_completions (SYMTAB_COMPUNIT (s),
- tracker,
- sym_text, sym_text_len,
- text, word, TYPE_CODE_UNDEF);
+ tracker, mode, lookup_name,
+ sym_text, word, TYPE_CODE_UNDEF);
return false;
});
}
add_filename_to_list (const char *fname, const char *text, const char *word,
completion_list *list)
{
- char *newobj;
- size_t fnlen = strlen (fname);
-
- if (word == text)
- {
- /* Return exactly fname. */
- newobj = (char *) xmalloc (fnlen + 5);
- strcpy (newobj, fname);
- }
- else if (word > text)
- {
- /* Return some portion of fname. */
- newobj = (char *) xmalloc (fnlen + 5);
- strcpy (newobj, fname + (word - text));
- }
- else
- {
- /* Return some of TEXT plus fname. */
- newobj = (char *) xmalloc (fnlen + (text - word) + 5);
- strncpy (newobj, word, text - word);
- newobj[text - word] = '\0';
- strcat (newobj, fname);
- }
- list->emplace_back (newobj);
+ list->emplace_back (make_completion_match_str (fname, text, word));
}
static int
struct template_symbol *result;
result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
- initialize_objfile_symbol_1 (&result->base);
+ initialize_objfile_symbol_1 (result);
return result;
}
symbol_cache_key
= register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup);
- add_info ("variables", info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+ add_info ("variables", info_variables_command,
+ info_print_args_help (_("\
+All global and static variable names or those matching REGEXPs.\n\
+Usage: info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+ _("global and static variables")));
if (dbx_commands)
- add_com ("whereis", class_info, info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+ add_com ("whereis", class_info, info_variables_command,
+ info_print_args_help (_("\
+All global and static variable names, or those matching REGEXPs.\n\
+Usage: whereis [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+ _("global and static variables")));
add_info ("functions", info_functions_command,
- _("All function names, or those matching REGEXP."));
+ info_print_args_help (_("\
+All function names or those matching REGEXPs.\n\
+Usage: info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the functions.\n"),
+ _("functions")));
/* FIXME: This command has at least the following problems:
1. It prints builtin types (in a very strange and confusing fashion).
_("Flush the symbol cache for each program space."),
&maintenancelist);
- observer_attach_executable_changed (symtab_observer_executable_changed);
- observer_attach_new_objfile (symtab_new_objfile_observer);
- observer_attach_free_objfile (symtab_free_objfile_observer);
+ 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);
}