X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Flinespec.c;h=9468f265a14adb50840a49cd588e7d3d7ca8f4ce;hb=403cb6b138c38faf72f7abc034db3505b9bdb82f;hp=7cbf1bf5746af27bf60a61f8bf59f67f010d19aa;hpb=001822aa58d2998ecc11067c07863745630ad388;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linespec.c b/gdb/linespec.c index 7cbf1bf574..9468f265a1 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. @@ -43,9 +43,7 @@ #include "cli/cli-utils.h" #include "filenames.h" #include "ada-lang.h" - -typedef struct symtab *symtab_p; -DEF_VEC_P (symtab_p); +#include "stack.h" typedef struct symbol *symbolp; DEF_VEC_P (symbolp); @@ -63,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 @@ -109,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; @@ -117,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 @@ -156,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. */ @@ -185,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. */ @@ -201,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; }; @@ -272,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. */ @@ -285,6 +291,11 @@ struct ls_parser /* Is the entire linespec quote-enclosed? */ int is_quote_enclosed; + /* Is a keyword syntactically valid at this point? + In, e.g., "break thread thread 1", the leading "keyword" must not + be interpreted as such. */ + int keyword_ok; + /* The state of the parse. */ struct linespec_state state; #define PARSER_STATE(PPTR) (&(PPTR)->state) @@ -297,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, @@ -334,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, @@ -365,31 +381,42 @@ static const char *const linespec_quote_characters = "\"\'"; /* Lexer functions. */ /* Lex a number from the input in PARSER. This only supports - decimal numbers. */ + decimal numbers. -static linespec_token -linespec_lexer_lex_number (linespec_parser *parser) -{ - linespec_token token; + Return true if input is decimal numbers. Return false if not. */ - token.type = LSTOKEN_NUMBER; - LS_TOKEN_STOKEN (token).length = 0; - LS_TOKEN_STOKEN (token).ptr = PARSER_STREAM (parser); +static int +linespec_lexer_lex_number (linespec_parser *parser, linespec_token *tokenp) +{ + tokenp->type = LSTOKEN_NUMBER; + LS_TOKEN_STOKEN (*tokenp).length = 0; + LS_TOKEN_STOKEN (*tokenp).ptr = PARSER_STREAM (parser); /* Keep any sign at the start of the stream. */ if (*PARSER_STREAM (parser) == '+' || *PARSER_STREAM (parser) == '-') { - ++LS_TOKEN_STOKEN (token).length; + ++LS_TOKEN_STOKEN (*tokenp).length; ++(PARSER_STREAM (parser)); } while (isdigit (*PARSER_STREAM (parser))) { - ++LS_TOKEN_STOKEN (token).length; + ++LS_TOKEN_STOKEN (*tokenp).length; ++(PARSER_STREAM (parser)); } - return token; + /* If the next character in the input buffer is not a space, comma, + 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) != ':' + && !strchr (linespec_quote_characters, *PARSER_STREAM (parser))) + { + PARSER_STREAM (parser) = LS_TOKEN_STOKEN (*tokenp).ptr; + return 0; + } + + return 1; } /* Does P represent one of the keywords? If so, return @@ -488,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 == '(') @@ -530,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; @@ -580,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, @@ -594,7 +621,11 @@ 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, + say, a function name. */ if (linespec_lexer_lex_keyword (p) != NULL) { LS_TOKEN_STOKEN (token).ptr = start; @@ -650,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) @@ -702,10 +733,12 @@ 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. */ - keyword = linespec_lexer_lex_keyword (PARSER_STREAM (parser)); + /* Check for a keyword, they end the linespec. */ + keyword = NULL; + if (parser->keyword_ok) + keyword = linespec_lexer_lex_keyword (PARSER_STREAM (parser)); if (keyword != NULL) { parser->lexer.current.type = LSTOKEN_KEYWORD; @@ -723,7 +756,8 @@ linespec_lexer_lex_one (linespec_parser *parser) case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - parser->lexer.current = linespec_lexer_lex_number (parser); + if (!linespec_lexer_lex_number (parser, &(parser->lexer.current))) + parser->lexer.current = linespec_lexer_lex_string (parser); break; case ':': @@ -785,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); @@ -809,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; } } @@ -987,27 +1032,22 @@ iterate_over_all_matching_symtabs (struct linespec_state *state, ALL_DOMAIN, &matcher_data); - ALL_OBJFILE_SYMTABS (objfile, symtab) + ALL_OBJFILE_PRIMARY_SYMTABS (objfile, symtab) { - if (symtab->primary) + 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; - block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); - LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data); - - if (include_inline) + for (i = FIRST_LOCAL_BLOCK; + i < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (symtab)); i++) { - struct symbol_and_data_callback cad = { callback, data }; - 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); - } + block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), i); + state->language->la_iterate_over_symbols + (block, name, domain, iterate_inline_only, &cad); } } } @@ -1015,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. */ @@ -1048,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); @@ -1058,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); @@ -1175,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. */ @@ -1195,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) @@ -1222,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 @@ -1232,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), &item_names); - make_cleanup (VEC_cleanup (const_char_ptr), &filters); - for (i = 0; i < result->nelts; ++i) + old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &filters); + + /* 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; + + canonical = &self->canonical_names[i]; + gdb_assert (canonical->suffix != NULL); + item = &items[i]; + + item->fullform = canonical_to_fullform (canonical); + make_cleanup (xfree, item->fullform); - gdb_assert (self->canonical_names[i] != NULL); - for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j) + 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; } - if (select_mode == multiple_symbols_cancel - && VEC_length (const_char_ptr, item_names) > 1) + /* 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 && 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) @@ -1318,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); } } } @@ -1349,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 = ""; @@ -1422,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}; @@ -1450,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. */ @@ -1509,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) @@ -1520,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 @@ -1697,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; } @@ -1811,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); @@ -1839,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) { @@ -1856,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) { - symbol_to_sal (&sal, state->funfirstline, sym); - add_sal_to_sals (state, &sals, &sal, - SYMBOL_NATURAL_NAME (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), 0); } } else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL) @@ -1867,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) @@ -1882,21 +2034,23 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls) { pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); set_current_program_space (pspace); - symbol_to_sal (&sal, state->funfirstline, sym); - if (maybe_add_address (state->addr_set, pspace, sal.pc)) - add_sal_to_sals (state, &sals, &sal, SYMBOL_NATURAL_NAME (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), 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; @@ -1912,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 { @@ -1982,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; @@ -2008,6 +2170,10 @@ parse_linespec (linespec_parser *parser, char **argptr) } } + /* A keyword at the start cannot be interpreted as such. + Consider "b thread thread 42". */ + parser->keyword_ok = 0; + parser->lexer.saved_arg = *argptr; parser->lexer.stream = argptr; file_exception.reason = 0; @@ -2029,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); @@ -2057,31 +2224,31 @@ 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); + /* Now we can recognize keywords. */ + parser->keyword_ok = 1; + /* Shortcut: If the next token is not LSTOKEN_COLON, we know that this token cannot represent a filename. */ token = linespec_lexer_peek_token (parser); @@ -2118,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. */ @@ -2133,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. */ @@ -2222,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); @@ -2260,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'. */ @@ -2279,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); } } @@ -2328,6 +2489,8 @@ decode_line_full (char **argptr, int flags, do_cleanups (cleanups); } +/* See linespec.h. */ + struct symtabs_and_lines decode_line_1 (char **argptr, int flags, struct symtab *default_symtab, @@ -2336,18 +2499,66 @@ 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; } +/* See linespec.h. */ + +struct symtabs_and_lines +decode_line_with_current_source (char *string, int flags) +{ + struct symtabs_and_lines sals; + struct symtab_and_line cursal; + + if (string == 0) + error (_("Empty line specification.")); + + /* We use whatever is set as the current source line. We do not try + and get a default source symtab+line or it will recursively call us! */ + cursal = get_current_source_symtab_and_line (); + + sals = decode_line_1 (&string, flags, + cursal.symtab, cursal.line); + + if (*string) + error (_("Junk at end of line specification: %s"), string); + return sals; +} + +/* See linespec.h. */ + +struct symtabs_and_lines +decode_line_with_last_displayed (char *string, int flags) +{ + struct symtabs_and_lines sals; + + if (string == 0) + error (_("Empty line specification.")); + + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&string, flags, + get_last_displayed_symtab (), + get_last_displayed_line ()); + else + sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0); + + if (*string) + error (_("Junk at end of line specification: %s"), string); + return sals; +} + /* First, some functions to initialize stuff at the beggining of the @@ -2375,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 @@ -2397,18 +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); + 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; @@ -2424,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; @@ -2432,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); @@ -2500,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; @@ -2517,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) { @@ -2530,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); } } @@ -2584,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; @@ -2659,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); @@ -2671,7 +2881,6 @@ find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs, VEC (typep) *superclass_vec; VEC (const_char_ptr) *result_names; struct collect_info info; - char *name_iter; /* Sort symbols so that symbols with the same program space are next to each other. */ @@ -2736,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; @@ -2756,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; @@ -2774,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; @@ -2782,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; @@ -2810,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, @@ -2835,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; @@ -2850,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 @@ -2866,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 @@ -2878,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, @@ -2905,77 +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); - 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 @@ -2995,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); @@ -3048,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. */ @@ -3064,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); } } @@ -3081,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; @@ -3196,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. */ @@ -3208,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 @@ -3226,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 @@ -3258,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); @@ -3273,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) @@ -3288,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); @@ -3300,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 @@ -3330,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) @@ -3339,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); } } @@ -3384,10 +3607,8 @@ 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) { - struct symbol *sym; - if (elt == NULL) { iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN, @@ -3401,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); } } }