/* Parser for linespec for the GNU debugger, GDB.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2016 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 "filenames.h"
#include "ada-lang.h"
#include "stack.h"
+#include "location.h"
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
DEF_VEC_O (bound_minimal_symbol_d);
-/* An enumeration of possible signs for a line offset. */
-enum offset_relative_sign
-{
- /* No sign */
- LINE_OFFSET_NONE,
-
- /* A plus sign ("+") */
- LINE_OFFSET_PLUS,
-
- /* A minus sign ("-") */
- LINE_OFFSET_MINUS,
-
- /* A special "sign" for unspecified offset. */
- LINE_OFFSET_UNKNOWN
-};
-
-/* A line offset in a linespec. */
-
-struct line_offset
-{
- /* Line offset and any specified sign. */
- int offset;
- enum offset_relative_sign sign;
-};
-
/* A linespec. Elements of this structure are filled in by a parser
(either parse_linespec or some other function). The structure is
then converted into SALs by convert_linespec_to_sals. */
struct linespec
{
- /* An expression and the resulting PC. Specifying an expression
- currently precludes the use of other members. */
-
- /* The expression entered by the user. */
- const char *expression;
-
- /* The resulting PC expression derived from evaluating EXPRESSION. */
- CORE_ADDR expr_pc;
-
- /* Any specified file symtabs. */
-
- /* The user-supplied source filename or NULL if none was specified. */
- const char *source_filename;
+ /* An explicit location describing the SaLs. */
+ struct explicit_location explicit_loc;
/* 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. */
+ be NULL. If explicit.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_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. */
- 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 (bound_minimal_symbol_d) *minimal_symbols;
- /* The name of a label and matching symbols. */
-
- /* The user-specified 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
or both must be non-NULL. */
VEC (symbolp) *label_symbols;
VEC (symbolp) *function_symbols;
} labels;
-
- /* Line offset. It may be LINE_OFFSET_UNKNOWN, meaning that no
- offset was specified. */
- struct line_offset line_offset;
};
typedef struct linespec *linespec_p;
/* The program space as seen when the module was entered. */
struct program_space *program_space;
+ /* If not NULL, the search is restricted to just this program
+ space. */
+ struct program_space *search_pspace;
+
/* The default symtab to use, if no other symtab is specified. */
struct symtab *default_symtab;
/* This is a set of address_entry objects which is used to prevent
duplicate symbols from being entered into the result. */
htab_t addr_set;
+
+ /* Are we building a linespec? */
+ int is_linespec;
};
/* This is a helper object that is used when collecting symbols into a
/* List of keywords */
static const char * const linespec_keywords[] = { "if", "thread", "task" };
+#define IF_KEYWORD_INDEX 0
/* A token of the linespec lexer */
const char *saved_arg;
/* Head of the input stream. */
- const char **stream;
-#define PARSER_STREAM(P) (*(P)->lexer.stream)
+ const char *stream;
+#define PARSER_STREAM(P) ((P)->lexer.stream)
/* The current token. */
linespec_token current;
/* 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)
};
typedef struct ls_parser linespec_parser;
+/* A convenience macro for accessing the explicit location result of
+ the parser. */
+#define PARSER_EXPLICIT(PPTR) (&PARSER_RESULT ((PPTR))->explicit_loc)
+
/* Prototypes for local functions. */
static void iterate_over_file_blocks (struct symtab *symtab,
static void initialize_defaults (struct symtab **default_symtab,
int *default_line);
-static CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
+CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
static struct symtabs_and_lines decode_objc (struct linespec_state *self,
linespec_p ls,
- const char **argptr);
+ const char *arg);
-static VEC (symtab_ptr) *symtabs_from_filename (const char *);
+static VEC (symtab_ptr) *symtabs_from_filename (const char *,
+ struct program_space *pspace);
static VEC (symbolp) *find_label_symbols (struct linespec_state *self,
VEC (symbolp) *function_symbols,
struct program_space *pspace,
VEC (const_char_ptr) *names);
-static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file);
+static VEC (symtab_ptr) *
+ collect_symtabs_from_filename (const char *file,
+ struct program_space *pspace);
static void decode_digits_ordinary (struct linespec_state *self,
linespec_p ls,
static int compare_msymbols (const void *a, const void *b);
-static const char *find_toplevel_char (const char *s, char c);
-
/* Permitted quote characters for the parser. This is different from the
completer's quote characters to allow backward compatibility with the
previous parser. */
return 1;
}
-/* Does P represent one of the keywords? If so, return
- the keyword. If not, return NULL. */
+/* See linespec.h. */
-static const char *
+const char *
linespec_lexer_lex_keyword (const char *p)
{
int i;
int len = strlen (linespec_keywords[i]);
/* If P begins with one of the keywords and the next
- character is not a valid identifier character,
- we have found a keyword. */
+ character is whitespace, we may have found a keyword.
+ It is only a keyword if it is not followed by another
+ keyword. */
if (strncmp (p, linespec_keywords[i], len) == 0
- && !(isalnum (p[len]) || p[len] == '_'))
- return linespec_keywords[i];
+ && isspace (p[len]))
+ {
+ int j;
+
+ /* Special case: "if" ALWAYS stops the lexer, since it
+ is not possible to predict what is going to appear in
+ the condition, which can only be parsed after SaLs have
+ been found. */
+ if (i != IF_KEYWORD_INDEX)
+ {
+ p += len;
+ p = skip_spaces_const (p);
+ for (j = 0; j < ARRAY_SIZE (linespec_keywords); ++j)
+ {
+ int nextlen = strlen (linespec_keywords[j]);
+
+ if (strncmp (p, linespec_keywords[j], nextlen) == 0
+ && isspace (p[nextlen]))
+ return NULL;
+ }
+ }
+
+ return linespec_keywords[i];
+ }
}
}
return NULL;
}
-/* Does STRING represent an Ada operator? If so, return the length
- of the decoded operator name. If not, return 0. */
+/* See description in linespec.h. */
-static int
+int
is_ada_operator (const char *string)
{
const struct ada_opname_map *mapping;
for (mapping = ada_opname_table;
mapping->encoded != NULL
- && strncmp (mapping->decoded, string,
- strlen (mapping->decoded)) != 0; ++mapping)
+ && !startswith (string, mapping->decoded); ++mapping)
;
return mapping->decoded == NULL ? 0 : strlen (mapping->decoded);
&& (PARSER_STREAM (parser) - start) > 8
/* strlen ("operator") */)
{
- char *p = strstr (start, "operator");
+ const char *p = strstr (start, "operator");
if (p != NULL && is_operator_name (p))
{
PARSER_STREAM (parser) = skip_spaces_const (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));
+ keyword = linespec_lexer_lex_keyword (PARSER_STREAM (parser));
if (keyword != NULL)
{
parser->lexer.current.type = LSTOKEN_KEYWORD;
LS_TOKEN_KEYWORD (parser->lexer.current) = keyword;
+ /* We do not advance the stream here intentionally:
+ we would like lexing to stop when a keyword is seen.
+
+ PARSER_STREAM (parser) += strlen (keyword); */
+
return parser->lexer.current;
}
struct symtab_and_line *sal)
{
++sals->nelts;
- sals->sals = xrealloc (sals->sals, sals->nelts * sizeof (sals->sals[0]));
+ sals->sals = XRESIZEVEC (struct symtab_and_line, sals->sals, sals->nelts);
sals->sals[sals->nelts - 1] = *sal;
}
{
struct linespec_canonical_name *canonical;
- self->canonical_names = xrealloc (self->canonical_names,
- (sals->nelts
- * sizeof (*self->canonical_names)));
+ self->canonical_names = XRESIZEVEC (struct linespec_canonical_name,
+ self->canonical_names, sals->nelts);
canonical = &self->canonical_names[sals->nelts - 1];
if (!literal_canonical && sal->symtab)
{
- const char *fullname = symtab_to_fullname (sal->symtab);
+ 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
static hashval_t
hash_address_entry (const void *p)
{
- const struct address_entry *aep = p;
+ const struct address_entry *aep = (const struct address_entry *) p;
hashval_t hash;
hash = iterative_hash_object (aep->pspace, 0);
static int
eq_address_entry (const void *a, const void *b)
{
- const struct address_entry *aea = a;
- const struct address_entry *aeb = b;
+ const struct address_entry *aea = (const struct address_entry *) a;
+ const struct address_entry *aeb = (const struct address_entry *) b;
return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
}
{
if (SYMBOL_INLINED (sym))
{
- struct symbol_and_data_callback *cad = d;
+ struct symbol_and_data_callback *cad
+ = (struct symbol_and_data_callback *) d;
return cad->callback (sym, cad->data);
}
static int
iterate_name_matcher (const char *name, void *d)
{
- const struct symbol_matcher_data *data = d;
+ const struct symbol_matcher_data *data
+ = (const struct symbol_matcher_data *) d;
if (data->symbol_name_cmp (name, data->lookup_name) == 0)
return 1; /* Expand this symbol's symbol table. */
ALL_OBJFILES (objfile)
{
- struct symtab *symtab;
+ struct compunit_symtab *cu;
if (objfile->sf)
objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
iterate_name_matcher,
- ALL_DOMAIN,
+ NULL, ALL_DOMAIN,
&matcher_data);
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, symtab)
+ ALL_OBJFILE_COMPUNITS (objfile, cu)
{
+ struct symtab *symtab = COMPUNIT_FILETABS (cu);
+
iterate_over_file_blocks (symtab, name, domain, callback, data);
if (include_inline)
int i;
for (i = FIRST_LOCAL_BLOCK;
- i < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (symtab)); i++)
+ i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab));
+ i++)
{
- block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), i);
+ block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
state->language->la_iterate_over_symbols
(block, name, domain, iterate_inline_only, &cad);
}
{
struct block *block;
- for (block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ for (block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
block != NULL;
block = BLOCK_SUPERBLOCK (block))
LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
{
int method_counter;
- CHECK_TYPEDEF (t);
+ t = check_typedef (t);
/* Loop over each method name. At this level, all overloads of a name
are counted as a single name. There is an inner loop which loops over
const char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
char dem_opname[64];
- if (strncmp (method_name, "__", 2) == 0 ||
- strncmp (method_name, "op", 2) == 0 ||
- strncmp (method_name, "type", 4) == 0)
+ if (startswith (method_name, "__") ||
+ startswith (method_name, "op") ||
+ startswith (method_name, "type"))
{
if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
method_name = dem_opname;
strings. Also, ignore the char within a template name, like a ','
within foo<int, int>. */
-static const char *
+const char *
find_toplevel_char (const char *s, char c)
{
int quoted = 0; /* zero if we're not in quotes;
if (s != NULL)
{
/* Found first char in HAYSTACK; check rest of string. */
- if (strncmp (s, needle, strlen (needle)) == 0)
+ if (startswith (s, needle))
return s;
/* Didn't find it; loop over HAYSTACK, looking for the next
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;
+ const struct decode_line_2_item *a = (const struct decode_line_2_item *) ap;
+ const struct decode_line_2_item *b = (const struct decode_line_2_item *) bp;
int retval;
retval = strcmp (a->displayform, b->displayform);
/* Prepare ITEMS array. */
items_count = result->nelts;
- items = xmalloc (sizeof (*items) * items_count);
+ items = XNEWVEC (struct decode_line_2_item, items_count);
make_cleanup (xfree, items);
for (i = 0; i < items_count; ++i)
{
|| token.type == LSTOKEN_KEYWORD)
{
char *string;
- struct cleanup *cleanup;
string = copy_token_string (token);
- cleanup = make_cleanup (xfree, string);
+ make_cleanup (xfree, string);
throw_error (GENERIC_ERROR,
_("malformed linespec error: unexpected %s, \"%s\""),
token_type_strings[token.type], string);
token_type_strings[token.type]);
}
-/* Parse and return a line offset in STRING. */
+/* Throw an undefined label error. */
-static struct line_offset
+static void ATTRIBUTE_NORETURN
+undefined_label_error (const char *function, const char *label)
+{
+ if (function != NULL)
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in function \"%s\"."),
+ label, function);
+ else
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in current function."),
+ label);
+}
+
+/* Throw a source file not found error. */
+
+static void ATTRIBUTE_NORETURN
+source_file_not_found_error (const char *name)
+{
+ throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
+}
+
+/* See description in linespec.h. */
+
+struct line_offset
linespec_parse_line_offset (const char *string)
{
+ const char *start = string;
struct line_offset line_offset = {0, LINE_OFFSET_NONE};
if (*string == '+')
++string;
}
+ if (*string != '\0' && !isdigit (*string))
+ error (_("malformed line offset: \"%s\""), start);
+
/* Right now, we only allow base 10 for offsets. */
line_offset.offset = atoi (string);
return line_offset;
/* Record the line offset and get the next token. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name);
+ PARSER_EXPLICIT (parser)->line_offset = linespec_parse_line_offset (name);
do_cleanups (cleanup);
/* Get the next token. */
{
PARSER_RESULT (parser)->function_symbols = symbols;
PARSER_RESULT (parser)->minimal_symbols = minimal_symbols;
- PARSER_RESULT (parser)->function_name = name;
+ PARSER_EXPLICIT (parser)->function_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
{
PARSER_RESULT (parser)->labels.label_symbols = labels;
PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
+ PARSER_EXPLICIT (parser)->label_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
&& *LS_TOKEN_STOKEN (token).ptr == '$')
{
/* User specified a convenience variable or history value. */
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_variable (PARSER_STATE (parser), name);
- if (PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
+ if (PARSER_EXPLICIT (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;
+ PARSER_EXPLICIT (parser)->function_name = name;
discard_cleanups (cleanup);
return;
}
an error here. parse_linespec will do it for us. */
/* Save a copy of the name we were trying to lookup. */
- PARSER_RESULT (parser)->function_name = name;
+ PARSER_EXPLICIT (parser)->function_name = name;
discard_cleanups (cleanup);
return;
}
get the next token. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_line_offset (name);
do_cleanups (cleanup);
{
PARSER_RESULT (parser)->labels.label_symbols = labels;
PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
+ PARSER_EXPLICIT (parser)->label_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
else
{
/* We don't know what it was, but it isn't a label. */
- throw_error (NOT_FOUND_ERROR,
- _("No label \"%s\" defined in function \"%s\"."),
- name, PARSER_RESULT (parser)->function_name);
+ undefined_label_error (PARSER_EXPLICIT (parser)->function_name,
+ name);
}
/* Check for a line offset. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_line_offset (name);
do_cleanups (cleanup);
}
/* Canonicalize the linespec contained in LS. The result is saved into
- STATE->canonical. */
+ STATE->canonical. This function handles both linespec and explicit
+ locations. */
static void
-canonicalize_linespec (struct linespec_state *state, linespec_p ls)
+canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
{
+ struct event_location *canon;
+ struct explicit_location *explicit_loc;
+
/* If canonicalization was not requested, no need to do anything. */
if (!state->canonical)
return;
- /* Shortcut expressions, which can only appear by themselves. */
- if (ls->expression != NULL)
- state->canonical->addr_string = xstrdup (ls->expression);
- else
- {
- struct ui_file *buf;
- int need_colon = 0;
-
- buf = mem_fileopen ();
- if (ls->source_filename)
- {
- fputs_unfiltered (ls->source_filename, buf);
- need_colon = 1;
- }
+ /* Save everything as an explicit location. */
+ canon = state->canonical->location
+ = new_explicit_location (&ls->explicit_loc);
+ explicit_loc = get_explicit_location (canon);
- if (ls->function_name)
- {
- if (need_colon)
- fputc_unfiltered (':', buf);
- fputs_unfiltered (ls->function_name, buf);
- need_colon = 1;
- }
+ if (explicit_loc->label_name != NULL)
+ {
+ state->canonical->special_display = 1;
- if (ls->label_name)
+ if (explicit_loc->function_name == NULL)
{
- if (need_colon)
- fputc_unfiltered (':', buf);
-
- if (ls->function_name == NULL)
- {
- struct symbol *s;
-
- /* No function was specified, so add the symbol name. */
- gdb_assert (ls->labels.function_symbols != NULL
- && (VEC_length (symbolp, ls->labels.function_symbols)
- == 1));
- s = VEC_index (symbolp, ls->labels.function_symbols, 0);
- fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
- fputc_unfiltered (':', buf);
- }
-
- fputs_unfiltered (ls->label_name, buf);
- need_colon = 1;
- state->canonical->special_display = 1;
+ struct symbol *s;
+
+ /* No function was specified, so add the symbol name. */
+ gdb_assert (ls->labels.function_symbols != NULL
+ && (VEC_length (symbolp, ls->labels.function_symbols)
+ == 1));
+ s = VEC_index (symbolp, ls->labels.function_symbols, 0);
+ explicit_loc->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
}
+ }
- if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
- {
- if (need_colon)
- fputc_unfiltered (':', buf);
- fprintf_filtered (buf, "%s%d",
- (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
- : (ls->line_offset.sign
- == LINE_OFFSET_PLUS ? "+" : "-")),
- ls->line_offset.offset);
- }
+ /* If this location originally came from a linespec, save a string
+ representation of it for display and saving to file. */
+ if (state->is_linespec)
+ {
+ char *linespec = explicit_location_to_linespec (explicit_loc);
- state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
- ui_file_delete (buf);
+ set_event_location_string (canon, linespec);
+ xfree (linespec);
}
}
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);
+ ls->file_symtabs = collect_symtabs_from_filename (fullname,
+ self->search_pspace);
use_default = 1;
}
- val.line = ls->line_offset.offset;
- switch (ls->line_offset.sign)
+ val.line = ls->explicit_loc.line_offset.offset;
+ switch (ls->explicit_loc.line_offset.sign)
{
case LINE_OFFSET_PLUS:
- if (ls->line_offset.offset == 0)
+ if (ls->explicit_loc.line_offset.offset == 0)
val.line = 5;
if (use_default)
val.line = self->default_line + val.line;
break;
case LINE_OFFSET_MINUS:
- if (ls->line_offset.offset == 0)
+ if (ls->explicit_loc.line_offset.offset == 0)
val.line = 15;
if (use_default)
val.line = self->default_line - val.line;
if (values.nelts == 0)
{
- if (ls->source_filename)
+ if (ls->explicit_loc.source_filename)
throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
- val.line, ls->source_filename);
+ val.line, ls->explicit_loc.source_filename);
else
throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
val.line);
return values;
}
+/* Convert the given ADDRESS into SaLs. */
+
+static struct symtabs_and_lines
+convert_address_location_to_sals (struct linespec_state *self,
+ CORE_ADDR address)
+{
+ struct symtab_and_line sal;
+ struct symtabs_and_lines sals = {NULL, 0};
+
+ sal = find_pc_line (address, 0);
+ sal.pc = address;
+ sal.section = find_pc_overlay (address);
+ sal.explicit_pc = 1;
+ add_sal_to_sals (self, &sals, &sal, core_addr_to_string (address), 1);
+
+ return sals;
+}
+
/* Create and return SALs from the linespec LS. */
static struct symtabs_and_lines
{
struct symtabs_and_lines sals = {NULL, 0};
- if (ls->expression != NULL)
- {
- struct symtab_and_line sal;
-
- /* We have an expression. No other attribute is allowed. */
- 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)
+ if (ls->labels.label_symbols != NULL)
{
/* We have just a bunch of functions/methods or labels. */
int i;
for (i = 0; VEC_iterate (symbolp, ls->labels.label_symbols, i, sym); ++i)
{
- struct program_space *pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (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))
for (i = 0; VEC_iterate (symbolp, ls->function_symbols, i, sym); ++i)
{
- pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ pspace = SYMTAB_PSPACE (symbol_symtab (sym));
set_current_program_space (pspace);
if (symbol_to_sal (&sal, state->funfirstline, sym)
&& maybe_add_address (state->addr_set, pspace, sal.pc))
}
}
}
- else if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ else if (ls->explicit_loc.line_offset.sign != LINE_OFFSET_UNKNOWN)
{
/* Only an offset was specified. */
sals = create_sals_line_offset (state, ls);
/* Make sure we have a filename for canonicalization. */
- if (ls->source_filename == NULL)
+ if (ls->explicit_loc.source_filename == NULL)
{
const char *fullname = symtab_to_fullname (state->default_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);
+ ls->explicit_loc.source_filename = xstrdup (fullname);
}
}
else
return sals;
}
+/* Convert the explicit location EXPLICIT_LOC into SaLs. */
+
+static struct symtabs_and_lines
+convert_explicit_location_to_sals (struct linespec_state *self,
+ linespec_p result,
+ const struct explicit_location *explicit_loc)
+{
+ VEC (symbolp) *symbols, *labels;
+ VEC (bound_minimal_symbol_d) *minimal_symbols;
+
+ if (explicit_loc->source_filename != NULL)
+ {
+ TRY
+ {
+ result->file_symtabs
+ = symtabs_from_filename (explicit_loc->source_filename,
+ self->search_pspace);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ source_file_not_found_error (explicit_loc->source_filename);
+ }
+ END_CATCH
+ result->explicit_loc.source_filename
+ = xstrdup (explicit_loc->source_filename);
+ }
+ else
+ {
+ /* A NULL entry means to use the default symtab. */
+ VEC_safe_push (symtab_ptr, result->file_symtabs, NULL);
+ }
+
+ if (explicit_loc->function_name != NULL)
+ {
+ find_linespec_symbols (self, result->file_symtabs,
+ explicit_loc->function_name, &symbols,
+ &minimal_symbols);
+
+ if (symbols == NULL && minimal_symbols == NULL)
+ symbol_not_found_error (explicit_loc->function_name,
+ result->explicit_loc.source_filename);
+
+ result->explicit_loc.function_name
+ = xstrdup (explicit_loc->function_name);
+ result->function_symbols = symbols;
+ result->minimal_symbols = minimal_symbols;
+ }
+
+ if (explicit_loc->label_name != NULL)
+ {
+ symbols = NULL;
+ labels = find_label_symbols (self, result->function_symbols,
+ &symbols, explicit_loc->label_name);
+
+ if (labels == NULL)
+ undefined_label_error (result->explicit_loc.function_name,
+ explicit_loc->label_name);
+
+ result->explicit_loc.label_name = xstrdup (explicit_loc->label_name);
+ result->labels.label_symbols = labels;
+ result->labels.function_symbols = symbols;
+ }
+
+ if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ result->explicit_loc.line_offset = explicit_loc->line_offset;
+
+ return convert_linespec_to_sals (self, result);
+}
+
/* Parse a string that specifies a linespec.
- Pass the address of a char * variable; that variable will be
- advanced over the characters actually parsed.
The basic grammar of linespecs:
- linespec -> expr_spec | var_spec | basic_spec
- expr_spec -> '*' STRING
+ linespec -> var_spec | basic_spec
var_spec -> '$' (STRING | NUMBER)
basic_spec -> file_offset_spec | function_spec | label_spec
if no file is validly specified. Callers must check that.
Also, the line number returned may be invalid. */
-/* Parse the linespec in ARGPTR. */
+/* Parse the linespec in ARG. */
static struct symtabs_and_lines
-parse_linespec (linespec_parser *parser, const char **argptr)
+parse_linespec (linespec_parser *parser, const char *arg)
{
linespec_token token;
struct symtabs_and_lines values;
- volatile struct gdb_exception file_exception;
+ struct gdb_exception file_exception = exception_none;
struct cleanup *cleanup;
/* A special case to start. It has become quite popular for
IDEs to work around bugs in the previous parser by quoting
the entire linespec, so we attempt to deal with this nicely. */
parser->is_quote_enclosed = 0;
- if (!is_ada_operator (*argptr)
- && strchr (linespec_quote_characters, **argptr) != NULL)
+ if (!is_ada_operator (arg)
+ && strchr (linespec_quote_characters, *arg) != NULL)
{
const char *end;
- end = skip_quote_char (*argptr + 1, **argptr);
+ end = skip_quote_char (arg + 1, *arg);
if (end != NULL && is_closing_quote_enclosed (end))
{
- /* Here's the special case. Skip ARGPTR past the initial
+ /* Here's the special case. Skip ARG past the initial
quote. */
- ++(*argptr);
+ ++arg;
parser->is_quote_enclosed = 1;
}
}
- /* 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;
+ parser->lexer.saved_arg = arg;
+ parser->lexer.stream = arg;
/* Initialize the default symtab and line offset. */
initialize_defaults (&PARSER_STATE (parser)->default_symtab,
&PARSER_STATE (parser)->default_line);
/* Objective-C shortcut. */
- values = decode_objc (PARSER_STATE (parser), PARSER_RESULT (parser), argptr);
+ values = decode_objc (PARSER_STATE (parser), PARSER_RESULT (parser), arg);
if (values.sals != NULL)
return values;
token = linespec_lexer_lex_one (parser);
/* It must be either LSTOKEN_STRING or LSTOKEN_NUMBER. */
- if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '*')
- {
- char *expr;
- const char *copy;
-
- /* User specified an expression, *EXPR. */
- copy = expr = copy_token_string (token);
- cleanup = make_cleanup (xfree, expr);
- PARSER_RESULT (parser)->expr_pc = linespec_expression_to_pc (©);
- discard_cleanups (cleanup);
- PARSER_RESULT (parser)->expression = expr;
-
- /* This is a little hacky/tricky. If linespec_expression_to_pc
- did not evaluate the entire token, then we must find the
- string COPY inside the original token buffer. */
- if (*copy != '\0')
- {
- PARSER_STREAM (parser) = strstr (parser->lexer.saved_arg, copy);
- gdb_assert (PARSER_STREAM (parser) != NULL);
- }
-
- /* Consume the token. */
- linespec_lexer_consume_token (parser);
-
- goto convert_to_sals;
- }
- else if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
+ if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
{
char *var;
/* User specified a convenience variable or history value. */
var = copy_token_string (token);
cleanup = make_cleanup (xfree, var);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (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)
+ if (PARSER_EXPLICIT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
{
/* Consume this token. */
linespec_lexer_consume_token (parser);
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);
user_filename = copy_token_string (token);
/* Check if the input is a filename. */
- TRY_CATCH (file_exception, RETURN_MASK_ERROR)
+ TRY
{
PARSER_RESULT (parser)->file_symtabs
- = symtabs_from_filename (user_filename);
+ = symtabs_from_filename (user_filename,
+ PARSER_STATE (parser)->search_pspace);
}
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ file_exception = ex;
+ }
+ END_CATCH
if (file_exception.reason >= 0)
{
/* Symtabs were found for the file. Record the filename. */
- PARSER_RESULT (parser)->source_filename = user_filename;
+ PARSER_EXPLICIT (parser)->source_filename = user_filename;
/* Get the next token. */
token = linespec_lexer_consume_token (parser);
if (PARSER_RESULT (parser)->function_symbols == NULL
&& PARSER_RESULT (parser)->labels.label_symbols == NULL
- && PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
+ && PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
&& PARSER_RESULT (parser)->minimal_symbols == NULL)
{
/* The linespec didn't parse. Re-throw the file exception if
throw_exception (file_exception);
/* Otherwise, the symbol is not found. */
- symbol_not_found_error (PARSER_RESULT (parser)->function_name,
- PARSER_RESULT (parser)->source_filename);
+ symbol_not_found_error (PARSER_EXPLICIT (parser)->function_name,
+ PARSER_EXPLICIT (parser)->source_filename);
}
convert_to_sals:
static void
linespec_state_constructor (struct linespec_state *self,
int flags, const struct language_defn *language,
+ struct program_space *search_pspace,
struct symtab *default_symtab,
int default_line,
struct linespec_result *canonical)
self->language = language;
self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
+ self->search_pspace = search_pspace;
self->default_symtab = default_symtab;
self->default_line = default_line;
self->canonical = canonical;
self->program_space = current_program_space;
self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
xfree, xcalloc, xfree);
+ self->is_linespec = 0;
}
/* Initialize a new linespec parser. */
static void
linespec_parser_new (linespec_parser *parser,
int flags, const struct language_defn *language,
+ struct program_space *search_pspace,
struct symtab *default_symtab,
int default_line,
struct linespec_result *canonical)
{
+ memset (parser, 0, sizeof (linespec_parser));
parser->lexer.current.type = LSTOKEN_CONSUMED;
memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
- PARSER_RESULT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
+ PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
linespec_state_constructor (PARSER_STATE (parser), flags, language,
+ search_pspace,
default_symtab, default_line, canonical);
}
{
linespec_parser *parser = (linespec_parser *) arg;
- 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);
+ xfree (PARSER_EXPLICIT (parser)->source_filename);
+ xfree (PARSER_EXPLICIT (parser)->label_name);
+ xfree (PARSER_EXPLICIT (parser)->function_name);
if (PARSER_RESULT (parser)->file_symtabs != NULL)
VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs);
linespec_state_destructor (PARSER_STATE (parser));
}
+/* See description in linespec.h. */
+
+void
+linespec_lex_to_end (char **stringp)
+{
+ linespec_parser parser;
+ struct cleanup *cleanup;
+ linespec_token token;
+ const char *orig;
+
+ if (stringp == NULL || *stringp == NULL)
+ return;
+
+ linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
+ cleanup = make_cleanup (linespec_parser_delete, &parser);
+ parser.lexer.saved_arg = *stringp;
+ PARSER_STREAM (&parser) = orig = *stringp;
+
+ do
+ {
+ /* Stop before any comma tokens; we need it to keep it
+ as the next token in the string. */
+ token = linespec_lexer_peek_token (&parser);
+ if (token.type == LSTOKEN_COMMA)
+ break;
+ token = linespec_lexer_consume_token (&parser);
+ }
+ while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
+
+ *stringp += PARSER_STREAM (&parser) - orig;
+ do_cleanups (cleanup);
+}
+
+/* A helper function for decode_line_full and decode_line_1 to
+ turn LOCATION into symtabs_and_lines. */
+
+static struct symtabs_and_lines
+event_location_to_sals (linespec_parser *parser,
+ const struct event_location *location)
+{
+ struct symtabs_and_lines result = {NULL, 0};
+
+ switch (event_location_type (location))
+ {
+ case LINESPEC_LOCATION:
+ {
+ PARSER_STATE (parser)->is_linespec = 1;
+ TRY
+ {
+ result = parse_linespec (parser, get_linespec_location (location));
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ throw_exception (except);
+ }
+ END_CATCH
+ }
+ break;
+
+ case ADDRESS_LOCATION:
+ {
+ const char *addr_string = get_address_string_location (location);
+ CORE_ADDR addr = get_address_location (location);
+
+ if (addr_string != NULL)
+ {
+ char *expr = xstrdup (addr_string);
+ const char *const_expr = expr;
+ struct cleanup *cleanup = make_cleanup (xfree, expr);
+
+ addr = linespec_expression_to_pc (&const_expr);
+ if (PARSER_STATE (parser)->canonical != NULL)
+ PARSER_STATE (parser)->canonical->location
+ = copy_event_location (location);
+
+ do_cleanups (cleanup);
+ }
+
+ result = convert_address_location_to_sals (PARSER_STATE (parser),
+ addr);
+ }
+ break;
+
+ case EXPLICIT_LOCATION:
+ {
+ const struct explicit_location *explicit_loc;
+
+ explicit_loc = get_explicit_location_const (location);
+ result = convert_explicit_location_to_sals (PARSER_STATE (parser),
+ PARSER_RESULT (parser),
+ explicit_loc);
+ }
+ break;
+
+ case PROBE_LOCATION:
+ /* Probes are handled by their own decoders. */
+ gdb_assert_not_reached ("attempt to decode probe location");
+ break;
+
+ default:
+ gdb_assert_not_reached ("unhandled event location type");
+ }
+
+ return result;
+}
+
/* See linespec.h. */
void
-decode_line_full (char **argptr, int flags,
+decode_line_full (const struct event_location *location, int flags,
+ struct program_space *search_pspace,
struct symtab *default_symtab,
int default_line, struct linespec_result *canonical,
const char *select_mode,
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'. */
|| select_mode == multiple_symbols_cancel);
gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
- linespec_parser_new (&parser, flags, current_language, default_symtab,
+ linespec_parser_new (&parser, flags, current_language,
+ search_pspace, default_symtab,
default_line, canonical);
cleanups = make_cleanup (linespec_parser_delete, &parser);
save_current_program_space ();
- orig = copy = *argptr;
- result = parse_linespec (&parser, ©);
- *argptr += copy - orig;
+ result = event_location_to_sals (&parser, location);
state = PARSER_STATE (&parser);
gdb_assert (result.nelts == 1 || canonical->pre_expanded);
- gdb_assert (canonical->addr_string != NULL);
canonical->pre_expanded = 1;
/* Arrange for allocated canonical names to be freed. */
/* See linespec.h. */
struct symtabs_and_lines
-decode_line_1 (char **argptr, int flags,
+decode_line_1 (const struct event_location *location, int flags,
+ struct program_space *search_pspace,
struct symtab *default_symtab,
int default_line)
{
struct symtabs_and_lines result;
linespec_parser parser;
struct cleanup *cleanups;
- const char *copy, *orig;
- linespec_parser_new (&parser, flags, current_language, default_symtab,
+ linespec_parser_new (&parser, flags, current_language,
+ search_pspace, default_symtab,
default_line, NULL);
cleanups = make_cleanup (linespec_parser_delete, &parser);
save_current_program_space ();
- orig = copy = *argptr;
- result = parse_linespec (&parser, ©);
- *argptr += copy - orig;
+ result = event_location_to_sals (&parser, location);
do_cleanups (cleanups);
return result;
{
struct symtabs_and_lines sals;
struct symtab_and_line cursal;
+ struct event_location *location;
+ struct cleanup *cleanup;
if (string == 0)
error (_("Empty line specification."));
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,
+ location = string_to_event_location (&string, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
+ sals = decode_line_1 (location, flags, NULL,
cursal.symtab, cursal.line);
if (*string)
error (_("Junk at end of line specification: %s"), string);
+
+ do_cleanups (cleanup);
return sals;
}
decode_line_with_last_displayed (char *string, int flags)
{
struct symtabs_and_lines sals;
+ struct event_location *location;
+ struct cleanup *cleanup;
if (string == 0)
error (_("Empty line specification."));
+ location = string_to_event_location (&string, current_language);
+ cleanup = make_cleanup_delete_event_location (location);
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&string, flags,
+ sals = decode_line_1 (location, flags, NULL,
get_last_displayed_symtab (),
get_last_displayed_line ());
else
- sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
+ sals = decode_line_1 (location, flags, NULL, (struct symtab *) NULL, 0);
if (*string)
error (_("Junk at end of line specification: %s"), string);
+
+ do_cleanups (cleanup);
return sals;
}
/* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR,
advancing EXP_PTR past any parsed text. */
-static CORE_ADDR
+CORE_ADDR
linespec_expression_to_pc (const char **exp_ptr)
{
if (current_program_space->executing_startup)
the existing C++ code to let the user choose one. */
static struct symtabs_and_lines
-decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
+decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
{
struct collect_info info;
VEC (const_char_ptr) *symbol_names = NULL;
values.nelts = 0;
values.sals = NULL;
- new_argptr = find_imps (*argptr, &symbol_names);
+ new_argptr = find_imps (arg, &symbol_names);
if (VEC_empty (const_char_ptr, symbol_names))
{
do_cleanups (cleanup);
{
char *saved_arg;
- saved_arg = alloca (new_argptr - *argptr + 1);
- memcpy (saved_arg, *argptr, new_argptr - *argptr);
- saved_arg[new_argptr - *argptr] = '\0';
+ saved_arg = (char *) alloca (new_argptr - arg + 1);
+ memcpy (saved_arg, arg, new_argptr - arg);
+ saved_arg[new_argptr - arg] = '\0';
- ls->function_name = xstrdup (saved_arg);
+ ls->explicit_loc.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);
if (self->canonical)
{
+ char *str;
+
self->canonical->pre_expanded = 1;
- if (ls->source_filename)
- self->canonical->addr_string
- = xstrprintf ("%s:%s", ls->source_filename, saved_arg);
+
+ if (ls->explicit_loc.source_filename)
+ {
+ str = xstrprintf ("%s:%s",
+ ls->explicit_loc.source_filename, saved_arg);
+ }
else
- self->canonical->addr_string = xstrdup (saved_arg);
+ str = xstrdup (saved_arg);
+
+ make_cleanup (xfree, str);
+ self->canonical->location = new_linespec_location (&str);
}
}
- *argptr = new_argptr;
-
do_cleanups (cleanup);
return values;
static int
collect_one_symbol (struct symbol *sym, void *d)
{
- struct decode_compound_collector *collector = d;
+ struct decode_compound_collector *collector
+ = (struct decode_compound_collector *) d;
void **slot;
struct type *t;
return 1; /* Continue iterating. */
t = SYMBOL_TYPE (sym);
- CHECK_TYPEDEF (t);
+ t = check_typedef (t);
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION
&& TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
static int
compare_symbols (const void *a, const void *b)
{
- struct symbol * const *sa = a;
- struct symbol * const *sb = b;
+ struct symbol * const *sa = (struct symbol * const*) a;
+ struct symbol * const *sb = (struct symbol * const*) b;
uintptr_t uia, uib;
- uia = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sa));
- uib = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sb));
+ uia = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sa));
+ uib = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sb));
if (uia < uib)
return -1;
static int
compare_msymbols (const void *a, const void *b)
{
- const struct bound_minimal_symbol *sa = a;
- const struct bound_minimal_symbol *sb = b;
+ const struct bound_minimal_symbol *sa
+ = (const struct bound_minimal_symbol *) a;
+ const struct bound_minimal_symbol *sb
+ = (const struct bound_minimal_symbol *) b;
uintptr_t uia, uib;
uia = (uintptr_t) sa->objfile->pspace;
/* Program spaces that are executing startup should have
been filtered out earlier. */
- gdb_assert (!SYMTAB_PSPACE (SYMBOL_SYMTAB (sym))->executing_startup);
- pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+ gdb_assert (!pspace->executing_startup);
set_current_program_space (pspace);
t = check_typedef (SYMBOL_TYPE (sym));
find_methods (t, method_name, &result_names, &superclass_vec);
sure not to miss the last batch. */
if (ix == VEC_length (symbolp, sym_classes) - 1
|| (pspace
- != SYMTAB_PSPACE (SYMBOL_SYMTAB (VEC_index (symbolp, sym_classes,
+ != SYMTAB_PSPACE (symbol_symtab (VEC_index (symbolp, sym_classes,
ix + 1)))))
{
/* If we did not find a direct implementation anywhere in
static int
add_symtabs_to_list (struct symtab *symtab, void *d)
{
- struct symtab_collector *data = d;
+ struct symtab_collector *data = (struct symtab_collector *) d;
void **slot;
slot = htab_find_slot (data->symtab_table, symtab, INSERT);
return 0;
}
-/* Given a file name, return a VEC of all matching symtabs. */
+/* Given a file name, return a VEC of all matching symtabs. If
+ SEARCH_PSPACE is not NULL, the search is restricted to just that
+ program space. */
static VEC (symtab_ptr) *
-collect_symtabs_from_filename (const char *file)
+collect_symtabs_from_filename (const char *file,
+ struct program_space *search_pspace)
{
struct symtab_collector collector;
struct cleanup *cleanups;
cleanups = make_cleanup_htab_delete (collector.symtab_table);
/* Find that file's data. */
- ALL_PSPACES (pspace)
- {
- if (pspace->executing_startup)
- continue;
+ if (search_pspace == NULL)
+ {
+ ALL_PSPACES (pspace)
+ {
+ if (pspace->executing_startup)
+ continue;
- set_current_program_space (pspace);
- iterate_over_symtabs (file, add_symtabs_to_list, &collector);
- }
+ set_current_program_space (pspace);
+ iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ }
+ }
+ else
+ {
+ set_current_program_space (search_pspace);
+ iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ }
do_cleanups (cleanups);
return collector.symtabs;
}
-/* Return all the symtabs associated to the FILENAME. */
+/* Return all the symtabs associated to the FILENAME. If SEARCH_PSPACE is
+ not NULL, the search is restricted to just that program space. */
static VEC (symtab_ptr) *
-symtabs_from_filename (const char *filename)
+symtabs_from_filename (const char *filename,
+ struct program_space *search_pspace)
{
VEC (symtab_ptr) *result;
- result = collect_symtabs_from_filename (filename);
+ result = collect_symtabs_from_filename (filename, search_pspace);
if (VEC_empty (symtab_ptr, result))
{
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. "
"Use the \"file\" command."));
- throw_error (NOT_FOUND_ERROR, _("No source file named %s."), filename);
+ source_file_not_found_error (filename);
}
return result;
/* Try NAME as an Objective-C selector. */
find_imps (name, &symbol_names);
if (!VEC_empty (const_char_ptr, symbol_names))
- add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
+ add_all_symbol_names_from_pspace (&info, state->search_pspace,
+ symbol_names);
else
- add_matching_symbols_to_info (name, &info, NULL);
+ add_matching_symbols_to_info (name, &info, state->search_pspace);
do_cleanups (cleanup);
struct cleanup *cleanup;
char *canon;
const char *lookup_name;
- volatile struct gdb_exception except;
cleanup = demangle_for_lookup (name, state->language->la_language,
&lookup_name);
/* LOOKUP_NAME points to the class name.
LAST points to the method name. */
- klass = xmalloc ((last - lookup_name + 1) * sizeof (char));
+ klass = XNEWVEC (char, last - lookup_name + 1);
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));
+ method = XNEWVEC (char, strlen (last) + 1);
make_cleanup (xfree, method);
strcpy (method, last);
if (!VEC_empty (symbolp, classes))
{
/* Now locate a list of suitable methods named METHOD. */
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
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);
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ if (except.error != NOT_FOUND_ERROR)
+ throw_exception (except);
+ }
+ END_CATCH
}
}
return NULL;
fn_sym = BLOCK_FUNCTION (block);
- sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
+ sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol;
if (sym != NULL)
{
for (ix = 0;
VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
{
- set_current_program_space (SYMTAB_PSPACE (SYMBOL_SYMTAB (fn_sym)));
+ set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym)));
block = SYMBOL_BLOCK_VALUE (fn_sym);
- sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
+ sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol;
if (sym != NULL)
{
static int
collect_symbols (struct symbol *sym, void *data)
{
- struct collect_info *info = data;
+ struct collect_info *info = (struct collect_info *) data;
/* In list mode, add all matching symbols, regardless of class.
This allows the user to type "list a_global_variable". */
}
/* We've found a minimal symbol MSYMBOL in OBJFILE to associate with our
- linespec; return the SAL in RESULT. */
+ linespec; return the SAL in RESULT. This function should return SALs
+ matching those from find_function_start_sal, otherwise false
+ multiple-locations breakpoints could be placed. */
static void
minsym_found (struct linespec_state *self, struct objfile *objfile,
sal = find_pc_sect_line (pc, NULL, 0);
if (self->funfirstline)
- skip_prologue_sal (&sal);
+ {
+ if (sal.symtab != NULL
+ && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
+ || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
+ {
+ /* If gdbarch_convert_from_func_ptr_addr does not apply then
+ sal.SECTION, sal.LINE&co. will stay correct from above.
+ If gdbarch_convert_from_func_ptr_addr applies then
+ sal.SECTION is cleared from above and sal.LINE&co. will
+ stay correct from the last find_pc_sect_line above. */
+ sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
+ sal.pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc,
+ ¤t_target);
+ if (gdbarch_skip_entrypoint_p (gdbarch))
+ sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
+ }
+ else
+ skip_prologue_sal (&sal);
+ }
if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
add_sal_to_sals (self, result, &sal, MSYMBOL_NATURAL_NAME (msymbol), 0);
/* The objfile we're examining. */
struct objfile *objfile;
+ /* Only search the given symtab, or NULL to search for all symbols. */
+ struct symtab *symtab;
+
/* The funfirstline setting from the initial call. */
int funfirstline;
static int
compare_msyms (const void *a, const void *b)
{
- const bound_minimal_symbol_d *moa = a;
- const bound_minimal_symbol_d *mob = b;
+ const bound_minimal_symbol_d *moa = (const bound_minimal_symbol_d *) a;
+ const bound_minimal_symbol_d *mob = (const bound_minimal_symbol_d *) b;
enum minimal_symbol_type ta = MSYMBOL_TYPE (moa->minsym);
enum minimal_symbol_type tb = MSYMBOL_TYPE (mob->minsym);
static void
add_minsym (struct minimal_symbol *minsym, void *d)
{
- struct collect_minsyms *info = d;
+ struct collect_minsyms *info = (struct collect_minsyms *) d;
bound_minimal_symbol_d mo;
mo.minsym = minsym;
mo.objfile = info->objfile;
+ if (info->symtab != NULL)
+ {
+ CORE_ADDR pc;
+ struct symtab_and_line sal;
+ struct gdbarch *gdbarch = get_objfile_arch (info->objfile);
+
+ sal = find_pc_sect_line (MSYMBOL_VALUE_ADDRESS (info->objfile, minsym),
+ NULL, 0);
+ sal.section = MSYMBOL_OBJ_SECTION (info->objfile, minsym);
+ pc
+ = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, ¤t_target);
+ if (pc != sal.pc)
+ sal = find_pc_sect_line (pc, NULL, 0);
+
+ if (info->symtab != sal.symtab)
+ return;
+ }
+
/* Exclude data symbols when looking for breakpoint locations. */
if (!info->list_mode)
switch (minsym->type)
VEC_safe_push (bound_minimal_symbol_d, info->msyms, &mo);
}
-/* Search minimal symbols in all objfiles for NAME. If SEARCH_PSPACE
+/* Search for minimal symbols called NAME. If SEARCH_PSPACE
is not NULL, the search is restricted to just that program
- space. */
+ space.
+
+ If SYMTAB is NULL, search all objfiles, otherwise
+ restrict results to the given SYMTAB. */
static void
search_minsyms_for_name (struct collect_info *info, const char *name,
- struct program_space *search_pspace)
+ struct program_space *search_pspace,
+ struct symtab *symtab)
{
- struct objfile *objfile;
- struct program_space *pspace;
+ struct collect_minsyms local;
+ struct cleanup *cleanup;
- ALL_PSPACES (pspace)
- {
- struct collect_minsyms local;
- struct cleanup *cleanup;
+ memset (&local, 0, sizeof (local));
+ local.funfirstline = info->state->funfirstline;
+ local.list_mode = info->state->list_mode;
+ local.symtab = symtab;
- if (search_pspace != NULL && search_pspace != pspace)
- continue;
- if (pspace->executing_startup)
- continue;
+ cleanup = make_cleanup (VEC_cleanup (bound_minimal_symbol_d), &local.msyms);
- set_current_program_space (pspace);
+ if (symtab == NULL)
+ {
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ struct objfile *objfile;
- memset (&local, 0, sizeof (local));
- local.funfirstline = info->state->funfirstline;
- local.list_mode = info->state->list_mode;
+ if (search_pspace != NULL && search_pspace != pspace)
+ continue;
+ if (pspace->executing_startup)
+ continue;
- cleanup = make_cleanup (VEC_cleanup (bound_minimal_symbol_d),
- &local.msyms);
+ set_current_program_space (pspace);
- ALL_OBJFILES (objfile)
+ ALL_OBJFILES (objfile)
+ {
+ local.objfile = objfile;
+ iterate_over_minimal_symbols (objfile, name, add_minsym, &local);
+ }
+ }
+ }
+ else
{
- local.objfile = objfile;
- iterate_over_minimal_symbols (objfile, name, add_minsym, &local);
+ if (search_pspace == NULL || SYMTAB_PSPACE (symtab) == search_pspace)
+ {
+ set_current_program_space (SYMTAB_PSPACE (symtab));
+ local.objfile = SYMTAB_OBJFILE(symtab);
+ iterate_over_minimal_symbols (local.objfile, name, add_minsym,
+ &local);
+ }
}
if (!VEC_empty (bound_minimal_symbol_d, local.msyms))
}
do_cleanups (cleanup);
- }
}
/* A helper function to add all symbols matching NAME to INFO. If
iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN,
collect_symbols, info,
pspace, 1);
- search_minsyms_for_name (info, name, pspace);
+ search_minsyms_for_name (info, name, pspace, NULL);
}
else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
{
+ int prev_len = VEC_length (symbolp, info->result.symbols);
+
/* 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));
iterate_over_file_blocks (elt, name, VAR_DOMAIN,
collect_symbols, info);
+
+ /* If no new symbols were found in this iteration and this symtab
+ is in assembler, we might actually be looking for a label for
+ which we don't have debug info. Check for a minimal symbol in
+ this case. */
+ if (prev_len == VEC_length (symbolp, info->result.symbols)
+ && elt->language == language_asm)
+ search_minsyms_for_name (info, name, pspace, elt);
}
}
}
if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
{
init_sal (result);
- result->symtab = SYMBOL_SYMTAB (sym);
+ result->symtab = symbol_symtab (sym);
result->line = SYMBOL_LINE (sym);
result->pc = SYMBOL_VALUE_ADDRESS (sym);
- result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ result->pspace = SYMTAB_PSPACE (result->symtab);
result->explicit_pc = 1;
return 1;
}
{
/* We know its line number. */
init_sal (result);
- result->symtab = SYMBOL_SYMTAB (sym);
+ result->symtab = symbol_symtab (sym);
result->line = SYMBOL_LINE (sym);
- result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ result->pspace = SYMTAB_PSPACE (result->symtab);
return 1;
}
}
int i;
struct linespec_sals *lsal;
- xfree (ls->addr_string);
+ delete_event_location (ls->location);
for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
{
xfree (lsal->canonical);
static void
cleanup_linespec_result (void *a)
{
- destroy_linespec_result (a);
+ destroy_linespec_result ((struct linespec_result *) a);
}
/* See the comment in linespec.h. */
{
return make_cleanup (cleanup_linespec_result, ls);
}
+
+/* Return the quote characters permitted by the linespec parser. */
+
+const char *
+get_gdb_linespec_parser_quote_characters (void)
+{
+ return linespec_quote_characters;
+}