/* Parser for linespec for the GNU debugger, GDB.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "block.h"
#include "objc-lang.h"
#include "linespec.h"
-#include "exceptions.h"
#include "language.h"
#include "interps.h"
#include "mi/mi-cmds.h"
#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);
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
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. */
/* 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. */
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;
};
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. */
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,
const char *name);
static void find_linespec_symbols (struct linespec_state *self,
- 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);
static struct line_offset
linespec_parse_variable (struct linespec_state *self,
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,
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 == '(')
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;
}
else
{
- char *p;
+ const char *p;
/* Otherwise, only identifier characters are permitted.
Spaces are the exception. In general, we keep spaces,
{
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,
else if (*PARSER_STREAM (parser) == '<'
|| *PARSER_STREAM (parser) == '(')
{
- char *p;
+ const char *p;
p = find_parameter_list_end (PARSER_STREAM (parser));
if (p != NULL)
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;
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);
if (symname != NULL)
canonical->suffix = xstrdup (symname);
else
- canonical->suffix = NULL;
+ canonical->suffix = xstrdup ("<unknown>");
canonical->symtab = NULL;
}
}
/* Returns the block to be used for symbol searches from
the current location. */
-static struct block *
-get_current_search_block ()
+static const struct block *
+get_current_search_block (void)
{
- struct block *block;
+ const struct block *block;
enum language save_language;
/* get_selected_block can change the current language when there is
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. */
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)
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;
+ }
+
+ /* The convenience variable/history value parsed correctly.
+ NAME is no longer needed. */
+ do_cleanups (cleanup);
+ }
else
{
/* The name is also not a label. Abort parsing. Do not throw
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_default_source_symtab_and_line ();
initialize_defaults (&self->default_symtab, &self->default_line);
fullname = symtab_to_fullname (self->default_symtab);
- VEC_pop (symtab_p, ls->file_symtabs);
- VEC_free (symtab_p, ls->file_symtabs);
+ 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;
}
{
struct linetable_entry *best_entry = NULL;
int *filter;
- struct block **blocks;
+ const struct block **blocks;
struct cleanup *cleanup;
struct symtabs_and_lines intermediate_results;
int i, j;
filter = XNEWVEC (int, intermediate_results.nelts);
make_cleanup (xfree, filter);
- blocks = XNEWVEC (struct block *, intermediate_results.nelts);
+ blocks = XNEWVEC (const struct block *, intermediate_results.nelts);
make_cleanup (xfree, blocks);
for (i = 0; i < intermediate_results.nelts; ++i)
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), 0);
}
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)
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;
{
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);
}
}
/* 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;
/* 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);
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);
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. */
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. */
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);
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'. */
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);
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;
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
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;
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;
/* 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;
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)
{
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;
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);
}
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;
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;
if (!*slot)
{
*slot = symtab;
- VEC_safe_push (symtab_p, data->symtabs, symtab);
+ VEC_safe_push (symtab_ptr, data->symtabs, symtab);
}
return 0;
/* 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;
/* 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,
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;
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
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
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,
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
VEC (symbolp) **label_funcs_ret, const char *name)
{
int ix;
- struct block *block;
+ const struct block *block;
struct symbol *sym;
struct symbol *fn_sym;
VEC (symbolp) *result = NULL;
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. */
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;
CORE_ADDR pc;
struct symtab_and_line sal;
- sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
+ sal = find_pc_sect_line (MSYMBOL_VALUE_ADDRESS (objfile, msymbol),
(struct obj_section *) 0, 0);
- sal.section = SYMBOL_OBJ_SECTION (msymbol);
+ sal.section = MSYMBOL_OBJ_SECTION (objfile, msymbol);
/* The minimal symbol might point to a function descriptor;
resolve it to the actual code address instead. */
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), 0);
+ add_sal_to_sals (self, result, &sal, MSYMBOL_NATURAL_NAME (msymbol), 0);
}
/* A helper struct to pass some data through
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
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);
add_minsym (struct minimal_symbol *minsym, void *d)
{
struct collect_minsyms *info = d;
- minsym_and_objfile_d mo;
+ bound_minimal_symbol_d mo;
+
+ mo.minsym = minsym;
+ mo.objfile = info->objfile;
/* Exclude data symbols when looking for breakpoint locations. */
if (!info->list_mode)
{
/* 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),
+ (gdbarch, BMSYMBOL_VALUE_ADDRESS (mo),
¤t_target);
- if (addr == SYMBOL_VALUE_ADDRESS (minsym))
+ if (addr == BMSYMBOL_VALUE_ADDRESS (mo))
return;
}
}
- 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
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)
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);
}
}
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)
{