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); |
} |
} |
} |