#include "progspace-and-thread.h"
#include "common/gdb_optional.h"
#include "filename-seen-cache.h"
+#include "arch-utils.h"
+#include <algorithm>
/* Forward declarations for local functions. */
/* See symtab.h. */
const struct block_symbol null_block_symbol = { NULL, NULL };
-extern initialize_file_ftype _initialize_symtab;
-
/* Program space key for finding name and language of "main". */
static const struct program_space_data *main_progspace_key;
absolutizing a relative path. */
if (IS_ABSOLUTE_PATH (name))
{
- real_path.reset (gdb_realpath (name));
+ real_path = gdb_realpath (name);
gdb_assert (IS_ABSOLUTE_PATH (real_path.get ()));
}
else
return symbol_natural_name (gsymbol);
}
-
-/* Initialize the structure fields to zero values. */
-
-void
-init_sal (struct symtab_and_line *sal)
-{
- memset (sal, 0, sizeof (*sal));
-}
\f
/* Return 1 if the two sections are the same, or if they could
/* The "mt print symbol-cache" command. */
static void
-maintenance_print_symbol_cache (char *args, int from_tty)
+maintenance_print_symbol_cache (const char *args, int from_tty)
{
struct program_space *pspace;
/* The "mt flush-symbol-cache" command. */
static void
-maintenance_flush_symbol_cache (char *args, int from_tty)
+maintenance_flush_symbol_cache (const char *args, int from_tty)
{
struct program_space *pspace;
/* The "mt print symbol-cache-statistics" command. */
static void
-maintenance_print_symbol_cache_statistics (char *args, int from_tty)
+maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
{
struct program_space *pspace;
int len;
int i;
struct linetable_entry *item;
- struct symtab_and_line val;
const struct blockvector *bv;
struct bound_minimal_symbol msymbol;
But what we want is the statement containing the instruction.
Fudge the pc to make sure we get that. */
- init_sal (&val); /* initialize to zeroes */
-
- val.pspace = current_program_space;
-
/* It's tempting to assume that, if we can't find debugging info for
any function enclosing PC, that we shouldn't search for line
number info, either. However, GAS can emit line number info for
return find_pc_line (BMSYMBOL_VALUE_ADDRESS (mfunsym), 0);
}
+ symtab_and_line val;
+ val.pspace = current_program_space;
cust = find_pc_sect_compunit_symtab (pc, section);
if (cust == NULL)
struct symtab_and_line
find_function_start_sal (struct symbol *sym, int funfirstline)
{
- struct symtab_and_line sal;
- struct obj_section *section;
-
fixup_symbol_section (sym, NULL);
- section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
- sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
+
+ 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;
if (funfirstline && sal.symtab != NULL
&& (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
can find a line number for after the prologue. */
if (sal.pc < BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))
{
- init_sal (&sal);
+ sal = {};
sal.pspace = current_program_space;
sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
sal.section = section;
+ sal.symbol = sym;
}
if (funfirstline)
if (gdbarch_skip_entrypoint_p (gdbarch))
pc = gdbarch_skip_entrypoint (gdbarch, pc);
if (skip)
- pc = gdbarch_skip_prologue (gdbarch, pc);
+ pc = gdbarch_skip_prologue_noexcept (gdbarch, pc);
/* For overlays, map pc back into its mapped VMA range. */
pc = overlay_mapped_address (pc, section);
/* Don't return END_PC, which is past the end of the function. */
return prologue_sal.pc;
}
+
+/* See symtab.h. */
+
+symbol *
+find_function_alias_target (bound_minimal_symbol msymbol)
+{
+ if (!msymbol_is_text (msymbol.minsym))
+ return NULL;
+
+ CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
+ symbol *sym = find_pc_function (addr);
+ if (sym != NULL
+ && SYMBOL_CLASS (sym) == LOC_BLOCK
+ && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == addr)
+ return sym;
+
+ return NULL;
+}
+
\f
/* If P is of the form "operator[ \t]+..." where `...' is
some legitimate operator text, return a pointer to the
}
static void
-sources_info (char *ignore, int from_tty)
+info_sources_command (char *ignore, int from_tty)
{
struct compunit_symtab *cu;
struct symtab *s;
return 0;
}
-/* Free any memory associated with a search. */
-
-void
-free_search_symbols (struct symbol_search *symbols)
-{
- struct symbol_search *p;
- struct symbol_search *next;
-
- for (p = symbols; p != NULL; p = next)
- {
- next = p->next;
- xfree (p);
- }
-}
-
-static void
-do_free_search_symbols_cleanup (void *symbolsp)
-{
- struct symbol_search *symbols = *(struct symbol_search **) symbolsp;
-
- free_search_symbols (symbols);
-}
-
-struct cleanup *
-make_cleanup_free_search_symbols (struct symbol_search **symbolsp)
-{
- return make_cleanup (do_free_search_symbols_cleanup, symbolsp);
-}
-
/* Helper function for sort_search_symbols_remove_dups and qsort. Can only
sort symbols, not minimal symbols. */
-static int
-compare_search_syms (const void *sa, const void *sb)
+int
+symbol_search::compare_search_syms (const symbol_search &sym_a,
+ const symbol_search &sym_b)
{
- struct symbol_search *sym_a = *(struct symbol_search **) sa;
- struct symbol_search *sym_b = *(struct symbol_search **) sb;
int c;
- c = FILENAME_CMP (symbol_symtab (sym_a->symbol)->filename,
- symbol_symtab (sym_b->symbol)->filename);
+ c = FILENAME_CMP (symbol_symtab (sym_a.symbol)->filename,
+ symbol_symtab (sym_b.symbol)->filename);
if (c != 0)
return c;
- if (sym_a->block != sym_b->block)
- return sym_a->block - sym_b->block;
+ if (sym_a.block != sym_b.block)
+ return sym_a.block - sym_b.block;
- return strcmp (SYMBOL_PRINT_NAME (sym_a->symbol),
- SYMBOL_PRINT_NAME (sym_b->symbol));
+ return strcmp (SYMBOL_PRINT_NAME (sym_a.symbol),
+ SYMBOL_PRINT_NAME (sym_b.symbol));
}
-/* Sort the NFOUND symbols in list FOUND and remove duplicates.
- The duplicates are freed, and the new list is returned in
- *NEW_HEAD, *NEW_TAIL. */
+/* Sort the symbols in RESULT and remove duplicates. */
static void
-sort_search_symbols_remove_dups (struct symbol_search *found, int nfound,
- struct symbol_search **new_head,
- struct symbol_search **new_tail)
+sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
{
- struct symbol_search **symbols, *symp;
- int i, j, nunique;
-
- gdb_assert (found != NULL && nfound > 0);
-
- /* Build an array out of the list so we can easily sort them. */
- symbols = XNEWVEC (struct symbol_search *, nfound);
-
- symp = found;
- for (i = 0; i < nfound; i++)
- {
- gdb_assert (symp != NULL);
- gdb_assert (symp->block >= 0 && symp->block <= 1);
- symbols[i] = symp;
- symp = symp->next;
- }
- gdb_assert (symp == NULL);
-
- qsort (symbols, nfound, sizeof (struct symbol_search *),
- compare_search_syms);
-
- /* Collapse out the dups. */
- for (i = 1, j = 1; i < nfound; ++i)
- {
- if (compare_search_syms (&symbols[j - 1], &symbols[i]) != 0)
- symbols[j++] = symbols[i];
- else
- xfree (symbols[i]);
- }
- nunique = j;
- symbols[j - 1]->next = NULL;
-
- /* Rebuild the linked list. */
- for (i = 0; i < nunique - 1; i++)
- symbols[i]->next = symbols[i + 1];
- symbols[nunique - 1]->next = NULL;
-
- *new_head = symbols[0];
- *new_tail = symbols[nunique - 1];
- xfree (symbols);
+ std::sort (result->begin (), result->end ());
+ result->erase (std::unique (result->begin (), result->end ()),
+ result->end ());
}
/* Search the symbol table for matches to the regular expression REGEXP,
- returning the results in *MATCHES.
+ returning the results.
Only symbols of KIND are searched:
VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
TYPES_DOMAIN - search all type names
ALL_DOMAIN - an internal error for this function
- free_search_symbols should be called when *MATCHES is no longer needed.
-
Within each file the results are sorted locally; each symtab's global and
static blocks are separately alphabetized.
Duplicate entries are removed. */
-void
+std::vector<symbol_search>
search_symbols (const char *regexp, enum search_domain kind,
- int nfiles, const char *files[],
- struct symbol_search **matches)
+ int nfiles, const char *files[])
{
struct compunit_symtab *cust;
const struct blockvector *bv;
enum minimal_symbol_type ourtype2;
enum minimal_symbol_type ourtype3;
enum minimal_symbol_type ourtype4;
- struct symbol_search *found;
- struct symbol_search *tail;
- int nfound;
+ std::vector<symbol_search> result;
gdb::optional<compiled_regex> preg;
- /* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current
- CLEANUP_CHAIN is freed only in the case of an error. */
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- struct cleanup *retval_chain;
-
gdb_assert (kind <= TYPES_DOMAIN);
ourtype = types[kind];
ourtype3 = types3[kind];
ourtype4 = types4[kind];
- *matches = NULL;
-
if (regexp != NULL)
{
/* Make sure spacing is right for C++ operators.
}
}
- found = NULL;
- tail = NULL;
- nfound = 0;
- retval_chain = make_cleanup_free_search_symbols (&found);
-
ALL_COMPUNITS (objfile, cust)
{
bv = COMPUNIT_BLOCKVECTOR (cust);
&& SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
{
/* match */
- struct symbol_search *psr = XCNEW (struct symbol_search);
-
- psr->block = i;
- psr->symbol = sym;
- psr->next = NULL;
- if (tail == NULL)
- found = psr;
- else
- tail->next = psr;
- tail = psr;
- nfound ++;
+ result.emplace_back (i, sym);
}
}
}
}
- if (found != NULL)
- {
- sort_search_symbols_remove_dups (found, nfound, &found, &tail);
- /* Note: nfound is no longer useful beyond this point. */
- }
+ if (!result.empty ())
+ 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. */
.symbol == NULL)
{
/* match */
- struct symbol_search *psr = XNEW (struct symbol_search);
- psr->block = i;
- psr->msymbol.minsym = msymbol;
- psr->msymbol.objfile = objfile;
- psr->symbol = NULL;
- psr->next = NULL;
- if (tail == NULL)
- found = psr;
- else
- tail->next = psr;
- tail = psr;
+ result.emplace_back (i, msymbol, objfile);
}
}
}
}
}
- discard_cleanups (retval_chain);
- do_cleanups (old_chain);
- *matches = found;
+ return result;
}
/* Helper function for symtab_symbol_info, this function uses
{
static const char * const classnames[] =
{"variable", "function", "type"};
- struct symbol_search *symbols;
- struct symbol_search *p;
- struct cleanup *old_chain;
const char *last_filename = NULL;
int first = 1;
gdb_assert (kind <= TYPES_DOMAIN);
/* Must make sure that if we're interrupted, symbols gets freed. */
- search_symbols (regexp, kind, 0, NULL, &symbols);
- old_chain = make_cleanup_free_search_symbols (&symbols);
+ std::vector<symbol_search> symbols = search_symbols (regexp, kind, 0, NULL);
if (regexp != NULL)
printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
else
printf_filtered (_("All defined %ss:\n"), classnames[kind]);
- for (p = symbols; p != NULL; p = p->next)
+ for (const symbol_search &p : symbols)
{
QUIT;
- if (p->msymbol.minsym != NULL)
+ if (p.msymbol.minsym != NULL)
{
if (first)
{
printf_filtered (_("\nNon-debugging symbols:\n"));
first = 0;
}
- print_msymbol_info (p->msymbol);
+ print_msymbol_info (p.msymbol);
}
else
{
print_symbol_info (kind,
- p->symbol,
- p->block,
+ p.symbol,
+ p.block,
last_filename);
last_filename
- = symtab_to_filename_for_display (symbol_symtab (p->symbol));
+ = symtab_to_filename_for_display (symbol_symtab (p.symbol));
}
}
-
- do_cleanups (old_chain);
}
static void
-variables_info (char *regexp, int from_tty)
+info_variables_command (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty);
}
static void
-functions_info (char *regexp, int from_tty)
+info_functions_command (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
}
static void
-types_info (char *regexp, int from_tty)
+info_types_command (char *regexp, int from_tty)
{
symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
}
rbreak_command (regexp, from_tty);
}
-/* A cleanup function that calls end_rbreak_breakpoints. */
-
-static void
-do_end_rbreak_breakpoints (void *ignore)
-{
- end_rbreak_breakpoints ();
-}
-
static void
rbreak_command (char *regexp, int from_tty)
{
- struct symbol_search *ss;
- struct symbol_search *p;
- struct cleanup *old_chain;
- char *string = NULL;
- int len = 0;
+ std::string string;
const char **files = NULL;
const char *file_name;
int nfiles = 0;
}
}
- search_symbols (regexp, FUNCTIONS_DOMAIN, nfiles, files, &ss);
- old_chain = make_cleanup_free_search_symbols (&ss);
- make_cleanup (free_current_contents, &string);
+ std::vector<symbol_search> symbols = search_symbols (regexp,
+ FUNCTIONS_DOMAIN,
+ nfiles, files);
- start_rbreak_breakpoints ();
- make_cleanup (do_end_rbreak_breakpoints, NULL);
- for (p = ss; p != NULL; p = p->next)
+ scoped_rbreak_breakpoints finalize;
+ for (const symbol_search &p : symbols)
{
- if (p->msymbol.minsym == NULL)
+ if (p.msymbol.minsym == NULL)
{
- struct symtab *symtab = symbol_symtab (p->symbol);
+ struct symtab *symtab = symbol_symtab (p.symbol);
const char *fullname = symtab_to_fullname (symtab);
- int newlen = (strlen (fullname)
- + strlen (SYMBOL_LINKAGE_NAME (p->symbol))
- + 4);
-
- if (newlen > len)
- {
- string = (char *) xrealloc (string, newlen);
- len = newlen;
- }
- strcpy (string, fullname);
- strcat (string, ":'");
- strcat (string, SYMBOL_LINKAGE_NAME (p->symbol));
- strcat (string, "'");
- break_command (string, from_tty);
+ 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,
+ p.symbol,
+ p.block,
symtab_to_filename_for_display (symtab));
}
else
{
- int newlen = (strlen (MSYMBOL_LINKAGE_NAME (p->msymbol.minsym)) + 3);
-
- if (newlen > len)
- {
- string = (char *) xrealloc (string, newlen);
- len = newlen;
- }
- strcpy (string, "'");
- strcat (string, MSYMBOL_LINKAGE_NAME (p->msymbol.minsym));
- strcat (string, "'");
+ string = string_printf ("'%s'",
+ MSYMBOL_LINKAGE_NAME (p.msymbol.minsym));
- break_command (string, from_tty);
+ break_command (&string[0], from_tty);
printf_filtered ("<function, no debug info> %s;\n",
- MSYMBOL_PRINT_NAME (p->msymbol.minsym));
+ MSYMBOL_PRINT_NAME (p.msymbol.minsym));
}
}
-
- do_cleanups (old_chain);
}
\f
void
default_collect_symbol_completion_matches_break_on
(completion_tracker &tracker,
+ complete_symbol_mode mode,
const char *text, const char *word,
const char *break_on, enum type_code code)
{
int sym_text_len;
/* Now look for the symbol we are supposed to complete on. */
+ if (mode == complete_symbol_mode::LINESPEC)
+ sym_text = text;
+ else
{
const char *p;
char quote_found;
void
default_collect_symbol_completion_matches (completion_tracker &tracker,
+ complete_symbol_mode mode,
const char *text, const char *word,
enum type_code code)
{
- return default_collect_symbol_completion_matches_break_on (tracker,
+ return default_collect_symbol_completion_matches_break_on (tracker, mode,
text, word, "",
code);
}
void
collect_symbol_completion_matches (completion_tracker &tracker,
+ complete_symbol_mode mode,
const char *text, const char *word)
{
- current_language->la_collect_symbol_completion_matches (tracker,
+ current_language->la_collect_symbol_completion_matches (tracker, mode,
text, word,
TYPE_CODE_UNDEF);
}
const char *text, const char *word,
enum type_code code)
{
+ complete_symbol_mode mode = complete_symbol_mode::EXPRESSION;
+
gdb_assert (code == TYPE_CODE_UNION
|| code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_ENUM);
- current_language->la_collect_symbol_completion_matches (tracker,
+ current_language->la_collect_symbol_completion_matches (tracker, mode,
text, word, code);
}
void
collect_file_symbol_completion_matches (completion_tracker &tracker,
+ complete_symbol_mode mode,
const char *text, const char *word,
const char *srcfile)
{
/* Now look for the symbol we are supposed to complete on.
FIXME: This should be language-specific. */
+ if (mode == complete_symbol_mode::LINESPEC)
+ sym_text = text;
+ else
{
const char *p;
char quote_found;
completion_list list;
const char *base_name;
struct add_partial_filename_data datum;
- struct cleanup *back_to;
if (!have_full_symbols () && !have_partial_symbols ())
return list;
symbol_cache_key
= register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup);
- add_info ("variables", variables_info, _("\
+ add_info ("variables", info_variables_command, _("\
All global and static variable names, or those matching REGEXP."));
if (dbx_commands)
- add_com ("whereis", class_info, variables_info, _("\
+ add_com ("whereis", class_info, info_variables_command, _("\
All global and static variable names, or those matching REGEXP."));
- add_info ("functions", functions_info,
+ add_info ("functions", info_functions_command,
_("All function names, or those matching REGEXP."));
/* FIXME: This command has at least the following problems:
print "struct foo *".
I also think "ptype" or "whatis" is more likely to be useful (but if
there is much disagreement "info types" can be fixed). */
- add_info ("types", types_info,
+ add_info ("types", info_types_command,
_("All type names, or those matching REGEXP."));
- add_info ("sources", sources_info,
+ add_info ("sources", info_sources_command,
_("Source files in the program."));
add_com ("rbreak", class_breakpoint, rbreak_command,