| Index: gdb/linespec.c
|
| diff --git a/gdb/linespec.c b/gdb/linespec.c
|
| index 683299968a52c8a112b5cac634a50170b377f02c..9468f265a14adb50840a49cd588e7d3d7ca8f4ce 100644
|
| --- a/gdb/linespec.c
|
| +++ b/gdb/linespec.c
|
| @@ -1,6 +1,6 @@
|
| /* Parser for linespec for the GNU debugger, GDB.
|
|
|
| - Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1986-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -45,9 +45,6 @@
|
| #include "ada-lang.h"
|
| #include "stack.h"
|
|
|
| -typedef struct symtab *symtab_p;
|
| -DEF_VEC_P (symtab_p);
|
| -
|
| typedef struct symbol *symbolp;
|
| DEF_VEC_P (symbolp);
|
|
|
| @@ -64,16 +61,9 @@ struct address_entry
|
| CORE_ADDR addr;
|
| };
|
|
|
| -/* A helper struct which just holds a minimal symbol and the object
|
| - file from which it came. */
|
| -
|
| -typedef struct minsym_and_objfile
|
| -{
|
| - struct minimal_symbol *minsym;
|
| - struct objfile *objfile;
|
| -} minsym_and_objfile_d;
|
| +typedef struct bound_minimal_symbol bound_minimal_symbol_d;
|
|
|
| -DEF_VEC_O (minsym_and_objfile_d);
|
| +DEF_VEC_O (bound_minimal_symbol_d);
|
|
|
| /* An enumeration of possible signs for a line offset. */
|
| enum offset_relative_sign
|
| @@ -110,7 +100,7 @@ struct linespec
|
| currently precludes the use of other members. */
|
|
|
| /* The expression entered by the user. */
|
| - char *expression;
|
| + const char *expression;
|
|
|
| /* The resulting PC expression derived from evaluating EXPRESSION. */
|
| CORE_ADDR expr_pc;
|
| @@ -118,29 +108,29 @@ struct linespec
|
| /* Any specified file symtabs. */
|
|
|
| /* The user-supplied source filename or NULL if none was specified. */
|
| - char *source_filename;
|
| + const char *source_filename;
|
|
|
| /* The list of symtabs to search to which to limit the search. May not
|
| be NULL. If SOURCE_FILENAME is NULL (no user-specified filename),
|
| FILE_SYMTABS should contain one single NULL member. This will
|
| cause the code to use the default symtab. */
|
| - VEC (symtab_p) *file_symtabs;
|
| + VEC (symtab_ptr) *file_symtabs;
|
|
|
| /* The name of a function or method and any matching symbols. */
|
|
|
| /* The user-specified function name. If no function name was
|
| supplied, this may be NULL. */
|
| - char *function_name;
|
| + const char *function_name;
|
|
|
| /* A list of matching function symbols and minimal symbols. Both lists
|
| may be NULL if no matching symbols were found. */
|
| VEC (symbolp) *function_symbols;
|
| - VEC (minsym_and_objfile_d) *minimal_symbols;
|
| + VEC (bound_minimal_symbol_d) *minimal_symbols;
|
|
|
| /* The name of a label and matching symbols. */
|
|
|
| /* The user-specified label name. */
|
| - char *label_name;
|
| + const char *label_name;
|
|
|
| /* A structure of matching label symbols and the corresponding
|
| function symbol in which the label was found. Both may be NULL
|
| @@ -157,6 +147,21 @@ struct linespec
|
| };
|
| typedef struct linespec *linespec_p;
|
|
|
| +/* A canonical linespec represented as a symtab-related string.
|
| +
|
| + Each entry represents the "SYMTAB:SUFFIX" linespec string.
|
| + SYMTAB can be converted for example by symtab_to_fullname or
|
| + symtab_to_filename_for_display as needed. */
|
| +
|
| +struct linespec_canonical_name
|
| +{
|
| + /* Remaining text part of the linespec string. */
|
| + char *suffix;
|
| +
|
| + /* If NULL then SUFFIX is the whole linespec string. */
|
| + struct symtab *symtab;
|
| +};
|
| +
|
| /* An instance of this is used to keep all state while linespec
|
| operates. This instance is passed around as a 'this' pointer to
|
| the various implementation methods. */
|
| @@ -186,7 +191,7 @@ struct linespec_state
|
| struct linespec_result *canonical;
|
|
|
| /* Canonical strings that mirror the symtabs_and_lines result. */
|
| - char **canonical_names;
|
| + struct linespec_canonical_name *canonical_names;
|
|
|
| /* This is a set of address_entry objects which is used to prevent
|
| duplicate symbols from being entered into the result. */
|
| @@ -202,13 +207,13 @@ struct collect_info
|
| struct linespec_state *state;
|
|
|
| /* A list of symtabs to which to restrict matches. */
|
| - VEC (symtab_p) *file_symtabs;
|
| + VEC (symtab_ptr) *file_symtabs;
|
|
|
| /* The result being accumulated. */
|
| struct
|
| {
|
| VEC (symbolp) *symbols;
|
| - VEC (minsym_and_objfile_d) *minimal_symbols;
|
| + VEC (bound_minimal_symbol_d) *minimal_symbols;
|
| } result;
|
| };
|
|
|
| @@ -273,10 +278,10 @@ struct ls_parser
|
| struct
|
| {
|
| /* Save head of input stream. */
|
| - char *saved_arg;
|
| + const char *saved_arg;
|
|
|
| /* Head of the input stream. */
|
| - char **stream;
|
| + const char **stream;
|
| #define PARSER_STREAM(P) (*(P)->lexer.stream)
|
|
|
| /* The current token. */
|
| @@ -303,27 +308,32 @@ typedef struct ls_parser linespec_parser;
|
|
|
| /* Prototypes for local functions. */
|
|
|
| +static void iterate_over_file_blocks (struct symtab *symtab,
|
| + const char *name, domain_enum domain,
|
| + symbol_found_callback_ftype *callback,
|
| + void *data);
|
| +
|
| static void initialize_defaults (struct symtab **default_symtab,
|
| int *default_line);
|
|
|
| -static CORE_ADDR linespec_expression_to_pc (char **exp_ptr);
|
| +static CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
|
|
|
| static struct symtabs_and_lines decode_objc (struct linespec_state *self,
|
| linespec_p ls,
|
| - char **argptr);
|
| + const char **argptr);
|
|
|
| -static VEC (symtab_p) *symtabs_from_filename (const char *);
|
| +static VEC (symtab_ptr) *symtabs_from_filename (const char *);
|
|
|
| static VEC (symbolp) *find_label_symbols (struct linespec_state *self,
|
| VEC (symbolp) *function_symbols,
|
| VEC (symbolp) **label_funcs_ret,
|
| const char *name);
|
|
|
| -void find_linespec_symbols (struct linespec_state *self,
|
| - VEC (symtab_p) *file_symtabs,
|
| - const char *name,
|
| - VEC (symbolp) **symbols,
|
| - VEC (minsym_and_objfile_d) **minsyms);
|
| +static void find_linespec_symbols (struct linespec_state *self,
|
| + VEC (symtab_ptr) *file_symtabs,
|
| + const char *name,
|
| + VEC (symbolp) **symbols,
|
| + VEC (bound_minimal_symbol_d) **minsyms);
|
|
|
| static struct line_offset
|
| linespec_parse_variable (struct linespec_state *self,
|
| @@ -340,7 +350,7 @@ static void add_all_symbol_names_from_pspace (struct collect_info *info,
|
| struct program_space *pspace,
|
| VEC (const_char_ptr) *names);
|
|
|
| -static VEC (symtab_p) *collect_symtabs_from_filename (const char *file);
|
| +static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file);
|
|
|
| static void decode_digits_ordinary (struct linespec_state *self,
|
| linespec_p ls,
|
| @@ -396,7 +406,7 @@ linespec_lexer_lex_number (linespec_parser *parser, linespec_token *tokenp)
|
| }
|
|
|
| /* If the next character in the input buffer is not a space, comma,
|
| - quote, or colon, the input does not represent a number. */
|
| + quote, or colon, this input does not represent a number. */
|
| if (*PARSER_STREAM (parser) != '\0'
|
| && !isspace (*PARSER_STREAM (parser)) && *PARSER_STREAM (parser) != ','
|
| && *PARSER_STREAM (parser) != ':'
|
| @@ -505,12 +515,12 @@ is_closing_quote_enclosed (const char *p)
|
| This helper function assists with lexing string segments
|
| which might contain valid (non-terminating) commas. */
|
|
|
| -static char *
|
| -find_parameter_list_end (char *input)
|
| +static const char *
|
| +find_parameter_list_end (const char *input)
|
| {
|
| char end_char, start_char;
|
| int depth;
|
| - char *p;
|
| + const char *p;
|
|
|
| start_char = *input;
|
| if (start_char == '(')
|
| @@ -547,7 +557,7 @@ static linespec_token
|
| linespec_lexer_lex_string (linespec_parser *parser)
|
| {
|
| linespec_token token;
|
| - char *start = PARSER_STREAM (parser);
|
| + const char *start = PARSER_STREAM (parser);
|
|
|
| token.type = LSTOKEN_STRING;
|
|
|
| @@ -597,7 +607,7 @@ linespec_lexer_lex_string (linespec_parser *parser)
|
| }
|
| else
|
| {
|
| - char *p;
|
| + const char *p;
|
|
|
| /* Otherwise, only identifier characters are permitted.
|
| Spaces are the exception. In general, we keep spaces,
|
| @@ -611,7 +621,7 @@ linespec_lexer_lex_string (linespec_parser *parser)
|
| {
|
| if (isspace (*PARSER_STREAM (parser)))
|
| {
|
| - p = skip_spaces (PARSER_STREAM (parser));
|
| + p = skip_spaces_const (PARSER_STREAM (parser));
|
| /* When we get here we know we've found something followed by
|
| a space (we skip over parens and templates below).
|
| So if we find a keyword now, we know it is a keyword and not,
|
| @@ -671,7 +681,7 @@ linespec_lexer_lex_string (linespec_parser *parser)
|
| else if (*PARSER_STREAM (parser) == '<'
|
| || *PARSER_STREAM (parser) == '(')
|
| {
|
| - char *p;
|
| + const char *p;
|
|
|
| p = find_parameter_list_end (PARSER_STREAM (parser));
|
| if (p != NULL)
|
| @@ -723,7 +733,7 @@ linespec_lexer_lex_one (linespec_parser *parser)
|
| if (parser->lexer.current.type == LSTOKEN_CONSUMED)
|
| {
|
| /* Skip any whitespace. */
|
| - PARSER_STREAM (parser) = skip_spaces (PARSER_STREAM (parser));
|
| + PARSER_STREAM (parser) = skip_spaces_const (PARSER_STREAM (parser));
|
|
|
| /* Check for a keyword, they end the linespec. */
|
| keyword = NULL;
|
| @@ -809,7 +819,7 @@ static linespec_token
|
| linespec_lexer_peek_token (linespec_parser *parser)
|
| {
|
| linespec_token next;
|
| - char *saved_stream = PARSER_STREAM (parser);
|
| + const char *saved_stream = PARSER_STREAM (parser);
|
| linespec_token saved_token = parser->lexer.current;
|
|
|
| next = linespec_lexer_consume_token (parser);
|
| @@ -833,40 +843,51 @@ add_sal_to_sals_basic (struct symtabs_and_lines *sals,
|
|
|
| /* Add SAL to SALS, and also update SELF->CANONICAL_NAMES to reflect
|
| the new sal, if needed. If not NULL, SYMNAME is the name of the
|
| - symbol to use when constructing the new canonical name. */
|
| + symbol to use when constructing the new canonical name.
|
| +
|
| + If LITERAL_CANONICAL is non-zero, SYMNAME will be used as the
|
| + canonical name for the SAL. */
|
|
|
| static void
|
| add_sal_to_sals (struct linespec_state *self,
|
| struct symtabs_and_lines *sals,
|
| struct symtab_and_line *sal,
|
| - const char *symname)
|
| + const char *symname, int literal_canonical)
|
| {
|
| add_sal_to_sals_basic (sals, sal);
|
|
|
| if (self->canonical)
|
| {
|
| - char *canonical_name = NULL;
|
| + struct linespec_canonical_name *canonical;
|
|
|
| self->canonical_names = xrealloc (self->canonical_names,
|
| - sals->nelts * sizeof (char *));
|
| - if (sal->symtab && sal->symtab->filename)
|
| + (sals->nelts
|
| + * sizeof (*self->canonical_names)));
|
| + canonical = &self->canonical_names[sals->nelts - 1];
|
| + if (!literal_canonical && sal->symtab)
|
| {
|
| - char *filename = sal->symtab->filename;
|
| + const char *fullname = symtab_to_fullname (sal->symtab);
|
|
|
| /* Note that the filter doesn't have to be a valid linespec
|
| input. We only apply the ":LINE" treatment to Ada for
|
| the time being. */
|
| if (symname != NULL && sal->line != 0
|
| && self->language->la_language == language_ada)
|
| - canonical_name = xstrprintf ("%s:%s:%d", filename, symname,
|
| - sal->line);
|
| + canonical->suffix = xstrprintf ("%s:%d", symname, sal->line);
|
| else if (symname != NULL)
|
| - canonical_name = xstrprintf ("%s:%s", filename, symname);
|
| + canonical->suffix = xstrdup (symname);
|
| else
|
| - canonical_name = xstrprintf ("%s:%d", filename, sal->line);
|
| + canonical->suffix = xstrprintf ("%d", sal->line);
|
| + canonical->symtab = sal->symtab;
|
| + }
|
| + else
|
| + {
|
| + if (symname != NULL)
|
| + canonical->suffix = xstrdup (symname);
|
| + else
|
| + canonical->suffix = NULL;
|
| + canonical->symtab = NULL;
|
| }
|
| -
|
| - self->canonical_names[sals->nelts - 1] = canonical_name;
|
| }
|
| }
|
|
|
| @@ -1013,22 +1034,20 @@ iterate_over_all_matching_symtabs (struct linespec_state *state,
|
|
|
| ALL_OBJFILE_PRIMARY_SYMTABS (objfile, symtab)
|
| {
|
| - struct block *block;
|
| -
|
| - block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
| - LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
|
| + iterate_over_file_blocks (symtab, name, domain, callback, data);
|
|
|
| if (include_inline)
|
| {
|
| struct symbol_and_data_callback cad = { callback, data };
|
| + struct block *block;
|
| int i;
|
|
|
| for (i = FIRST_LOCAL_BLOCK;
|
| i < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (symtab)); i++)
|
| {
|
| block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), i);
|
| - LA_ITERATE_OVER_SYMBOLS (block, name, domain,
|
| - iterate_inline_only, &cad);
|
| + state->language->la_iterate_over_symbols
|
| + (block, name, domain, iterate_inline_only, &cad);
|
| }
|
| }
|
| }
|
| @@ -1036,30 +1055,39 @@ iterate_over_all_matching_symtabs (struct linespec_state *state,
|
| }
|
| }
|
|
|
| -/* Returns the block to be used for symbol searches for the given SYMTAB,
|
| - which may be NULL. */
|
| +/* Returns the block to be used for symbol searches from
|
| + the current location. */
|
|
|
| static struct block *
|
| -get_search_block (struct symtab *symtab)
|
| +get_current_search_block (void)
|
| {
|
| struct block *block;
|
| + enum language save_language;
|
|
|
| - if (symtab != NULL)
|
| - block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
| - else
|
| - {
|
| - enum language save_language;
|
| -
|
| - /* get_selected_block can change the current language when there is
|
| - no selected frame yet. */
|
| - save_language = current_language->la_language;
|
| - block = get_selected_block (0);
|
| - set_language (save_language);
|
| - }
|
| + /* get_selected_block can change the current language when there is
|
| + no selected frame yet. */
|
| + save_language = current_language->la_language;
|
| + block = get_selected_block (0);
|
| + set_language (save_language);
|
|
|
| return block;
|
| }
|
|
|
| +/* Iterate over static and global blocks. */
|
| +
|
| +static void
|
| +iterate_over_file_blocks (struct symtab *symtab,
|
| + const char *name, domain_enum domain,
|
| + symbol_found_callback_ftype *callback, void *data)
|
| +{
|
| + struct block *block;
|
| +
|
| + for (block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
| + block != NULL;
|
| + block = BLOCK_SUPERBLOCK (block))
|
| + LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
|
| +}
|
| +
|
| /* A helper for find_method. This finds all methods in type T which
|
| match NAME. It adds matching symbol names to RESULT_NAMES, and
|
| adds T's direct superclasses to SUPERCLASSES. */
|
| @@ -1069,7 +1097,6 @@ find_methods (struct type *t, const char *name,
|
| VEC (const_char_ptr) **result_names,
|
| VEC (typep) **superclasses)
|
| {
|
| - int i1 = 0;
|
| int ibase;
|
| const char *class_name = type_name_no_tag (t);
|
|
|
| @@ -1079,7 +1106,6 @@ find_methods (struct type *t, const char *name,
|
| if (class_name)
|
| {
|
| int method_counter;
|
| - int name_len = strlen (name);
|
|
|
| CHECK_TYPEDEF (t);
|
|
|
| @@ -1196,6 +1222,19 @@ find_toplevel_string (const char *haystack, const char *needle)
|
| return NULL;
|
| }
|
|
|
| +/* Convert CANONICAL to its string representation using
|
| + symtab_to_fullname for SYMTAB. The caller must xfree the result. */
|
| +
|
| +static char *
|
| +canonical_to_fullform (const struct linespec_canonical_name *canonical)
|
| +{
|
| + if (canonical->symtab == NULL)
|
| + return xstrdup (canonical->suffix);
|
| + else
|
| + return xstrprintf ("%s:%s", symtab_to_fullname (canonical->symtab),
|
| + canonical->suffix);
|
| +}
|
| +
|
| /* Given FILTERS, a list of canonical names, filter the sals in RESULT
|
| and store the result in SELF->CANONICAL. */
|
|
|
| @@ -1216,8 +1255,18 @@ filter_results (struct linespec_state *self,
|
|
|
| for (j = 0; j < result->nelts; ++j)
|
| {
|
| - if (strcmp (name, self->canonical_names[j]) == 0)
|
| + const struct linespec_canonical_name *canonical;
|
| + char *fullform;
|
| + struct cleanup *cleanup;
|
| +
|
| + canonical = &self->canonical_names[j];
|
| + fullform = canonical_to_fullform (canonical);
|
| + cleanup = make_cleanup (xfree, fullform);
|
| +
|
| + if (strcmp (name, fullform) == 0)
|
| add_sal_to_sals_basic (&lsal.sals, &result->sals[j]);
|
| +
|
| + do_cleanups (cleanup);
|
| }
|
|
|
| if (lsal.sals.nelts > 0)
|
| @@ -1243,6 +1292,44 @@ convert_results_to_lsals (struct linespec_state *self,
|
| VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
|
| }
|
|
|
| +/* A structure that contains two string representations of a struct
|
| + linespec_canonical_name:
|
| + - one where the the symtab's fullname is used;
|
| + - one where the filename followed the "set filename-display"
|
| + setting. */
|
| +
|
| +struct decode_line_2_item
|
| +{
|
| + /* The form using symtab_to_fullname.
|
| + It must be xfree'ed after use. */
|
| + char *fullform;
|
| +
|
| + /* The form using symtab_to_filename_for_display.
|
| + It must be xfree'ed after use. */
|
| + char *displayform;
|
| +
|
| + /* Field is initialized to zero and it is set to one if the user
|
| + requested breakpoint for this entry. */
|
| + unsigned int selected : 1;
|
| +};
|
| +
|
| +/* Helper for qsort to sort decode_line_2_item entries by DISPLAYFORM and
|
| + secondarily by FULLFORM. */
|
| +
|
| +static int
|
| +decode_line_2_compare_items (const void *ap, const void *bp)
|
| +{
|
| + const struct decode_line_2_item *a = ap;
|
| + const struct decode_line_2_item *b = bp;
|
| + int retval;
|
| +
|
| + retval = strcmp (a->displayform, b->displayform);
|
| + if (retval != 0)
|
| + return retval;
|
| +
|
| + return strcmp (a->fullform, b->fullform);
|
| +}
|
| +
|
| /* Handle multiple results in RESULT depending on SELECT_MODE. This
|
| will either return normally, throw an exception on multiple
|
| results, or present a menu to the user. On return, the SALS vector
|
| @@ -1253,58 +1340,80 @@ decode_line_2 (struct linespec_state *self,
|
| struct symtabs_and_lines *result,
|
| const char *select_mode)
|
| {
|
| - const char *iter;
|
| char *args, *prompt;
|
| int i;
|
| struct cleanup *old_chain;
|
| - VEC (const_char_ptr) *item_names = NULL, *filters = NULL;
|
| + VEC (const_char_ptr) *filters = NULL;
|
| struct get_number_or_range_state state;
|
| + struct decode_line_2_item *items;
|
| + int items_count;
|
|
|
| gdb_assert (select_mode != multiple_symbols_all);
|
| gdb_assert (self->canonical != NULL);
|
| + gdb_assert (result->nelts >= 1);
|
| +
|
| + old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &filters);
|
|
|
| - old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &item_names);
|
| - make_cleanup (VEC_cleanup (const_char_ptr), &filters);
|
| - for (i = 0; i < result->nelts; ++i)
|
| + /* Prepare ITEMS array. */
|
| + items_count = result->nelts;
|
| + items = xmalloc (sizeof (*items) * items_count);
|
| + make_cleanup (xfree, items);
|
| + for (i = 0; i < items_count; ++i)
|
| {
|
| - int j, found = 0;
|
| - const char *iter;
|
| + const struct linespec_canonical_name *canonical;
|
| + struct decode_line_2_item *item;
|
|
|
| - gdb_assert (self->canonical_names[i] != NULL);
|
| - for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j)
|
| + canonical = &self->canonical_names[i];
|
| + gdb_assert (canonical->suffix != NULL);
|
| + item = &items[i];
|
| +
|
| + item->fullform = canonical_to_fullform (canonical);
|
| + make_cleanup (xfree, item->fullform);
|
| +
|
| + if (canonical->symtab == NULL)
|
| + item->displayform = canonical->suffix;
|
| + else
|
| {
|
| - if (strcmp (iter, self->canonical_names[i]) == 0)
|
| - {
|
| - found = 1;
|
| - break;
|
| - }
|
| + const char *fn_for_display;
|
| +
|
| + fn_for_display = symtab_to_filename_for_display (canonical->symtab);
|
| + item->displayform = xstrprintf ("%s:%s", fn_for_display,
|
| + canonical->suffix);
|
| + make_cleanup (xfree, item->displayform);
|
| }
|
|
|
| - if (!found)
|
| - VEC_safe_push (const_char_ptr, item_names, self->canonical_names[i]);
|
| + item->selected = 0;
|
| + }
|
| +
|
| + /* Sort the list of method names. */
|
| + qsort (items, items_count, sizeof (*items), decode_line_2_compare_items);
|
| +
|
| + /* Remove entries with the same FULLFORM. */
|
| + if (items_count >= 2)
|
| + {
|
| + struct decode_line_2_item *dst, *src;
|
| +
|
| + dst = items;
|
| + for (src = &items[1]; src < &items[items_count]; src++)
|
| + if (strcmp (src->fullform, dst->fullform) != 0)
|
| + *++dst = *src;
|
| + items_count = dst + 1 - items;
|
| }
|
|
|
| - if (select_mode == multiple_symbols_cancel
|
| - && VEC_length (const_char_ptr, item_names) > 1)
|
| + if (select_mode == multiple_symbols_cancel && items_count > 1)
|
| error (_("canceled because the command is ambiguous\n"
|
| "See set/show multiple-symbol."));
|
|
|
| - if (select_mode == multiple_symbols_all
|
| - || VEC_length (const_char_ptr, item_names) == 1)
|
| + if (select_mode == multiple_symbols_all || items_count == 1)
|
| {
|
| do_cleanups (old_chain);
|
| convert_results_to_lsals (self, result);
|
| return;
|
| }
|
|
|
| - /* Sort the list of method names alphabetically. */
|
| - qsort (VEC_address (const_char_ptr, item_names),
|
| - VEC_length (const_char_ptr, item_names),
|
| - sizeof (const_char_ptr), compare_strings);
|
| -
|
| printf_unfiltered (_("[0] cancel\n[1] all\n"));
|
| - for (i = 0; VEC_iterate (const_char_ptr, item_names, i, iter); ++i)
|
| - printf_unfiltered ("[%d] %s\n", i + 2, iter);
|
| + for (i = 0; i < items_count; i++)
|
| + printf_unfiltered ("[%d] %s\n", i + 2, items[i].displayform);
|
|
|
| prompt = getenv ("PS2");
|
| if (prompt == NULL)
|
| @@ -1339,21 +1448,21 @@ decode_line_2 (struct linespec_state *self,
|
| }
|
|
|
| num -= 2;
|
| - if (num >= VEC_length (const_char_ptr, item_names))
|
| + if (num >= items_count)
|
| printf_unfiltered (_("No choice number %d.\n"), num);
|
| else
|
| {
|
| - const char *elt = VEC_index (const_char_ptr, item_names, num);
|
| + struct decode_line_2_item *item = &items[num];
|
|
|
| - if (elt != NULL)
|
| + if (!item->selected)
|
| {
|
| - VEC_safe_push (const_char_ptr, filters, elt);
|
| - VEC_replace (const_char_ptr, item_names, num, NULL);
|
| + VEC_safe_push (const_char_ptr, filters, item->fullform);
|
| + item->selected = 1;
|
| }
|
| else
|
| {
|
| printf_unfiltered (_("duplicate request for %d ignored.\n"),
|
| - num);
|
| + num + 2);
|
| }
|
| }
|
| }
|
| @@ -1370,7 +1479,7 @@ decode_line_2 (struct linespec_state *self,
|
| FILENAME). */
|
|
|
| static void ATTRIBUTE_NORETURN
|
| -symbol_not_found_error (char *symbol, char *filename)
|
| +symbol_not_found_error (const char *symbol, const char *filename)
|
| {
|
| if (symbol == NULL)
|
| symbol = "";
|
| @@ -1443,7 +1552,7 @@ unexpected_linespec_error (linespec_parser *parser)
|
| /* Parse and return a line offset in STRING. */
|
|
|
| static struct line_offset
|
| -linespec_parse_line_offset (char *string)
|
| +linespec_parse_line_offset (const char *string)
|
| {
|
| struct line_offset line_offset = {0, LINE_OFFSET_NONE};
|
|
|
| @@ -1471,7 +1580,7 @@ linespec_parse_basic (linespec_parser *parser)
|
| char *name;
|
| linespec_token token;
|
| VEC (symbolp) *symbols, *labels;
|
| - VEC (minsym_and_objfile_d) *minimal_symbols;
|
| + VEC (bound_minimal_symbol_d) *minimal_symbols;
|
| struct cleanup *cleanup;
|
|
|
| /* Get the next token. */
|
| @@ -1530,7 +1639,7 @@ linespec_parse_basic (linespec_parser *parser)
|
| else
|
| {
|
| /* NAME was not a function or a method. So it must be a label
|
| - name. */
|
| + name or user specified variable like "break foo.c:$zippo". */
|
| labels = find_label_symbols (PARSER_STATE (parser), NULL,
|
| &symbols, name);
|
| if (labels != NULL)
|
| @@ -1541,6 +1650,22 @@ linespec_parse_basic (linespec_parser *parser)
|
| symbols = NULL;
|
| discard_cleanups (cleanup);
|
| }
|
| + else if (token.type == LSTOKEN_STRING
|
| + && *LS_TOKEN_STOKEN (token).ptr == '$')
|
| + {
|
| + /* User specified a convenience variable or history value. */
|
| + PARSER_RESULT (parser)->line_offset
|
| + = linespec_parse_variable (PARSER_STATE (parser), name);
|
| +
|
| + if (PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
|
| + {
|
| + /* The user-specified variable was not valid. Do not
|
| + throw an error here. parse_linespec will do it for us. */
|
| + PARSER_RESULT (parser)->function_name = name;
|
| + discard_cleanups (cleanup);
|
| + return;
|
| + }
|
| + }
|
| else
|
| {
|
| /* The name is also not a label. Abort parsing. Do not throw
|
| @@ -1718,22 +1843,24 @@ create_sals_line_offset (struct linespec_state *self,
|
|
|
| /* This is where we need to make sure we have good defaults.
|
| We must guarantee that this section of code is never executed
|
| - when we are called with just a function anme, since
|
| + when we are called with just a function name, since
|
| set_default_source_symtab_and_line uses
|
| select_source_symtab that calls us with such an argument. */
|
|
|
| - if (VEC_length (symtab_p, ls->file_symtabs) == 1
|
| - && VEC_index (symtab_p, ls->file_symtabs, 0) == NULL)
|
| + if (VEC_length (symtab_ptr, ls->file_symtabs) == 1
|
| + && VEC_index (symtab_ptr, ls->file_symtabs, 0) == NULL)
|
| {
|
| + const char *fullname;
|
| +
|
| set_current_program_space (self->program_space);
|
|
|
| /* Make sure we have at least a default source line. */
|
| set_default_source_symtab_and_line ();
|
| initialize_defaults (&self->default_symtab, &self->default_line);
|
| - VEC_pop (symtab_p, ls->file_symtabs);
|
| - VEC_free (symtab_p, ls->file_symtabs);
|
| - ls->file_symtabs
|
| - = collect_symtabs_from_filename (self->default_symtab->filename);
|
| + fullname = symtab_to_fullname (self->default_symtab);
|
| + VEC_pop (symtab_ptr, ls->file_symtabs);
|
| + VEC_free (symtab_ptr, ls->file_symtabs);
|
| + ls->file_symtabs = collect_symtabs_from_filename (fullname);
|
| use_default = 1;
|
| }
|
|
|
| @@ -1832,7 +1959,7 @@ create_sals_line_offset (struct linespec_state *self,
|
| found. */
|
| intermediate_results.sals[i].line = val.line;
|
| add_sal_to_sals (self, &values, &intermediate_results.sals[i],
|
| - sym ? SYMBOL_NATURAL_NAME (sym) : NULL);
|
| + sym ? SYMBOL_NATURAL_NAME (sym) : NULL, 0);
|
| }
|
|
|
| do_cleanups (cleanup);
|
| @@ -1860,13 +1987,14 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
|
|
| if (ls->expression != NULL)
|
| {
|
| + struct symtab_and_line sal;
|
| +
|
| /* We have an expression. No other attribute is allowed. */
|
| - sals.sals = XMALLOC (struct symtab_and_line);
|
| - sals.nelts = 1;
|
| - sals.sals[0] = find_pc_line (ls->expr_pc, 0);
|
| - sals.sals[0].pc = ls->expr_pc;
|
| - sals.sals[0].section = find_pc_overlay (ls->expr_pc);
|
| - sals.sals[0].explicit_pc = 1;
|
| + sal = find_pc_line (ls->expr_pc, 0);
|
| + sal.pc = ls->expr_pc;
|
| + sal.section = find_pc_overlay (ls->expr_pc);
|
| + sal.explicit_pc = 1;
|
| + add_sal_to_sals (state, &sals, &sal, ls->expression, 1);
|
| }
|
| else if (ls->labels.label_symbols != NULL)
|
| {
|
| @@ -1877,9 +2005,12 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
|
|
| for (i = 0; VEC_iterate (symbolp, ls->labels.label_symbols, i, sym); ++i)
|
| {
|
| - if (symbol_to_sal (&sal, state->funfirstline, sym))
|
| + struct program_space *pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
|
| +
|
| + if (symbol_to_sal (&sal, state->funfirstline, sym)
|
| + && maybe_add_address (state->addr_set, pspace, sal.pc))
|
| add_sal_to_sals (state, &sals, &sal,
|
| - SYMBOL_NATURAL_NAME (sym));
|
| + SYMBOL_NATURAL_NAME (sym), 0);
|
| }
|
| }
|
| else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL)
|
| @@ -1888,7 +2019,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
| int i;
|
| struct symtab_and_line sal;
|
| struct symbol *sym;
|
| - minsym_and_objfile_d *elem;
|
| + bound_minimal_symbol_d *elem;
|
| struct program_space *pspace;
|
|
|
| if (ls->function_symbols != NULL)
|
| @@ -1905,19 +2036,21 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
| set_current_program_space (pspace);
|
| if (symbol_to_sal (&sal, state->funfirstline, sym)
|
| && maybe_add_address (state->addr_set, pspace, sal.pc))
|
| - add_sal_to_sals (state, &sals, &sal, SYMBOL_NATURAL_NAME (sym));
|
| + add_sal_to_sals (state, &sals, &sal,
|
| + SYMBOL_NATURAL_NAME (sym), 0);
|
| }
|
| }
|
|
|
| if (ls->minimal_symbols != NULL)
|
| {
|
| /* Sort minimal symbols by program space, too. */
|
| - qsort (VEC_address (minsym_and_objfile_d, ls->minimal_symbols),
|
| - VEC_length (minsym_and_objfile_d, ls->minimal_symbols),
|
| - sizeof (minsym_and_objfile_d), compare_msymbols);
|
| + qsort (VEC_address (bound_minimal_symbol_d, ls->minimal_symbols),
|
| + VEC_length (bound_minimal_symbol_d, ls->minimal_symbols),
|
| + sizeof (bound_minimal_symbol_d), compare_msymbols);
|
|
|
| for (i = 0;
|
| - VEC_iterate (minsym_and_objfile_d, ls->minimal_symbols, i, elem);
|
| + VEC_iterate (bound_minimal_symbol_d, ls->minimal_symbols,
|
| + i, elem);
|
| ++i)
|
| {
|
| pspace = elem->objfile->pspace;
|
| @@ -1933,7 +2066,15 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
|
|
| /* Make sure we have a filename for canonicalization. */
|
| if (ls->source_filename == NULL)
|
| - ls->source_filename = xstrdup (state->default_symtab->filename);
|
| + {
|
| + const char *fullname = symtab_to_fullname (state->default_symtab);
|
| +
|
| + /* It may be more appropriate to keep DEFAULT_SYMTAB in its symtab
|
| + form so that displaying SOURCE_FILENAME can follow the current
|
| + FILENAME_DISPLAY_STRING setting. But as it is used only rarely
|
| + it has been kept for code simplicity only in absolute form. */
|
| + ls->source_filename = xstrdup (fullname);
|
| + }
|
| }
|
| else
|
| {
|
| @@ -2003,7 +2144,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
|
| /* Parse the linespec in ARGPTR. */
|
|
|
| static struct symtabs_and_lines
|
| -parse_linespec (linespec_parser *parser, char **argptr)
|
| +parse_linespec (linespec_parser *parser, const char **argptr)
|
| {
|
| linespec_token token;
|
| struct symtabs_and_lines values;
|
| @@ -2054,7 +2195,8 @@ parse_linespec (linespec_parser *parser, char **argptr)
|
| /* It must be either LSTOKEN_STRING or LSTOKEN_NUMBER. */
|
| if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '*')
|
| {
|
| - char *expr, *copy;
|
| + char *expr;
|
| + const char *copy;
|
|
|
| /* User specified an expression, *EXPR. */
|
| copy = expr = copy_token_string (token);
|
| @@ -2082,27 +2224,24 @@ parse_linespec (linespec_parser *parser, char **argptr)
|
| char *var;
|
|
|
| /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB. */
|
| - VEC_safe_push (symtab_p, PARSER_RESULT (parser)->file_symtabs, NULL);
|
| + VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
|
|
|
| /* User specified a convenience variable or history value. */
|
| var = copy_token_string (token);
|
| cleanup = make_cleanup (xfree, var);
|
| PARSER_RESULT (parser)->line_offset
|
| = linespec_parse_variable (PARSER_STATE (parser), var);
|
| + do_cleanups (cleanup);
|
|
|
| /* If a line_offset wasn't found (VAR is the name of a user
|
| variable/function), then skip to normal symbol processing. */
|
| if (PARSER_RESULT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
|
| {
|
| - discard_cleanups (cleanup);
|
| -
|
| /* Consume this token. */
|
| linespec_lexer_consume_token (parser);
|
|
|
| goto convert_to_sals;
|
| }
|
| -
|
| - do_cleanups (cleanup);
|
| }
|
| else if (token.type != LSTOKEN_STRING && token.type != LSTOKEN_NUMBER)
|
| unexpected_linespec_error (parser);
|
| @@ -2146,7 +2285,7 @@ parse_linespec (linespec_parser *parser, char **argptr)
|
| xfree (user_filename);
|
|
|
| /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB. */
|
| - VEC_safe_push (symtab_p, PARSER_RESULT (parser)->file_symtabs, NULL);
|
| + VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
|
| }
|
| }
|
| /* If the next token is not EOI, KEYWORD, or COMMA, issue an error. */
|
| @@ -2161,7 +2300,7 @@ parse_linespec (linespec_parser *parser, char **argptr)
|
| else
|
| {
|
| /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB. */
|
| - VEC_safe_push (symtab_p, PARSER_RESULT (parser)->file_symtabs, NULL);
|
| + VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
|
| }
|
|
|
| /* Parse the rest of the linespec. */
|
| @@ -2250,23 +2389,19 @@ linespec_parser_delete (void *arg)
|
| {
|
| linespec_parser *parser = (linespec_parser *) arg;
|
|
|
| - if (PARSER_RESULT (parser)->expression)
|
| - xfree (PARSER_RESULT (parser)->expression);
|
| - if (PARSER_RESULT (parser)->source_filename)
|
| - xfree (PARSER_RESULT (parser)->source_filename);
|
| - if (PARSER_RESULT (parser)->label_name)
|
| - xfree (PARSER_RESULT (parser)->label_name);
|
| - if (PARSER_RESULT (parser)->function_name)
|
| - xfree (PARSER_RESULT (parser)->function_name);
|
| + xfree ((char *) PARSER_RESULT (parser)->expression);
|
| + xfree ((char *) PARSER_RESULT (parser)->source_filename);
|
| + xfree ((char *) PARSER_RESULT (parser)->label_name);
|
| + xfree ((char *) PARSER_RESULT (parser)->function_name);
|
|
|
| if (PARSER_RESULT (parser)->file_symtabs != NULL)
|
| - VEC_free (symtab_p, PARSER_RESULT (parser)->file_symtabs);
|
| + VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs);
|
|
|
| if (PARSER_RESULT (parser)->function_symbols != NULL)
|
| VEC_free (symbolp, PARSER_RESULT (parser)->function_symbols);
|
|
|
| if (PARSER_RESULT (parser)->minimal_symbols != NULL)
|
| - VEC_free (minsym_and_objfile_d, PARSER_RESULT (parser)->minimal_symbols);
|
| + VEC_free (bound_minimal_symbol_d, PARSER_RESULT (parser)->minimal_symbols);
|
|
|
| if (PARSER_RESULT (parser)->labels.label_symbols != NULL)
|
| VEC_free (symbolp, PARSER_RESULT (parser)->labels.label_symbols);
|
| @@ -2288,10 +2423,10 @@ decode_line_full (char **argptr, int flags,
|
| {
|
| struct symtabs_and_lines result;
|
| struct cleanup *cleanups;
|
| - char *arg_start = *argptr;
|
| VEC (const_char_ptr) *filters = NULL;
|
| linespec_parser parser;
|
| struct linespec_state *state;
|
| + const char *copy, *orig;
|
|
|
| gdb_assert (canonical != NULL);
|
| /* The filter only makes sense for 'all'. */
|
| @@ -2307,27 +2442,25 @@ decode_line_full (char **argptr, int flags,
|
| cleanups = make_cleanup (linespec_parser_delete, &parser);
|
| save_current_program_space ();
|
|
|
| - result = parse_linespec (&parser, argptr);
|
| + orig = copy = *argptr;
|
| + result = parse_linespec (&parser, ©);
|
| + *argptr += copy - orig;
|
| state = PARSER_STATE (&parser);
|
|
|
| gdb_assert (result.nelts == 1 || canonical->pre_expanded);
|
| gdb_assert (canonical->addr_string != NULL);
|
| canonical->pre_expanded = 1;
|
|
|
| - /* Fill in the missing canonical names. */
|
| + /* Arrange for allocated canonical names to be freed. */
|
| if (result.nelts > 0)
|
| {
|
| int i;
|
|
|
| - if (state->canonical_names == NULL)
|
| - state->canonical_names = xcalloc (result.nelts, sizeof (char *));
|
| make_cleanup (xfree, state->canonical_names);
|
| for (i = 0; i < result.nelts; ++i)
|
| {
|
| - if (state->canonical_names[i] == NULL)
|
| - state->canonical_names[i] = savestring (arg_start,
|
| - *argptr - arg_start);
|
| - make_cleanup (xfree, state->canonical_names[i]);
|
| + gdb_assert (state->canonical_names[i].suffix != NULL);
|
| + make_cleanup (xfree, state->canonical_names[i].suffix);
|
| }
|
| }
|
|
|
| @@ -2366,13 +2499,16 @@ decode_line_1 (char **argptr, int flags,
|
| struct symtabs_and_lines result;
|
| linespec_parser parser;
|
| struct cleanup *cleanups;
|
| + const char *copy, *orig;
|
|
|
| linespec_parser_new (&parser, flags, current_language, default_symtab,
|
| default_line, NULL);
|
| cleanups = make_cleanup (linespec_parser_delete, &parser);
|
| save_current_program_space ();
|
|
|
| - result = parse_linespec (&parser, argptr);
|
| + orig = copy = *argptr;
|
| + result = parse_linespec (&parser, ©);
|
| + *argptr += copy - orig;
|
|
|
| do_cleanups (cleanups);
|
| return result;
|
| @@ -2450,7 +2586,7 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
|
| advancing EXP_PTR past any parsed text. */
|
|
|
| static CORE_ADDR
|
| -linespec_expression_to_pc (char **exp_ptr)
|
| +linespec_expression_to_pc (const char **exp_ptr)
|
| {
|
| if (current_program_space->executing_startup)
|
| /* The error message doesn't really matter, because this case
|
| @@ -2472,19 +2608,19 @@ linespec_expression_to_pc (char **exp_ptr)
|
| the existing C++ code to let the user choose one. */
|
|
|
| static struct symtabs_and_lines
|
| -decode_objc (struct linespec_state *self, linespec_p ls, char **argptr)
|
| +decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
|
| {
|
| struct collect_info info;
|
| VEC (const_char_ptr) *symbol_names = NULL;
|
| struct symtabs_and_lines values;
|
| - char *new_argptr;
|
| + const char *new_argptr;
|
| struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr),
|
| &symbol_names);
|
|
|
| info.state = self;
|
| info.file_symtabs = NULL;
|
| - VEC_safe_push (symtab_p, info.file_symtabs, NULL);
|
| - make_cleanup (VEC_cleanup (symtab_p), &info.file_symtabs);
|
| + VEC_safe_push (symtab_ptr, info.file_symtabs, NULL);
|
| + make_cleanup (VEC_cleanup (symtab_ptr), &info.file_symtabs);
|
| info.result.symbols = NULL;
|
| info.result.minimal_symbols = NULL;
|
| values.nelts = 0;
|
| @@ -2500,7 +2636,7 @@ decode_objc (struct linespec_state *self, linespec_p ls, char **argptr)
|
| add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
|
|
|
| if (!VEC_empty (symbolp, info.result.symbols)
|
| - || !VEC_empty (minsym_and_objfile_d, info.result.minimal_symbols))
|
| + || !VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
|
| {
|
| char *saved_arg;
|
|
|
| @@ -2508,6 +2644,7 @@ decode_objc (struct linespec_state *self, linespec_p ls, char **argptr)
|
| memcpy (saved_arg, *argptr, new_argptr - *argptr);
|
| saved_arg[new_argptr - *argptr] = '\0';
|
|
|
| + ls->function_name = xstrdup (saved_arg);
|
| ls->function_symbols = info.result.symbols;
|
| ls->minimal_symbols = info.result.minimal_symbols;
|
| values = convert_linespec_to_sals (self, ls);
|
| @@ -2576,7 +2713,7 @@ collect_one_symbol (struct symbol *sym, void *d)
|
| /* Return any symbols corresponding to CLASS_NAME in FILE_SYMTABS. */
|
|
|
| static VEC (symbolp) *
|
| -lookup_prefix_sym (struct linespec_state *state, VEC (symtab_p) *file_symtabs,
|
| +lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs,
|
| const char *class_name)
|
| {
|
| int ix;
|
| @@ -2593,7 +2730,7 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_p) *file_symtabs,
|
| xcalloc, xfree);
|
| cleanup = make_cleanup_htab_delete (collector.unique_syms);
|
|
|
| - for (ix = 0; VEC_iterate (symtab_p, file_symtabs, ix, elt); ++ix)
|
| + for (ix = 0; VEC_iterate (symtab_ptr, file_symtabs, ix, elt); ++ix)
|
| {
|
| if (elt == NULL)
|
| {
|
| @@ -2606,17 +2743,14 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_p) *file_symtabs,
|
| }
|
| else
|
| {
|
| - struct block *search_block;
|
| -
|
| /* Program spaces that are executing startup should have
|
| been filtered out earlier. */
|
| gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
|
| set_current_program_space (SYMTAB_PSPACE (elt));
|
| - search_block = get_search_block (elt);
|
| - LA_ITERATE_OVER_SYMBOLS (search_block, class_name, STRUCT_DOMAIN,
|
| - collect_one_symbol, &collector);
|
| - LA_ITERATE_OVER_SYMBOLS (search_block, class_name, VAR_DOMAIN,
|
| - collect_one_symbol, &collector);
|
| + iterate_over_file_blocks (elt, class_name, STRUCT_DOMAIN,
|
| + collect_one_symbol, &collector);
|
| + iterate_over_file_blocks (elt, class_name, VAR_DOMAIN,
|
| + collect_one_symbol, &collector);
|
| }
|
| }
|
|
|
| @@ -2660,8 +2794,8 @@ compare_symbols (const void *a, const void *b)
|
| static int
|
| compare_msymbols (const void *a, const void *b)
|
| {
|
| - const struct minsym_and_objfile *sa = a;
|
| - const struct minsym_and_objfile *sb = b;
|
| + const struct bound_minimal_symbol *sa = a;
|
| + const struct bound_minimal_symbol *sb = b;
|
| uintptr_t uia, uib;
|
|
|
| uia = (uintptr_t) sa->objfile->pspace;
|
| @@ -2735,10 +2869,10 @@ find_superclass_methods (VEC (typep) *superclasses,
|
| in SYMBOLS (for debug symbols) and MINSYMS (for minimal symbols). */
|
|
|
| static void
|
| -find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs,
|
| +find_method (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs,
|
| const char *class_name, const char *method_name,
|
| VEC (symbolp) *sym_classes, VEC (symbolp) **symbols,
|
| - VEC (minsym_and_objfile_d) **minsyms)
|
| + VEC (bound_minimal_symbol_d) **minsyms)
|
| {
|
| struct symbol *sym;
|
| struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
|
| @@ -2811,7 +2945,7 @@ find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs,
|
| }
|
|
|
| if (!VEC_empty (symbolp, info.result.symbols)
|
| - || !VEC_empty (minsym_and_objfile_d, info.result.minimal_symbols))
|
| + || !VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
|
| {
|
| *symbols = info.result.symbols;
|
| *minsyms = info.result.minimal_symbols;
|
| @@ -2831,7 +2965,7 @@ find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs,
|
| struct symtab_collector
|
| {
|
| /* The result vector of symtabs. */
|
| - VEC (symtab_p) *symtabs;
|
| + VEC (symtab_ptr) *symtabs;
|
|
|
| /* This is used to ensure the symtabs are unique. */
|
| htab_t symtab_table;
|
| @@ -2849,7 +2983,7 @@ add_symtabs_to_list (struct symtab *symtab, void *d)
|
| if (!*slot)
|
| {
|
| *slot = symtab;
|
| - VEC_safe_push (symtab_p, data->symtabs, symtab);
|
| + VEC_safe_push (symtab_ptr, data->symtabs, symtab);
|
| }
|
|
|
| return 0;
|
| @@ -2857,7 +2991,7 @@ add_symtabs_to_list (struct symtab *symtab, void *d)
|
|
|
| /* Given a file name, return a VEC of all matching symtabs. */
|
|
|
| -static VEC (symtab_p) *
|
| +static VEC (symtab_ptr) *
|
| collect_symtabs_from_filename (const char *file)
|
| {
|
| struct symtab_collector collector;
|
| @@ -2885,14 +3019,14 @@ collect_symtabs_from_filename (const char *file)
|
|
|
| /* Return all the symtabs associated to the FILENAME. */
|
|
|
| -static VEC (symtab_p) *
|
| +static VEC (symtab_ptr) *
|
| symtabs_from_filename (const char *filename)
|
| {
|
| - VEC (symtab_p) *result;
|
| + VEC (symtab_ptr) *result;
|
|
|
| result = collect_symtabs_from_filename (filename);
|
|
|
| - if (VEC_empty (symtab_p, result))
|
| + if (VEC_empty (symtab_ptr, result))
|
| {
|
| if (!have_full_symbols () && !have_partial_symbols ())
|
| throw_error (NOT_FOUND_ERROR,
|
| @@ -2910,9 +3044,9 @@ symtabs_from_filename (const char *filename)
|
|
|
| static void
|
| find_function_symbols (struct linespec_state *state,
|
| - VEC (symtab_p) *file_symtabs, const char *name,
|
| + VEC (symtab_ptr) *file_symtabs, const char *name,
|
| VEC (symbolp) **symbols,
|
| - VEC (minsym_and_objfile_d) **minsyms)
|
| + VEC (bound_minimal_symbol_d) **minsyms)
|
| {
|
| struct collect_info info;
|
| VEC (const_char_ptr) *symbol_names = NULL;
|
| @@ -2925,7 +3059,7 @@ find_function_symbols (struct linespec_state *state,
|
| info.file_symtabs = file_symtabs;
|
|
|
| /* Try NAME as an Objective-C selector. */
|
| - find_imps ((char *) name, &symbol_names);
|
| + find_imps (name, &symbol_names);
|
| if (!VEC_empty (const_char_ptr, symbol_names))
|
| add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
|
| else
|
| @@ -2941,9 +3075,9 @@ find_function_symbols (struct linespec_state *state,
|
| else
|
| *symbols = info.result.symbols;
|
|
|
| - if (VEC_empty (minsym_and_objfile_d, info.result.minimal_symbols))
|
| + if (VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
|
| {
|
| - VEC_free (minsym_and_objfile_d, info.result.minimal_symbols);
|
| + VEC_free (bound_minimal_symbol_d, info.result.minimal_symbols);
|
| *minsyms = NULL;
|
| }
|
| else
|
| @@ -2953,17 +3087,16 @@ find_function_symbols (struct linespec_state *state,
|
| /* Find all symbols named NAME in FILE_SYMTABS, returning debug symbols
|
| in SYMBOLS and minimal symbols in MINSYMS. */
|
|
|
| -void
|
| +static void
|
| find_linespec_symbols (struct linespec_state *state,
|
| - VEC (symtab_p) *file_symtabs,
|
| + VEC (symtab_ptr) *file_symtabs,
|
| const char *name,
|
| VEC (symbolp) **symbols,
|
| - VEC (minsym_and_objfile_d) **minsyms)
|
| + VEC (bound_minimal_symbol_d) **minsyms)
|
| {
|
| - char *klass, *method, *canon;
|
| - const char *lookup_name, *last, *p, *scope_op;
|
| struct cleanup *cleanup;
|
| - VEC (symbolp) *classes;
|
| + char *canon;
|
| + const char *lookup_name;
|
| volatile struct gdb_exception except;
|
|
|
| cleanup = demangle_for_lookup (name, state->language->la_language,
|
| @@ -2980,78 +3113,92 @@ find_linespec_symbols (struct linespec_state *state,
|
| if (canon != NULL)
|
| {
|
| lookup_name = canon;
|
| - cleanup = make_cleanup (xfree, canon);
|
| - }
|
| -
|
| - /* See if we can find a scope operator and break this symbol
|
| - name into namespaces${SCOPE_OPERATOR}class_name and method_name. */
|
| - scope_op = "::";
|
| - p = find_toplevel_string (lookup_name, scope_op);
|
| - if (p == NULL)
|
| - {
|
| - /* No C++ scope operator. Try Java. */
|
| - scope_op = ".";
|
| + make_cleanup (xfree, canon);
|
| + }
|
| +
|
| + /* It's important to not call expand_symtabs_matching unnecessarily
|
| + as it can really slow things down (by unnecessarily expanding
|
| + potentially 1000s of symtabs, which when debugging some apps can
|
| + cost 100s of seconds). Avoid this to some extent by *first* calling
|
| + find_function_symbols, and only if that doesn't find anything
|
| + *then* call find_method. This handles two important cases:
|
| + 1) break (anonymous namespace)::foo
|
| + 2) break class::method where method is in class (and not a baseclass) */
|
| +
|
| + find_function_symbols (state, file_symtabs, lookup_name,
|
| + symbols, minsyms);
|
| +
|
| + /* If we were unable to locate a symbol of the same name, try dividing
|
| + the name into class and method names and searching the class and its
|
| + baseclasses. */
|
| + if (VEC_empty (symbolp, *symbols)
|
| + && VEC_empty (bound_minimal_symbol_d, *minsyms))
|
| + {
|
| + char *klass, *method;
|
| + const char *last, *p, *scope_op;
|
| + VEC (symbolp) *classes;
|
| +
|
| + /* See if we can find a scope operator and break this symbol
|
| + name into namespaces${SCOPE_OPERATOR}class_name and method_name. */
|
| + scope_op = "::";
|
| p = find_toplevel_string (lookup_name, scope_op);
|
| - }
|
| -
|
| - last = NULL;
|
| - while (p != NULL)
|
| - {
|
| - last = p;
|
| - p = find_toplevel_string (p + strlen (scope_op), scope_op);
|
| - }
|
| -
|
| - /* If no scope operator was found, lookup the name as a symbol. */
|
| - if (last == NULL)
|
| - {
|
| - find_function_symbols (state, file_symtabs, lookup_name,
|
| - symbols, minsyms);
|
| - do_cleanups (cleanup);
|
| - return;
|
| - }
|
| -
|
| - /* NAME points to the class name.
|
| - LAST points to the method name. */
|
| - klass = xmalloc ((last - lookup_name + 1) * sizeof (char));
|
| - make_cleanup (xfree, klass);
|
| - strncpy (klass, lookup_name, last - lookup_name);
|
| - klass[last - lookup_name] = '\0';
|
| -
|
| - /* Skip past the scope operator. */
|
| - last += strlen (scope_op);
|
| - method = xmalloc ((strlen (last) + 1) * sizeof (char));
|
| - make_cleanup (xfree, method);
|
| - strcpy (method, last);
|
| + if (p == NULL)
|
| + {
|
| + /* No C++ scope operator. Try Java. */
|
| + scope_op = ".";
|
| + p = find_toplevel_string (lookup_name, scope_op);
|
| + }
|
|
|
| - /* Find a list of classes named KLASS. */
|
| - classes = lookup_prefix_sym (state, file_symtabs, klass);
|
| - make_cleanup (VEC_cleanup (symbolp), &classes);
|
| - if (!VEC_empty (symbolp, classes))
|
| - {
|
| - /* Now locate a list of suitable methods named METHOD. */
|
| - TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + last = NULL;
|
| + while (p != NULL)
|
| {
|
| - find_method (state, file_symtabs, klass, method, classes,
|
| - symbols, minsyms);
|
| + last = p;
|
| + p = find_toplevel_string (p + strlen (scope_op), scope_op);
|
| }
|
|
|
| - /* If successful, we're done. If NOT_FOUND_ERROR
|
| - was not thrown, rethrow the exception that we did get.
|
| - Otherwise, fall back to looking up the entire name as a symbol.
|
| - This can happen with namespace::function. */
|
| - if (except.reason >= 0)
|
| + /* If no scope operator was found, there is nothing more we can do;
|
| + we already attempted to lookup the entire name as a symbol
|
| + and failed. */
|
| + if (last == NULL)
|
| {
|
| do_cleanups (cleanup);
|
| return;
|
| }
|
| - else if (except.error != NOT_FOUND_ERROR)
|
| - throw_exception (except);
|
| +
|
| + /* LOOKUP_NAME points to the class name.
|
| + LAST points to the method name. */
|
| + klass = xmalloc ((last - lookup_name + 1) * sizeof (char));
|
| + make_cleanup (xfree, klass);
|
| + strncpy (klass, lookup_name, last - lookup_name);
|
| + klass[last - lookup_name] = '\0';
|
| +
|
| + /* Skip past the scope operator. */
|
| + last += strlen (scope_op);
|
| + method = xmalloc ((strlen (last) + 1) * sizeof (char));
|
| + make_cleanup (xfree, method);
|
| + strcpy (method, last);
|
| +
|
| + /* Find a list of classes named KLASS. */
|
| + classes = lookup_prefix_sym (state, file_symtabs, klass);
|
| + make_cleanup (VEC_cleanup (symbolp), &classes);
|
| +
|
| + if (!VEC_empty (symbolp, classes))
|
| + {
|
| + /* Now locate a list of suitable methods named METHOD. */
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + find_method (state, file_symtabs, klass, method, classes,
|
| + symbols, minsyms);
|
| + }
|
| +
|
| + /* If successful, we're done. If NOT_FOUND_ERROR
|
| + was not thrown, rethrow the exception that we did get. */
|
| + if (except.reason < 0 && except.error != NOT_FOUND_ERROR)
|
| + throw_exception (except);
|
| + }
|
| }
|
|
|
| - /* We couldn't find a class, so we check the entire name as a symbol
|
| - instead. */
|
| - find_function_symbols (state, file_symtabs, lookup_name, symbols, minsyms);
|
| - do_cleanups (cleanup);
|
| + do_cleanups (cleanup);
|
| }
|
|
|
| /* Return all labels named NAME in FUNCTION_SYMBOLS. Return the
|
| @@ -3071,7 +3218,7 @@ find_label_symbols (struct linespec_state *self,
|
| if (function_symbols == NULL)
|
| {
|
| set_current_program_space (self->program_space);
|
| - block = get_search_block (NULL);
|
| + block = get_current_search_block ();
|
|
|
| for (;
|
| block && !BLOCK_FUNCTION (block);
|
| @@ -3124,7 +3271,7 @@ decode_digits_list_mode (struct linespec_state *self,
|
|
|
| gdb_assert (self->list_mode);
|
|
|
| - for (ix = 0; VEC_iterate (symtab_p, ls->file_symtabs, ix, elt);
|
| + for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt);
|
| ++ix)
|
| {
|
| /* The logic above should ensure this. */
|
| @@ -3140,7 +3287,7 @@ decode_digits_list_mode (struct linespec_state *self,
|
| val.pc = 0;
|
| val.explicit_line = 1;
|
|
|
| - add_sal_to_sals (self, values, &val, NULL);
|
| + add_sal_to_sals (self, values, &val, NULL, 0);
|
| }
|
| }
|
|
|
| @@ -3157,7 +3304,7 @@ decode_digits_ordinary (struct linespec_state *self,
|
| int ix;
|
| struct symtab *elt;
|
|
|
| - for (ix = 0; VEC_iterate (symtab_p, ls->file_symtabs, ix, elt); ++ix)
|
| + for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt); ++ix)
|
| {
|
| int i;
|
| VEC (CORE_ADDR) *pcs;
|
| @@ -3272,7 +3419,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
|
|
|
| sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
|
| (struct obj_section *) 0, 0);
|
| - sal.section = SYMBOL_OBJ_SECTION (msymbol);
|
| + sal.section = SYMBOL_OBJ_SECTION (objfile, msymbol);
|
|
|
| /* The minimal symbol might point to a function descriptor;
|
| resolve it to the actual code address instead. */
|
| @@ -3284,7 +3431,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
|
| skip_prologue_sal (&sal);
|
|
|
| if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
|
| - add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol));
|
| + add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol), 0);
|
| }
|
|
|
| /* A helper struct to pass some data through
|
| @@ -3302,7 +3449,7 @@ struct collect_minsyms
|
| int list_mode;
|
|
|
| /* The resulting symbols. */
|
| - VEC (minsym_and_objfile_d) *msyms;
|
| + VEC (bound_minimal_symbol_d) *msyms;
|
| };
|
|
|
| /* A helper function to classify a minimal_symbol_type according to
|
| @@ -3334,8 +3481,8 @@ classify_mtype (enum minimal_symbol_type t)
|
| static int
|
| compare_msyms (const void *a, const void *b)
|
| {
|
| - const minsym_and_objfile_d *moa = a;
|
| - const minsym_and_objfile_d *mob = b;
|
| + const bound_minimal_symbol_d *moa = a;
|
| + const bound_minimal_symbol_d *mob = b;
|
| enum minimal_symbol_type ta = MSYMBOL_TYPE (moa->minsym);
|
| enum minimal_symbol_type tb = MSYMBOL_TYPE (mob->minsym);
|
|
|
| @@ -3349,7 +3496,7 @@ static void
|
| add_minsym (struct minimal_symbol *minsym, void *d)
|
| {
|
| struct collect_minsyms *info = d;
|
| - minsym_and_objfile_d mo;
|
| + bound_minimal_symbol_d mo;
|
|
|
| /* Exclude data symbols when looking for breakpoint locations. */
|
| if (!info->list_mode)
|
| @@ -3364,7 +3511,7 @@ add_minsym (struct minimal_symbol *minsym, void *d)
|
| {
|
| /* Make sure this minsym is not a function descriptor
|
| before we decide to discard it. */
|
| - struct gdbarch *gdbarch = info->objfile->gdbarch;
|
| + struct gdbarch *gdbarch = get_objfile_arch (info->objfile);
|
| CORE_ADDR addr = gdbarch_convert_from_func_ptr_addr
|
| (gdbarch, SYMBOL_VALUE_ADDRESS (minsym),
|
| ¤t_target);
|
| @@ -3376,7 +3523,7 @@ add_minsym (struct minimal_symbol *minsym, void *d)
|
|
|
| mo.minsym = minsym;
|
| mo.objfile = info->objfile;
|
| - VEC_safe_push (minsym_and_objfile_d, info->msyms, &mo);
|
| + VEC_safe_push (bound_minimal_symbol_d, info->msyms, &mo);
|
| }
|
|
|
| /* Search minimal symbols in all objfiles for NAME. If SEARCH_PSPACE
|
| @@ -3406,7 +3553,7 @@ search_minsyms_for_name (struct collect_info *info, const char *name,
|
| local.funfirstline = info->state->funfirstline;
|
| local.list_mode = info->state->list_mode;
|
|
|
| - cleanup = make_cleanup (VEC_cleanup (minsym_and_objfile_d),
|
| + cleanup = make_cleanup (VEC_cleanup (bound_minimal_symbol_d),
|
| &local.msyms);
|
|
|
| ALL_OBJFILES (objfile)
|
| @@ -3415,31 +3562,31 @@ search_minsyms_for_name (struct collect_info *info, const char *name,
|
| iterate_over_minimal_symbols (objfile, name, add_minsym, &local);
|
| }
|
|
|
| - if (!VEC_empty (minsym_and_objfile_d, local.msyms))
|
| + if (!VEC_empty (bound_minimal_symbol_d, local.msyms))
|
| {
|
| int classification;
|
| int ix;
|
| - minsym_and_objfile_d *item;
|
| + bound_minimal_symbol_d *item;
|
|
|
| - qsort (VEC_address (minsym_and_objfile_d, local.msyms),
|
| - VEC_length (minsym_and_objfile_d, local.msyms),
|
| - sizeof (minsym_and_objfile_d),
|
| + qsort (VEC_address (bound_minimal_symbol_d, local.msyms),
|
| + VEC_length (bound_minimal_symbol_d, local.msyms),
|
| + sizeof (bound_minimal_symbol_d),
|
| compare_msyms);
|
|
|
| /* Now the minsyms are in classification order. So, we walk
|
| over them and process just the minsyms with the same
|
| classification as the very first minsym in the list. */
|
| - item = VEC_index (minsym_and_objfile_d, local.msyms, 0);
|
| + item = VEC_index (bound_minimal_symbol_d, local.msyms, 0);
|
| classification = classify_mtype (MSYMBOL_TYPE (item->minsym));
|
|
|
| for (ix = 0;
|
| - VEC_iterate (minsym_and_objfile_d, local.msyms, ix, item);
|
| + VEC_iterate (bound_minimal_symbol_d, local.msyms, ix, item);
|
| ++ix)
|
| {
|
| if (classify_mtype (MSYMBOL_TYPE (item->minsym)) != classification)
|
| break;
|
|
|
| - VEC_safe_push (minsym_and_objfile_d,
|
| + VEC_safe_push (bound_minimal_symbol_d,
|
| info->result.minimal_symbols, item);
|
| }
|
| }
|
| @@ -3460,7 +3607,7 @@ add_matching_symbols_to_info (const char *name,
|
| int ix;
|
| struct symtab *elt;
|
|
|
| - for (ix = 0; VEC_iterate (symtab_p, info->file_symtabs, ix, elt); ++ix)
|
| + for (ix = 0; VEC_iterate (symtab_ptr, info->file_symtabs, ix, elt); ++ix)
|
| {
|
| if (elt == NULL)
|
| {
|
| @@ -3475,9 +3622,8 @@ add_matching_symbols_to_info (const char *name,
|
| been filtered out earlier. */
|
| gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
|
| set_current_program_space (SYMTAB_PSPACE (elt));
|
| - LA_ITERATE_OVER_SYMBOLS (get_search_block (elt), name,
|
| - VAR_DOMAIN, collect_symbols,
|
| - info);
|
| + iterate_over_file_blocks (elt, name, VAR_DOMAIN,
|
| + collect_symbols, info);
|
| }
|
| }
|
| }
|
|
|