gdb/linespec.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "symtab.h"
- #include "frame.h"
- #include "command.h"
- #include "symfile.h"
- #include "objfiles.h"
- #include "source.h"
- #include "demangle.h"
- #include "value.h"
- #include "completer.h"
- #include "cp-abi.h"
- #include "cp-support.h"
- #include "parser-defs.h"
- #include "block.h"
- #include "objc-lang.h"
- #include "linespec.h"
- #include "language.h"
- #include "interps.h"
- #include "mi/mi-cmds.h"
- #include "target.h"
- #include "arch-utils.h"
- #include <ctype.h>
- #include "cli/cli-utils.h"
- #include "filenames.h"
- #include "ada-lang.h"
- #include "stack.h"
- typedef struct symbol *symbolp;
- DEF_VEC_P (symbolp);
- typedef struct type *typep;
- DEF_VEC_P (typep);
- struct address_entry
- {
- struct program_space *pspace;
- CORE_ADDR addr;
- };
- typedef struct bound_minimal_symbol bound_minimal_symbol_d;
- DEF_VEC_O (bound_minimal_symbol_d);
- enum offset_relative_sign
- {
-
- LINE_OFFSET_NONE,
-
- LINE_OFFSET_PLUS,
-
- LINE_OFFSET_MINUS,
-
- LINE_OFFSET_UNKNOWN
- };
- struct line_offset
- {
-
- int offset;
- enum offset_relative_sign sign;
- };
- struct linespec
- {
-
-
- const char *expression;
-
- CORE_ADDR expr_pc;
-
-
- const char *source_filename;
-
- VEC (symtab_ptr) *file_symtabs;
-
-
- const char *function_name;
-
- VEC (symbolp) *function_symbols;
- VEC (bound_minimal_symbol_d) *minimal_symbols;
-
-
- const char *label_name;
-
- struct
- {
- VEC (symbolp) *label_symbols;
- VEC (symbolp) *function_symbols;
- } labels;
-
- struct line_offset line_offset;
- };
- typedef struct linespec *linespec_p;
- struct linespec_canonical_name
- {
-
- char *suffix;
-
- struct symtab *symtab;
- };
- struct linespec_state
- {
-
- const struct language_defn *language;
-
- struct program_space *program_space;
-
- struct symtab *default_symtab;
-
- int default_line;
-
- int funfirstline;
-
- int list_mode;
-
- struct linespec_result *canonical;
-
- struct linespec_canonical_name *canonical_names;
-
- htab_t addr_set;
- };
- struct collect_info
- {
-
- struct linespec_state *state;
-
- VEC (symtab_ptr) *file_symtabs;
-
- struct
- {
- VEC (symbolp) *symbols;
- VEC (bound_minimal_symbol_d) *minimal_symbols;
- } result;
- };
- enum ls_token_type
- {
-
- LSTOKEN_KEYWORD = 0,
-
- LSTOKEN_COLON,
-
- LSTOKEN_STRING,
-
- LSTOKEN_NUMBER,
-
- LSTOKEN_COMMA,
-
- LSTOKEN_EOI,
-
- LSTOKEN_CONSUMED
- };
- typedef enum ls_token_type linespec_token_type;
- static const char * const linespec_keywords[] = { "if", "thread", "task" };
- struct ls_token
- {
-
- linespec_token_type type;
-
- union
- {
-
- struct stoken string;
-
- const char *keyword;
- } data;
- };
- typedef struct ls_token linespec_token;
- #define LS_TOKEN_STOKEN(TOK) (TOK).data.string
- #define LS_TOKEN_KEYWORD(TOK) (TOK).data.keyword
- struct ls_parser
- {
-
- struct
- {
-
- const char *saved_arg;
-
- const char **stream;
- #define PARSER_STREAM(P) (*(P)->lexer.stream)
-
- linespec_token current;
- } lexer;
-
- int is_quote_enclosed;
-
- int keyword_ok;
-
- struct linespec_state state;
- #define PARSER_STATE(PPTR) (&(PPTR)->state)
-
- struct linespec result;
- #define PARSER_RESULT(PPTR) (&(PPTR)->result)
- };
- typedef struct ls_parser linespec_parser;
- 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 (const char **exp_ptr);
- static struct symtabs_and_lines decode_objc (struct linespec_state *self,
- linespec_p ls,
- const char **argptr);
- 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);
- 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,
- const char *variable);
- static int symbol_to_sal (struct symtab_and_line *result,
- int funfirstline, struct symbol *sym);
- static void add_matching_symbols_to_info (const char *name,
- struct collect_info *info,
- struct program_space *pspace);
- static void add_all_symbol_names_from_pspace (struct collect_info *info,
- struct program_space *pspace,
- VEC (const_char_ptr) *names);
- static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file);
- static void decode_digits_ordinary (struct linespec_state *self,
- linespec_p ls,
- int line,
- struct symtabs_and_lines *sals,
- struct linetable_entry **best_entry);
- static void decode_digits_list_mode (struct linespec_state *self,
- linespec_p ls,
- struct symtabs_and_lines *values,
- struct symtab_and_line val);
- static void minsym_found (struct linespec_state *self, struct objfile *objfile,
- struct minimal_symbol *msymbol,
- struct symtabs_and_lines *result);
- static int compare_symbols (const void *a, const void *b);
- static int compare_msymbols (const void *a, const void *b);
- static const char *find_toplevel_char (const char *s, char c);
- static const char *const linespec_quote_characters = "\"\'";
- static int
- linespec_lexer_lex_number (linespec_parser *parser, linespec_token *tokenp)
- {
- tokenp->type = LSTOKEN_NUMBER;
- LS_TOKEN_STOKEN (*tokenp).length = 0;
- LS_TOKEN_STOKEN (*tokenp).ptr = PARSER_STREAM (parser);
-
- if (*PARSER_STREAM (parser) == '+' || *PARSER_STREAM (parser) == '-')
- {
- ++LS_TOKEN_STOKEN (*tokenp).length;
- ++(PARSER_STREAM (parser));
- }
- while (isdigit (*PARSER_STREAM (parser)))
- {
- ++LS_TOKEN_STOKEN (*tokenp).length;
- ++(PARSER_STREAM (parser));
- }
-
- if (*PARSER_STREAM (parser) != '\0'
- && !isspace (*PARSER_STREAM (parser)) && *PARSER_STREAM (parser) != ','
- && *PARSER_STREAM (parser) != ':'
- && !strchr (linespec_quote_characters, *PARSER_STREAM (parser)))
- {
- PARSER_STREAM (parser) = LS_TOKEN_STOKEN (*tokenp).ptr;
- return 0;
- }
- return 1;
- }
- static const char *
- linespec_lexer_lex_keyword (const char *p)
- {
- int i;
- if (p != NULL)
- {
- for (i = 0; i < ARRAY_SIZE (linespec_keywords); ++i)
- {
- int len = strlen (linespec_keywords[i]);
-
- if (strncmp (p, linespec_keywords[i], len) == 0
- && !(isalnum (p[len]) || p[len] == '_'))
- return linespec_keywords[i];
- }
- }
- return NULL;
- }
- static 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)
- ;
- return mapping->decoded == NULL ? 0 : strlen (mapping->decoded);
- }
- static const char *
- skip_quote_char (const char *string, char quote_char)
- {
- const char *p, *last;
- p = last = find_toplevel_char (string, quote_char);
- while (p && *p != '\0' && *p != ':')
- {
- p = find_toplevel_char (p, quote_char);
- if (p != NULL)
- last = p++;
- }
- return last;
- }
- static char *
- copy_token_string (linespec_token token)
- {
- char *str, *s;
- if (token.type == LSTOKEN_KEYWORD)
- return xstrdup (LS_TOKEN_KEYWORD (token));
- str = savestring (LS_TOKEN_STOKEN (token).ptr,
- LS_TOKEN_STOKEN (token).length);
- s = remove_trailing_whitespace (str, str + LS_TOKEN_STOKEN (token).length);
- *s = '\0';
- return str;
- }
- static int
- is_closing_quote_enclosed (const char *p)
- {
- if (strchr (linespec_quote_characters, *p))
- ++p;
- p = skip_spaces ((char *) p);
- return (*p == '\0' || linespec_lexer_lex_keyword (p));
- }
- static const char *
- find_parameter_list_end (const char *input)
- {
- char end_char, start_char;
- int depth;
- const char *p;
- start_char = *input;
- if (start_char == '(')
- end_char = ')';
- else if (start_char == '<')
- end_char = '>';
- else
- return NULL;
- p = input;
- depth = 0;
- while (*p)
- {
- if (*p == start_char)
- ++depth;
- else if (*p == end_char)
- {
- if (--depth == 0)
- {
- ++p;
- break;
- }
- }
- ++p;
- }
- return p;
- }
- static linespec_token
- linespec_lexer_lex_string (linespec_parser *parser)
- {
- linespec_token token;
- const char *start = PARSER_STREAM (parser);
- token.type = LSTOKEN_STRING;
-
- if (strchr (linespec_quote_characters, *PARSER_STREAM (parser)))
- {
- const char *end;
- char quote_char = *PARSER_STREAM (parser);
-
- if (PARSER_STATE (parser)->language->la_language == language_ada
- && quote_char == '\"')
- {
- int len = is_ada_operator (PARSER_STREAM (parser));
- if (len != 0)
- {
-
- LS_TOKEN_STOKEN (token).ptr = PARSER_STREAM (parser);
- LS_TOKEN_STOKEN (token).length = len;
- PARSER_STREAM (parser) += len;
- return token;
- }
-
- }
-
- ++(PARSER_STREAM (parser));
-
- LS_TOKEN_STOKEN (token).ptr = PARSER_STREAM (parser);
-
- end = skip_quote_char (PARSER_STREAM (parser), quote_char);
-
- if (end == NULL)
- error (_("unmatched quote"));
-
- PARSER_STREAM (parser) = (char *) ++end;
- LS_TOKEN_STOKEN (token).length = PARSER_STREAM (parser) - 2 - start;
- }
- else
- {
- const char *p;
-
- while (1)
- {
- if (isspace (*PARSER_STREAM (parser)))
- {
- p = skip_spaces_const (PARSER_STREAM (parser));
-
- if (linespec_lexer_lex_keyword (p) != NULL)
- {
- LS_TOKEN_STOKEN (token).ptr = start;
- LS_TOKEN_STOKEN (token).length
- = PARSER_STREAM (parser) - start;
- return token;
- }
-
- PARSER_STREAM (parser) = p;
- }
-
- if (*PARSER_STREAM (parser) == 0)
- {
- LS_TOKEN_STOKEN (token).ptr = start;
- LS_TOKEN_STOKEN (token).length = PARSER_STREAM (parser) - start;
- return token;
- }
- else if (PARSER_STREAM (parser)[0] == ':')
- {
-
- if (PARSER_STREAM (parser)[1] == ':')
- ++(PARSER_STREAM (parser));
-
- else if ((PARSER_STREAM (parser) - start) != 1
- || !IS_DIR_SEPARATOR (PARSER_STREAM (parser)[1]))
- {
- LS_TOKEN_STOKEN (token).ptr = start;
- LS_TOKEN_STOKEN (token).length
- = PARSER_STREAM (parser) - start;
- return token;
- }
- }
-
- else if (parser->is_quote_enclosed
- && strchr (linespec_quote_characters,
- *PARSER_STREAM (parser))
- && is_closing_quote_enclosed (PARSER_STREAM (parser)))
- {
- LS_TOKEN_STOKEN (token).ptr = start;
- LS_TOKEN_STOKEN (token).length = PARSER_STREAM (parser) - start;
- return token;
- }
-
- else if (*PARSER_STREAM (parser) == '<'
- || *PARSER_STREAM (parser) == '(')
- {
- const char *p;
- p = find_parameter_list_end (PARSER_STREAM (parser));
- if (p != NULL)
- {
- PARSER_STREAM (parser) = p;
- continue;
- }
- }
-
- else if (*PARSER_STREAM (parser) == ',')
- {
- if ((PARSER_STATE (parser)->language->la_language
- == language_cplus)
- && (PARSER_STREAM (parser) - start) > 8
- )
- {
- char *p = strstr (start, "operator");
- if (p != NULL && is_operator_name (p))
- {
-
- ++(PARSER_STREAM (parser));
- continue;
- }
- }
-
- LS_TOKEN_STOKEN (token).ptr = start;
- LS_TOKEN_STOKEN (token).length = PARSER_STREAM (parser) - start;
- return token;
- }
-
- ++(PARSER_STREAM (parser));
- }
- }
- return token;
- }
- static linespec_token
- linespec_lexer_lex_one (linespec_parser *parser)
- {
- const char *keyword;
- if (parser->lexer.current.type == LSTOKEN_CONSUMED)
- {
-
- PARSER_STREAM (parser) = skip_spaces_const (PARSER_STREAM (parser));
-
- keyword = NULL;
- if (parser->keyword_ok)
- keyword = linespec_lexer_lex_keyword (PARSER_STREAM (parser));
- if (keyword != NULL)
- {
- parser->lexer.current.type = LSTOKEN_KEYWORD;
- LS_TOKEN_KEYWORD (parser->lexer.current) = keyword;
- return parser->lexer.current;
- }
-
- switch (*PARSER_STREAM (parser))
- {
- case 0:
- parser->lexer.current.type = LSTOKEN_EOI;
- break;
- case '+': case '-':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (!linespec_lexer_lex_number (parser, &(parser->lexer.current)))
- parser->lexer.current = linespec_lexer_lex_string (parser);
- break;
- case ':':
-
- if (PARSER_STREAM (parser)[1] == ':')
- parser->lexer.current = linespec_lexer_lex_string (parser);
- else
- {
- parser->lexer.current.type = LSTOKEN_COLON;
- ++(PARSER_STREAM (parser));
- }
- break;
- case '\'': case '\"':
-
- if (parser->is_quote_enclosed
- && is_closing_quote_enclosed (PARSER_STREAM (parser)))
- {
- ++(PARSER_STREAM (parser));
- parser->lexer.current.type = LSTOKEN_EOI;
- }
- else
- parser->lexer.current = linespec_lexer_lex_string (parser);
- break;
- case ',':
- parser->lexer.current.type = LSTOKEN_COMMA;
- LS_TOKEN_STOKEN (parser->lexer.current).ptr
- = PARSER_STREAM (parser);
- LS_TOKEN_STOKEN (parser->lexer.current).length = 1;
- ++(PARSER_STREAM (parser));
- break;
- default:
-
- parser->lexer.current = linespec_lexer_lex_string (parser);
- break;
- }
- }
- return parser->lexer.current;
- }
- static linespec_token
- linespec_lexer_consume_token (linespec_parser *parser)
- {
- parser->lexer.current.type = LSTOKEN_CONSUMED;
- return linespec_lexer_lex_one (parser);
- }
- static linespec_token
- linespec_lexer_peek_token (linespec_parser *parser)
- {
- linespec_token next;
- const char *saved_stream = PARSER_STREAM (parser);
- linespec_token saved_token = parser->lexer.current;
- next = linespec_lexer_consume_token (parser);
- PARSER_STREAM (parser) = saved_stream;
- parser->lexer.current = saved_token;
- return next;
- }
- static void
- add_sal_to_sals_basic (struct symtabs_and_lines *sals,
- struct symtab_and_line *sal)
- {
- ++sals->nelts;
- sals->sals = xrealloc (sals->sals, sals->nelts * sizeof (sals->sals[0]));
- sals->sals[sals->nelts - 1] = *sal;
- }
- static void
- add_sal_to_sals (struct linespec_state *self,
- struct symtabs_and_lines *sals,
- struct symtab_and_line *sal,
- const char *symname, int literal_canonical)
- {
- add_sal_to_sals_basic (sals, sal);
- if (self->canonical)
- {
- struct linespec_canonical_name *canonical;
- self->canonical_names = xrealloc (self->canonical_names,
- (sals->nelts
- * sizeof (*self->canonical_names)));
- canonical = &self->canonical_names[sals->nelts - 1];
- if (!literal_canonical && sal->symtab)
- {
- const char *fullname = symtab_to_fullname (sal->symtab);
-
- if (symname != NULL && sal->line != 0
- && self->language->la_language == language_ada)
- canonical->suffix = xstrprintf ("%s:%d", symname, sal->line);
- else if (symname != NULL)
- canonical->suffix = xstrdup (symname);
- else
- canonical->suffix = xstrprintf ("%d", sal->line);
- canonical->symtab = sal->symtab;
- }
- else
- {
- if (symname != NULL)
- canonical->suffix = xstrdup (symname);
- else
- canonical->suffix = xstrdup ("<unknown>");
- canonical->symtab = NULL;
- }
- }
- }
- static hashval_t
- hash_address_entry (const void *p)
- {
- const struct address_entry *aep = p;
- hashval_t hash;
- hash = iterative_hash_object (aep->pspace, 0);
- return iterative_hash_object (aep->addr, hash);
- }
- static int
- eq_address_entry (const void *a, const void *b)
- {
- const struct address_entry *aea = a;
- const struct address_entry *aeb = b;
- return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
- }
- static int
- maybe_add_address (htab_t set, struct program_space *pspace, CORE_ADDR addr)
- {
- struct address_entry e, *p;
- void **slot;
- e.pspace = pspace;
- e.addr = addr;
- slot = htab_find_slot (set, &e, INSERT);
- if (*slot)
- return 0;
- p = XNEW (struct address_entry);
- memcpy (p, &e, sizeof (struct address_entry));
- *slot = p;
- return 1;
- }
- struct symbol_and_data_callback
- {
-
- symbol_found_callback_ftype *callback;
-
- void *data;
- };
- static int
- iterate_inline_only (struct symbol *sym, void *d)
- {
- if (SYMBOL_INLINED (sym))
- {
- struct symbol_and_data_callback *cad = d;
- return cad->callback (sym, cad->data);
- }
- return 1;
- }
- struct symbol_matcher_data
- {
-
- const char *lookup_name;
-
- symbol_name_cmp_ftype symbol_name_cmp;
- };
- static int
- iterate_name_matcher (const char *name, void *d)
- {
- const struct symbol_matcher_data *data = d;
- if (data->symbol_name_cmp (name, data->lookup_name) == 0)
- return 1;
- return 0;
- }
- static void
- iterate_over_all_matching_symtabs (struct linespec_state *state,
- const char *name,
- const domain_enum domain,
- symbol_found_callback_ftype *callback,
- void *data,
- struct program_space *search_pspace,
- int include_inline)
- {
- struct objfile *objfile;
- struct program_space *pspace;
- struct symbol_matcher_data matcher_data;
- matcher_data.lookup_name = name;
- matcher_data.symbol_name_cmp =
- state->language->la_get_symbol_name_cmp != NULL
- ? state->language->la_get_symbol_name_cmp (name)
- : strcmp_iw;
- ALL_PSPACES (pspace)
- {
- if (search_pspace != NULL && search_pspace != pspace)
- continue;
- if (pspace->executing_startup)
- continue;
- set_current_program_space (pspace);
- ALL_OBJFILES (objfile)
- {
- struct compunit_symtab *cu;
- if (objfile->sf)
- objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
- iterate_name_matcher,
- ALL_DOMAIN,
- &matcher_data);
- ALL_OBJFILE_COMPUNITS (objfile, cu)
- {
- struct symtab *symtab = COMPUNIT_FILETABS (cu);
- 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 (SYMTAB_BLOCKVECTOR (symtab));
- i++)
- {
- block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
- state->language->la_iterate_over_symbols
- (block, name, domain, iterate_inline_only, &cad);
- }
- }
- }
- }
- }
- }
- static const struct block *
- get_current_search_block (void)
- {
- const struct block *block;
- enum language save_language;
-
- save_language = current_language->la_language;
- block = get_selected_block (0);
- set_language (save_language);
- return block;
- }
- 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 (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
- block != NULL;
- block = BLOCK_SUPERBLOCK (block))
- LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
- }
- static void
- find_methods (struct type *t, const char *name,
- VEC (const_char_ptr) **result_names,
- VEC (typep) **superclasses)
- {
- int ibase;
- const char *class_name = type_name_no_tag (t);
-
- if (class_name)
- {
- int method_counter;
- CHECK_TYPEDEF (t);
-
- for (method_counter = TYPE_NFN_FIELDS (t) - 1;
- method_counter >= 0;
- --method_counter)
- {
- 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 (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
- method_name = dem_opname;
- else if (cplus_demangle_opname (method_name, dem_opname, 0))
- method_name = dem_opname;
- }
- if (strcmp_iw (method_name, name) == 0)
- {
- int field_counter;
- for (field_counter = (TYPE_FN_FIELDLIST_LENGTH (t, method_counter)
- - 1);
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- const char *phys_name;
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- continue;
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
- VEC_safe_push (const_char_ptr, *result_names, phys_name);
- }
- }
- }
- }
- for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
- }
- static const char *
- find_toplevel_char (const char *s, char c)
- {
- int quoted = 0;
- int depth = 0;
- const char *scan;
- for (scan = s; *scan; scan++)
- {
- if (quoted)
- {
- if (*scan == quoted)
- quoted = 0;
- else if (*scan == '\\' && *(scan + 1))
- scan++;
- }
- else if (*scan == c && ! quoted && depth == 0)
- return scan;
- else if (*scan == '"' || *scan == '\'')
- quoted = *scan;
- else if (*scan == '(' || *scan == '<')
- depth++;
- else if ((*scan == ')' || *scan == '>') && depth > 0)
- depth--;
- }
- return 0;
- }
- static const char *
- find_toplevel_string (const char *haystack, const char *needle)
- {
- const char *s = haystack;
- do
- {
- s = find_toplevel_char (s, *needle);
- if (s != NULL)
- {
-
- if (strncmp (s, needle, strlen (needle)) == 0)
- return s;
-
- ++s;
- }
- }
- while (s != NULL && *s != '\0');
-
- return NULL;
- }
- 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);
- }
- static void
- filter_results (struct linespec_state *self,
- struct symtabs_and_lines *result,
- VEC (const_char_ptr) *filters)
- {
- int i;
- const char *name;
- for (i = 0; VEC_iterate (const_char_ptr, filters, i, name); ++i)
- {
- struct linespec_sals lsal;
- int j;
- memset (&lsal, 0, sizeof (lsal));
- for (j = 0; j < result->nelts; ++j)
- {
- 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)
- {
- lsal.canonical = xstrdup (name);
- VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
- }
- }
- self->canonical->pre_expanded = 0;
- }
- static void
- convert_results_to_lsals (struct linespec_state *self,
- struct symtabs_and_lines *result)
- {
- struct linespec_sals lsal;
- lsal.canonical = NULL;
- lsal.sals = *result;
- VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
- }
- struct decode_line_2_item
- {
-
- char *fullform;
-
- char *displayform;
-
- unsigned int selected : 1;
- };
- 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);
- }
- static void
- decode_line_2 (struct linespec_state *self,
- struct symtabs_and_lines *result,
- const char *select_mode)
- {
- char *args, *prompt;
- int i;
- struct cleanup *old_chain;
- 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);
-
- items_count = result->nelts;
- items = xmalloc (sizeof (*items) * items_count);
- make_cleanup (xfree, items);
- for (i = 0; i < items_count; ++i)
- {
- const struct linespec_canonical_name *canonical;
- struct decode_line_2_item *item;
- canonical = &self->canonical_names[i];
- gdb_assert (canonical->suffix != NULL);
- item = &items[i];
- item->fullform = canonical_to_fullform (canonical);
- make_cleanup (xfree, item->fullform);
- if (canonical->symtab == NULL)
- item->displayform = canonical->suffix;
- else
- {
- 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);
- }
- item->selected = 0;
- }
-
- qsort (items, items_count, sizeof (*items), decode_line_2_compare_items);
-
- if (items_count >= 2)
- {
- struct decode_line_2_item *dst, *src;
- dst = items;
- for (src = &items[1]; src < &items[items_count]; src++)
- if (strcmp (src->fullform, dst->fullform) != 0)
- *++dst = *src;
- items_count = dst + 1 - items;
- }
- if (select_mode == multiple_symbols_cancel && items_count > 1)
- error (_("canceled because the command is ambiguous\n"
- "See set/show multiple-symbol."));
- if (select_mode == multiple_symbols_all || items_count == 1)
- {
- do_cleanups (old_chain);
- convert_results_to_lsals (self, result);
- return;
- }
- printf_unfiltered (_("[0] cancel\n[1] all\n"));
- for (i = 0; i < items_count; i++)
- printf_unfiltered ("[%d] %s\n", i + 2, items[i].displayform);
- prompt = getenv ("PS2");
- if (prompt == NULL)
- {
- prompt = "> ";
- }
- args = command_line_input (prompt, 0, "overload-choice");
- if (args == 0 || *args == 0)
- error_no_arg (_("one or more choice numbers"));
- init_number_or_range (&state, args);
- while (!state.finished)
- {
- int num;
- num = get_number_or_range (&state);
- if (num == 0)
- error (_("canceled"));
- else if (num == 1)
- {
-
- do_cleanups (old_chain);
- convert_results_to_lsals (self, result);
- return;
- }
- num -= 2;
- if (num >= items_count)
- printf_unfiltered (_("No choice number %d.\n"), num);
- else
- {
- struct decode_line_2_item *item = &items[num];
- if (!item->selected)
- {
- VEC_safe_push (const_char_ptr, filters, item->fullform);
- item->selected = 1;
- }
- else
- {
- printf_unfiltered (_("duplicate request for %d ignored.\n"),
- num + 2);
- }
- }
- }
- filter_results (self, result, filters);
- do_cleanups (old_chain);
- }
- static void ATTRIBUTE_NORETURN
- symbol_not_found_error (const char *symbol, const char *filename)
- {
- if (symbol == NULL)
- symbol = "";
- if (!have_full_symbols ()
- && !have_partial_symbols ()
- && !have_minimal_symbols ())
- throw_error (NOT_FOUND_ERROR,
- _("No symbol table is loaded. Use the \"file\" command."));
-
- if (*symbol == '$')
- {
- if (filename)
- throw_error (NOT_FOUND_ERROR,
- _("Undefined convenience variable or function \"%s\" "
- "not defined in \"%s\"."), symbol, filename);
- else
- throw_error (NOT_FOUND_ERROR,
- _("Undefined convenience variable or function \"%s\" "
- "not defined."), symbol);
- }
- else
- {
- if (filename)
- throw_error (NOT_FOUND_ERROR,
- _("Function \"%s\" not defined in \"%s\"."),
- symbol, filename);
- else
- throw_error (NOT_FOUND_ERROR,
- _("Function \"%s\" not defined."), symbol);
- }
- }
- static void ATTRIBUTE_NORETURN
- unexpected_linespec_error (linespec_parser *parser)
- {
- linespec_token token;
- static const char * token_type_strings[]
- = {"keyword", "colon", "string", "number", "comma", "end of input"};
-
- token = linespec_lexer_lex_one (parser);
-
- if (token.type == LSTOKEN_STRING || token.type == LSTOKEN_NUMBER
- || token.type == LSTOKEN_KEYWORD)
- {
- char *string;
- struct cleanup *cleanup;
- string = copy_token_string (token);
- cleanup = make_cleanup (xfree, string);
- throw_error (GENERIC_ERROR,
- _("malformed linespec error: unexpected %s, \"%s\""),
- token_type_strings[token.type], string);
- }
- else
- throw_error (GENERIC_ERROR,
- _("malformed linespec error: unexpected %s"),
- token_type_strings[token.type]);
- }
- static struct line_offset
- linespec_parse_line_offset (const char *string)
- {
- struct line_offset line_offset = {0, LINE_OFFSET_NONE};
- if (*string == '+')
- {
- line_offset.sign = LINE_OFFSET_PLUS;
- ++string;
- }
- else if (*string == '-')
- {
- line_offset.sign = LINE_OFFSET_MINUS;
- ++string;
- }
-
- line_offset.offset = atoi (string);
- return line_offset;
- }
- static void
- linespec_parse_basic (linespec_parser *parser)
- {
- char *name;
- linespec_token token;
- VEC (symbolp) *symbols, *labels;
- VEC (bound_minimal_symbol_d) *minimal_symbols;
- struct cleanup *cleanup;
-
- token = linespec_lexer_lex_one (parser);
-
- if (token.type == LSTOKEN_KEYWORD || token.type == LSTOKEN_EOI)
- unexpected_linespec_error (parser);
-
- else if (token.type == LSTOKEN_NUMBER)
- {
-
- name = copy_token_string (token);
- cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name);
- do_cleanups (cleanup);
-
- token = linespec_lexer_consume_token (parser);
-
- if (token.type == LSTOKEN_COMMA)
- return;
-
- if (token.type != LSTOKEN_KEYWORD && token.type != LSTOKEN_EOI)
- unexpected_linespec_error (parser);
- }
- if (token.type == LSTOKEN_KEYWORD || token.type == LSTOKEN_EOI)
- return;
-
- if (token.type != LSTOKEN_STRING)
- unexpected_linespec_error (parser);
-
- name = copy_token_string (token);
- cleanup = make_cleanup (xfree, name);
-
- find_linespec_symbols (PARSER_STATE (parser),
- PARSER_RESULT (parser)->file_symtabs, name,
- &symbols, &minimal_symbols);
- if (symbols != NULL || minimal_symbols != NULL)
- {
- PARSER_RESULT (parser)->function_symbols = symbols;
- PARSER_RESULT (parser)->minimal_symbols = minimal_symbols;
- PARSER_RESULT (parser)->function_name = name;
- symbols = NULL;
- discard_cleanups (cleanup);
- }
- else
- {
-
- labels = find_label_symbols (PARSER_STATE (parser), NULL,
- &symbols, name);
- if (labels != NULL)
- {
- PARSER_RESULT (parser)->labels.label_symbols = labels;
- PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
- symbols = NULL;
- discard_cleanups (cleanup);
- }
- else if (token.type == LSTOKEN_STRING
- && *LS_TOKEN_STOKEN (token).ptr == '$')
- {
-
- PARSER_RESULT (parser)->line_offset
- = linespec_parse_variable (PARSER_STATE (parser), name);
- if (PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
- {
-
- PARSER_RESULT (parser)->function_name = name;
- discard_cleanups (cleanup);
- return;
- }
-
- do_cleanups (cleanup);
- }
- else
- {
-
-
- PARSER_RESULT (parser)->function_name = name;
- discard_cleanups (cleanup);
- return;
- }
- }
-
- token = linespec_lexer_consume_token (parser);
- if (token.type == LSTOKEN_COLON)
- {
-
- token = linespec_lexer_consume_token (parser);
- if (token.type == LSTOKEN_NUMBER)
- {
-
- name = copy_token_string (token);
- cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
- = linespec_parse_line_offset (name);
- do_cleanups (cleanup);
-
- token = linespec_lexer_consume_token (parser);
- }
- else if (token.type == LSTOKEN_STRING)
- {
-
- name = copy_token_string (token);
- cleanup = make_cleanup (xfree, name);
- labels = find_label_symbols (PARSER_STATE (parser),
- PARSER_RESULT (parser)->function_symbols,
- &symbols, name);
- if (labels != NULL)
- {
- PARSER_RESULT (parser)->labels.label_symbols = labels;
- PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
- symbols = NULL;
- discard_cleanups (cleanup);
- }
- else
- {
-
- throw_error (NOT_FOUND_ERROR,
- _("No label \"%s\" defined in function \"%s\"."),
- name, PARSER_RESULT (parser)->function_name);
- }
-
- token = linespec_lexer_consume_token (parser);
- if (token.type == LSTOKEN_COLON)
- {
-
- token = linespec_lexer_consume_token (parser);
-
- if (token.type != LSTOKEN_NUMBER)
- unexpected_linespec_error (parser);
-
- name = copy_token_string (token);
- cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
- = linespec_parse_line_offset (name);
- do_cleanups (cleanup);
-
- token = linespec_lexer_consume_token (parser);
- }
- }
- else
- {
-
- unexpected_linespec_error (parser);
- }
- }
- }
- static void
- canonicalize_linespec (struct linespec_state *state, linespec_p ls)
- {
-
- if (!state->canonical)
- return;
-
- 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;
- }
- if (ls->function_name)
- {
- if (need_colon)
- fputc_unfiltered (':', buf);
- fputs_unfiltered (ls->function_name, buf);
- need_colon = 1;
- }
- if (ls->label_name)
- {
- if (need_colon)
- fputc_unfiltered (':', buf);
- if (ls->function_name == NULL)
- {
- struct symbol *s;
-
- 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;
- }
- 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);
- }
- state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
- ui_file_delete (buf);
- }
- }
- static struct symtabs_and_lines
- create_sals_line_offset (struct linespec_state *self,
- linespec_p ls)
- {
- struct symtabs_and_lines values;
- struct symtab_and_line val;
- int use_default = 0;
- init_sal (&val);
- values.sals = NULL;
- values.nelts = 0;
-
- 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);
-
- set_default_source_symtab_and_line ();
- initialize_defaults (&self->default_symtab, &self->default_line);
- 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;
- }
- val.line = ls->line_offset.offset;
- switch (ls->line_offset.sign)
- {
- case LINE_OFFSET_PLUS:
- if (ls->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)
- val.line = 15;
- if (use_default)
- val.line = self->default_line - val.line;
- else
- val.line = -val.line;
- break;
- case LINE_OFFSET_NONE:
- break;
- }
- if (self->list_mode)
- decode_digits_list_mode (self, ls, &values, val);
- else
- {
- struct linetable_entry *best_entry = NULL;
- int *filter;
- const struct block **blocks;
- struct cleanup *cleanup;
- struct symtabs_and_lines intermediate_results;
- int i, j;
- intermediate_results.sals = NULL;
- intermediate_results.nelts = 0;
- decode_digits_ordinary (self, ls, val.line, &intermediate_results,
- &best_entry);
- if (intermediate_results.nelts == 0 && best_entry != NULL)
- decode_digits_ordinary (self, ls, best_entry->line,
- &intermediate_results, &best_entry);
- cleanup = make_cleanup (xfree, intermediate_results.sals);
-
- filter = XNEWVEC (int, intermediate_results.nelts);
- make_cleanup (xfree, filter);
- blocks = XNEWVEC (const struct block *, intermediate_results.nelts);
- make_cleanup (xfree, blocks);
- for (i = 0; i < intermediate_results.nelts; ++i)
- {
- set_current_program_space (intermediate_results.sals[i].pspace);
- filter[i] = 1;
- blocks[i] = block_for_pc_sect (intermediate_results.sals[i].pc,
- intermediate_results.sals[i].section);
- }
- for (i = 0; i < intermediate_results.nelts; ++i)
- {
- if (blocks[i] != NULL)
- for (j = i + 1; j < intermediate_results.nelts; ++j)
- {
- if (blocks[j] == blocks[i])
- {
- filter[j] = 0;
- break;
- }
- }
- }
- for (i = 0; i < intermediate_results.nelts; ++i)
- if (filter[i])
- {
- struct symbol *sym = (blocks[i]
- ? block_containing_function (blocks[i])
- : NULL);
- if (self->funfirstline)
- skip_prologue_sal (&intermediate_results.sals[i]);
-
- intermediate_results.sals[i].line = val.line;
- add_sal_to_sals (self, &values, &intermediate_results.sals[i],
- sym ? SYMBOL_NATURAL_NAME (sym) : NULL, 0);
- }
- do_cleanups (cleanup);
- }
- if (values.nelts == 0)
- {
- if (ls->source_filename)
- throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
- val.line, ls->source_filename);
- else
- throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
- val.line);
- }
- return values;
- }
- static struct symtabs_and_lines
- convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
- {
- struct symtabs_and_lines sals = {NULL, 0};
- if (ls->expression != NULL)
- {
- struct symtab_and_line sal;
-
- 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)
- {
-
- int i;
- struct symtab_and_line sal;
- struct symbol *sym;
- for (i = 0; VEC_iterate (symbolp, ls->labels.label_symbols, i, sym); ++i)
- {
- struct program_space *pspace = SYMTAB_PSPACE (symbol_symtab (sym));
- if (symbol_to_sal (&sal, state->funfirstline, sym)
- && maybe_add_address (state->addr_set, pspace, sal.pc))
- add_sal_to_sals (state, &sals, &sal,
- SYMBOL_NATURAL_NAME (sym), 0);
- }
- }
- else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL)
- {
-
- int i;
- struct symtab_and_line sal;
- struct symbol *sym;
- bound_minimal_symbol_d *elem;
- struct program_space *pspace;
- if (ls->function_symbols != NULL)
- {
-
- qsort (VEC_address (symbolp, ls->function_symbols),
- VEC_length (symbolp, ls->function_symbols),
- sizeof (symbolp), compare_symbols);
- for (i = 0; VEC_iterate (symbolp, ls->function_symbols, i, sym); ++i)
- {
- 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))
- add_sal_to_sals (state, &sals, &sal,
- SYMBOL_NATURAL_NAME (sym), 0);
- }
- }
- if (ls->minimal_symbols != NULL)
- {
-
- 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 (bound_minimal_symbol_d, ls->minimal_symbols,
- i, elem);
- ++i)
- {
- pspace = elem->objfile->pspace;
- set_current_program_space (pspace);
- minsym_found (state, elem->objfile, elem->minsym, &sals);
- }
- }
- }
- else if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
- {
-
- sals = create_sals_line_offset (state, ls);
-
- if (ls->source_filename == NULL)
- {
- const char *fullname = symtab_to_fullname (state->default_symtab);
-
- ls->source_filename = xstrdup (fullname);
- }
- }
- else
- {
-
- return sals;
- }
- canonicalize_linespec (state, ls);
- if (sals.nelts > 0 && state->canonical != NULL)
- state->canonical->pre_expanded = 1;
- return sals;
- }
- static struct symtabs_and_lines
- parse_linespec (linespec_parser *parser, const char **argptr)
- {
- linespec_token token;
- struct symtabs_and_lines values;
- volatile struct gdb_exception file_exception;
- struct cleanup *cleanup;
-
- parser->is_quote_enclosed = 0;
- if (!is_ada_operator (*argptr)
- && strchr (linespec_quote_characters, **argptr) != NULL)
- {
- const char *end;
- end = skip_quote_char (*argptr + 1, **argptr);
- if (end != NULL && is_closing_quote_enclosed (end))
- {
-
- ++(*argptr);
- parser->is_quote_enclosed = 1;
- }
- }
-
- parser->keyword_ok = 0;
- parser->lexer.saved_arg = *argptr;
- parser->lexer.stream = argptr;
- file_exception.reason = 0;
-
- initialize_defaults (&PARSER_STATE (parser)->default_symtab,
- &PARSER_STATE (parser)->default_line);
-
- values = decode_objc (PARSER_STATE (parser), PARSER_RESULT (parser), argptr);
- if (values.sals != NULL)
- return values;
-
-
- token = linespec_lexer_lex_one (parser);
-
- if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '*')
- {
- char *expr;
- const char *copy;
-
- 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;
-
- if (*copy != '\0')
- {
- PARSER_STREAM (parser) = strstr (parser->lexer.saved_arg, copy);
- gdb_assert (PARSER_STREAM (parser) != NULL);
- }
-
- linespec_lexer_consume_token (parser);
- goto convert_to_sals;
- }
- else if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
- {
- char *var;
-
- VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
-
- 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 (PARSER_RESULT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
- {
-
- linespec_lexer_consume_token (parser);
- goto convert_to_sals;
- }
- }
- else if (token.type != LSTOKEN_STRING && token.type != LSTOKEN_NUMBER)
- unexpected_linespec_error (parser);
-
- parser->keyword_ok = 1;
-
- token = linespec_lexer_peek_token (parser);
- if (token.type == LSTOKEN_COLON)
- {
- char *user_filename;
-
- token = linespec_lexer_lex_one (parser);
- user_filename = copy_token_string (token);
-
- TRY_CATCH (file_exception, RETURN_MASK_ERROR)
- {
- PARSER_RESULT (parser)->file_symtabs
- = symtabs_from_filename (user_filename);
- }
- if (file_exception.reason >= 0)
- {
-
- PARSER_RESULT (parser)->source_filename = user_filename;
-
- token = linespec_lexer_consume_token (parser);
-
- linespec_lexer_consume_token (parser);
- }
- else
- {
-
- xfree (user_filename);
-
- VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
- }
- }
-
- else if (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD
- && token.type != LSTOKEN_COMMA)
- {
-
- linespec_lexer_consume_token (parser);
- unexpected_linespec_error (parser);
- }
- else
- {
-
- VEC_safe_push (symtab_ptr, PARSER_RESULT (parser)->file_symtabs, NULL);
- }
-
- linespec_parse_basic (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_RESULT (parser)->minimal_symbols == NULL)
- {
-
- if (file_exception.reason < 0)
- throw_exception (file_exception);
-
- symbol_not_found_error (PARSER_RESULT (parser)->function_name,
- PARSER_RESULT (parser)->source_filename);
- }
- convert_to_sals:
-
- token = linespec_lexer_lex_one (parser);
- if (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD)
- PARSER_STREAM (parser) = LS_TOKEN_STOKEN (token).ptr;
-
- values = convert_linespec_to_sals (PARSER_STATE (parser),
- PARSER_RESULT (parser));
- return values;
- }
- static void
- linespec_state_constructor (struct linespec_state *self,
- int flags, const struct language_defn *language,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical)
- {
- memset (self, 0, sizeof (*self));
- self->language = language;
- self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
- self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
- 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);
- }
- static void
- linespec_parser_new (linespec_parser *parser,
- int flags, const struct language_defn *language,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical)
- {
- parser->lexer.current.type = LSTOKEN_CONSUMED;
- memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
- PARSER_RESULT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
- linespec_state_constructor (PARSER_STATE (parser), flags, language,
- default_symtab, default_line, canonical);
- }
- static void
- linespec_state_destructor (struct linespec_state *self)
- {
- htab_delete (self->addr_set);
- }
- static void
- linespec_parser_delete (void *arg)
- {
- 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);
- if (PARSER_RESULT (parser)->file_symtabs != NULL)
- 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 (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);
- if (PARSER_RESULT (parser)->labels.function_symbols != NULL)
- VEC_free (symbolp, PARSER_RESULT (parser)->labels.function_symbols);
- linespec_state_destructor (PARSER_STATE (parser));
- }
- void
- decode_line_full (char **argptr, int flags,
- struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical,
- const char *select_mode,
- const char *filter)
- {
- struct symtabs_and_lines result;
- struct cleanup *cleanups;
- VEC (const_char_ptr) *filters = NULL;
- linespec_parser parser;
- struct linespec_state *state;
- const char *copy, *orig;
- gdb_assert (canonical != NULL);
-
- gdb_assert (filter == NULL || select_mode == multiple_symbols_all);
- gdb_assert (select_mode == NULL
- || select_mode == multiple_symbols_all
- || select_mode == multiple_symbols_ask
- || select_mode == multiple_symbols_cancel);
- gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
- linespec_parser_new (&parser, flags, current_language, 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;
- state = PARSER_STATE (&parser);
- gdb_assert (result.nelts == 1 || canonical->pre_expanded);
- gdb_assert (canonical->addr_string != NULL);
- canonical->pre_expanded = 1;
-
- if (result.nelts > 0)
- {
- int i;
- make_cleanup (xfree, state->canonical_names);
- for (i = 0; i < result.nelts; ++i)
- {
- gdb_assert (state->canonical_names[i].suffix != NULL);
- make_cleanup (xfree, state->canonical_names[i].suffix);
- }
- }
- if (select_mode == NULL)
- {
- if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
- select_mode = multiple_symbols_all;
- else
- select_mode = multiple_symbols_select_mode ();
- }
- if (select_mode == multiple_symbols_all)
- {
- if (filter != NULL)
- {
- make_cleanup (VEC_cleanup (const_char_ptr), &filters);
- VEC_safe_push (const_char_ptr, filters, filter);
- filter_results (state, &result, filters);
- }
- else
- convert_results_to_lsals (state, &result);
- }
- else
- decode_line_2 (state, &result, select_mode);
- do_cleanups (cleanups);
- }
- struct symtabs_and_lines
- decode_line_1 (char **argptr, int flags,
- 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,
- default_line, NULL);
- cleanups = make_cleanup (linespec_parser_delete, &parser);
- save_current_program_space ();
- orig = copy = *argptr;
- result = parse_linespec (&parser, ©);
- *argptr += copy - orig;
- do_cleanups (cleanups);
- return result;
- }
- struct symtabs_and_lines
- decode_line_with_current_source (char *string, int flags)
- {
- struct symtabs_and_lines sals;
- struct symtab_and_line cursal;
- if (string == 0)
- error (_("Empty line specification."));
-
- cursal = get_current_source_symtab_and_line ();
- sals = decode_line_1 (&string, flags,
- cursal.symtab, cursal.line);
- if (*string)
- error (_("Junk at end of line specification: %s"), string);
- return sals;
- }
- struct symtabs_and_lines
- decode_line_with_last_displayed (char *string, int flags)
- {
- struct symtabs_and_lines sals;
- if (string == 0)
- error (_("Empty line specification."));
- if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&string, flags,
- get_last_displayed_symtab (),
- get_last_displayed_line ());
- else
- sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
- if (*string)
- error (_("Junk at end of line specification: %s"), string);
- return sals;
- }
- static void
- initialize_defaults (struct symtab **default_symtab, int *default_line)
- {
- if (*default_symtab == 0)
- {
-
- struct symtab_and_line cursal =
- get_current_source_symtab_and_line ();
- *default_symtab = cursal.symtab;
- *default_line = cursal.line;
- }
- }
- static CORE_ADDR
- linespec_expression_to_pc (const char **exp_ptr)
- {
- if (current_program_space->executing_startup)
-
- throw_error (NOT_FOUND_ERROR, _("cannot evaluate expressions while "
- "program space is in startup"));
- (*exp_ptr)++;
- return value_as_address (parse_to_comma_and_eval (exp_ptr));
- }
- static struct symtabs_and_lines
- 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;
- 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_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;
- values.sals = NULL;
- new_argptr = find_imps (*argptr, &symbol_names);
- if (VEC_empty (const_char_ptr, symbol_names))
- {
- do_cleanups (cleanup);
- return values;
- }
- add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
- if (!VEC_empty (symbolp, info.result.symbols)
- || !VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
- {
- char *saved_arg;
- saved_arg = alloca (new_argptr - *argptr + 1);
- 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);
- if (self->canonical)
- {
- self->canonical->pre_expanded = 1;
- if (ls->source_filename)
- self->canonical->addr_string
- = xstrprintf ("%s:%s", ls->source_filename, saved_arg);
- else
- self->canonical->addr_string = xstrdup (saved_arg);
- }
- }
- *argptr = new_argptr;
- do_cleanups (cleanup);
- return values;
- }
- struct decode_compound_collector
- {
-
- VEC (symbolp) *symbols;
-
- htab_t unique_syms;
- };
- static int
- collect_one_symbol (struct symbol *sym, void *d)
- {
- struct decode_compound_collector *collector = d;
- void **slot;
- struct type *t;
- if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- return 1;
- t = SYMBOL_TYPE (sym);
- CHECK_TYPEDEF (t);
- if (TYPE_CODE (t) != TYPE_CODE_STRUCT
- && TYPE_CODE (t) != TYPE_CODE_UNION
- && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
- return 1;
- slot = htab_find_slot (collector->unique_syms, sym, INSERT);
- if (!*slot)
- {
- *slot = sym;
- VEC_safe_push (symbolp, collector->symbols, sym);
- }
- return 1;
- }
- static VEC (symbolp) *
- lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs,
- const char *class_name)
- {
- int ix;
- struct symtab *elt;
- struct decode_compound_collector collector;
- struct cleanup *outer;
- struct cleanup *cleanup;
- collector.symbols = NULL;
- outer = make_cleanup (VEC_cleanup (symbolp), &collector.symbols);
- collector.unique_syms = htab_create_alloc (1, htab_hash_pointer,
- htab_eq_pointer, NULL,
- xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (collector.unique_syms);
- for (ix = 0; VEC_iterate (symtab_ptr, file_symtabs, ix, elt); ++ix)
- {
- if (elt == NULL)
- {
- iterate_over_all_matching_symtabs (state, class_name, STRUCT_DOMAIN,
- collect_one_symbol, &collector,
- NULL, 0);
- iterate_over_all_matching_symtabs (state, class_name, VAR_DOMAIN,
- collect_one_symbol, &collector,
- NULL, 0);
- }
- else
- {
-
- gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
- set_current_program_space (SYMTAB_PSPACE (elt));
- 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);
- }
- }
- do_cleanups (cleanup);
- discard_cleanups (outer);
- return collector.symbols;
- }
- static int
- compare_symbols (const void *a, const void *b)
- {
- struct symbol * const *sa = a;
- struct symbol * const *sb = b;
- uintptr_t uia, uib;
- uia = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sa));
- uib = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sb));
- if (uia < uib)
- return -1;
- if (uia > uib)
- return 1;
- uia = (uintptr_t) *sa;
- uib = (uintptr_t) *sb;
- if (uia < uib)
- return -1;
- if (uia > uib)
- return 1;
- return 0;
- }
- static int
- compare_msymbols (const void *a, const void *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;
- uib = (uintptr_t) sa->objfile->pspace;
- if (uia < uib)
- return -1;
- if (uia > uib)
- return 1;
- uia = (uintptr_t) sa->minsym;
- uib = (uintptr_t) sb->minsym;
- if (uia < uib)
- return -1;
- if (uia > uib)
- return 1;
- return 0;
- }
- static void
- add_all_symbol_names_from_pspace (struct collect_info *info,
- struct program_space *pspace,
- VEC (const_char_ptr) *names)
- {
- int ix;
- const char *iter;
- for (ix = 0; VEC_iterate (const_char_ptr, names, ix, iter); ++ix)
- add_matching_symbols_to_info (iter, info, pspace);
- }
- static void
- find_superclass_methods (VEC (typep) *superclasses,
- const char *name,
- VEC (const_char_ptr) **result_names)
- {
- int old_len = VEC_length (const_char_ptr, *result_names);
- VEC (typep) *iter_classes;
- struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
- iter_classes = superclasses;
- while (1)
- {
- VEC (typep) *new_supers = NULL;
- int ix;
- struct type *t;
- make_cleanup (VEC_cleanup (typep), &new_supers);
- for (ix = 0; VEC_iterate (typep, iter_classes, ix, t); ++ix)
- find_methods (t, name, result_names, &new_supers);
- if (VEC_length (const_char_ptr, *result_names) != old_len
- || VEC_empty (typep, new_supers))
- break;
- iter_classes = new_supers;
- }
- do_cleanups (cleanup);
- }
- static void
- 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 (bound_minimal_symbol_d) **minsyms)
- {
- struct symbol *sym;
- struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
- int ix;
- int last_result_len;
- VEC (typep) *superclass_vec;
- VEC (const_char_ptr) *result_names;
- struct collect_info info;
-
- qsort (VEC_address (symbolp, sym_classes),
- VEC_length (symbolp, sym_classes),
- sizeof (symbolp),
- compare_symbols);
- info.state = self;
- info.file_symtabs = file_symtabs;
- info.result.symbols = NULL;
- info.result.minimal_symbols = NULL;
-
- superclass_vec = NULL;
- make_cleanup (VEC_cleanup (typep), &superclass_vec);
- result_names = NULL;
- make_cleanup (VEC_cleanup (const_char_ptr), &result_names);
- last_result_len = 0;
- for (ix = 0; VEC_iterate (symbolp, sym_classes, ix, sym); ++ix)
- {
- struct type *t;
- struct program_space *pspace;
-
- 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);
-
- if (ix == VEC_length (symbolp, sym_classes) - 1
- || (pspace
- != SYMTAB_PSPACE (symbol_symtab (VEC_index (symbolp, sym_classes,
- ix + 1)))))
- {
-
- if (VEC_length (const_char_ptr, result_names) == last_result_len)
- find_superclass_methods (superclass_vec, method_name,
- &result_names);
-
- add_all_symbol_names_from_pspace (&info, pspace, result_names);
- VEC_truncate (typep, superclass_vec, 0);
- last_result_len = VEC_length (const_char_ptr, result_names);
- }
- }
- if (!VEC_empty (symbolp, info.result.symbols)
- || !VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
- {
- *symbols = info.result.symbols;
- *minsyms = info.result.minimal_symbols;
- do_cleanups (cleanup);
- return;
- }
-
- throw_error (NOT_FOUND_ERROR, _("see caller, this text doesn't matter"));
- }
- struct symtab_collector
- {
-
- VEC (symtab_ptr) *symtabs;
-
- htab_t symtab_table;
- };
- static int
- add_symtabs_to_list (struct symtab *symtab, void *d)
- {
- struct symtab_collector *data = d;
- void **slot;
- slot = htab_find_slot (data->symtab_table, symtab, INSERT);
- if (!*slot)
- {
- *slot = symtab;
- VEC_safe_push (symtab_ptr, data->symtabs, symtab);
- }
- return 0;
- }
- static VEC (symtab_ptr) *
- collect_symtabs_from_filename (const char *file)
- {
- struct symtab_collector collector;
- struct cleanup *cleanups;
- struct program_space *pspace;
- collector.symtabs = NULL;
- collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
- NULL);
- cleanups = make_cleanup_htab_delete (collector.symtab_table);
-
- ALL_PSPACES (pspace)
- {
- if (pspace->executing_startup)
- continue;
- set_current_program_space (pspace);
- iterate_over_symtabs (file, add_symtabs_to_list, &collector);
- }
- do_cleanups (cleanups);
- return collector.symtabs;
- }
- static VEC (symtab_ptr) *
- symtabs_from_filename (const char *filename)
- {
- VEC (symtab_ptr) *result;
- result = collect_symtabs_from_filename (filename);
- if (VEC_empty (symtab_ptr, result))
- {
- if (!have_full_symbols () && !have_partial_symbols ())
- 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);
- }
- return result;
- }
- static void
- find_function_symbols (struct linespec_state *state,
- VEC (symtab_ptr) *file_symtabs, const char *name,
- VEC (symbolp) **symbols,
- VEC (bound_minimal_symbol_d) **minsyms)
- {
- struct collect_info info;
- VEC (const_char_ptr) *symbol_names = NULL;
- struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr),
- &symbol_names);
- info.state = state;
- info.result.symbols = NULL;
- info.result.minimal_symbols = NULL;
- info.file_symtabs = file_symtabs;
-
- find_imps (name, &symbol_names);
- if (!VEC_empty (const_char_ptr, symbol_names))
- add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
- else
- add_matching_symbols_to_info (name, &info, NULL);
- do_cleanups (cleanup);
- if (VEC_empty (symbolp, info.result.symbols))
- {
- VEC_free (symbolp, info.result.symbols);
- *symbols = NULL;
- }
- else
- *symbols = info.result.symbols;
- if (VEC_empty (bound_minimal_symbol_d, info.result.minimal_symbols))
- {
- VEC_free (bound_minimal_symbol_d, info.result.minimal_symbols);
- *minsyms = NULL;
- }
- else
- *minsyms = info.result.minimal_symbols;
- }
- static void
- find_linespec_symbols (struct linespec_state *state,
- VEC (symtab_ptr) *file_symtabs,
- const char *name,
- VEC (symbolp) **symbols,
- VEC (bound_minimal_symbol_d) **minsyms)
- {
- 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);
- if (state->language->la_language == language_ada)
- {
-
- lookup_name = ada_name_for_lookup (name);
- make_cleanup (xfree, (void *) lookup_name);
- }
- canon = cp_canonicalize_string_no_typedefs (lookup_name);
- if (canon != NULL)
- {
- lookup_name = canon;
- make_cleanup (xfree, canon);
- }
-
- find_function_symbols (state, file_symtabs, lookup_name,
- symbols, minsyms);
-
- if (VEC_empty (symbolp, *symbols)
- && VEC_empty (bound_minimal_symbol_d, *minsyms))
- {
- char *klass, *method;
- const char *last, *p, *scope_op;
- VEC (symbolp) *classes;
-
- scope_op = "::";
- p = find_toplevel_string (lookup_name, scope_op);
- if (p == NULL)
- {
-
- 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 (last == NULL)
- {
- do_cleanups (cleanup);
- return;
- }
-
- klass = xmalloc ((last - lookup_name + 1) * sizeof (char));
- make_cleanup (xfree, klass);
- strncpy (klass, lookup_name, last - lookup_name);
- klass[last - lookup_name] = '\0';
-
- last += strlen (scope_op);
- method = xmalloc ((strlen (last) + 1) * sizeof (char));
- make_cleanup (xfree, method);
- strcpy (method, last);
-
- classes = lookup_prefix_sym (state, file_symtabs, klass);
- make_cleanup (VEC_cleanup (symbolp), &classes);
- if (!VEC_empty (symbolp, classes))
- {
-
- TRY_CATCH (except, RETURN_MASK_ERROR)
- {
- find_method (state, file_symtabs, klass, method, classes,
- symbols, minsyms);
- }
-
- if (except.reason < 0 && except.error != NOT_FOUND_ERROR)
- throw_exception (except);
- }
- }
- do_cleanups (cleanup);
- }
- static VEC (symbolp) *
- find_label_symbols (struct linespec_state *self,
- VEC (symbolp) *function_symbols,
- VEC (symbolp) **label_funcs_ret, const char *name)
- {
- int ix;
- const struct block *block;
- struct symbol *sym;
- struct symbol *fn_sym;
- VEC (symbolp) *result = NULL;
- if (function_symbols == NULL)
- {
- set_current_program_space (self->program_space);
- block = get_current_search_block ();
- for (;
- block && !BLOCK_FUNCTION (block);
- block = BLOCK_SUPERBLOCK (block))
- ;
- if (!block)
- return NULL;
- fn_sym = BLOCK_FUNCTION (block);
- sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
- if (sym != NULL)
- {
- VEC_safe_push (symbolp, result, sym);
- VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
- }
- }
- else
- {
- for (ix = 0;
- VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
- {
- set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym)));
- block = SYMBOL_BLOCK_VALUE (fn_sym);
- sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
- if (sym != NULL)
- {
- VEC_safe_push (symbolp, result, sym);
- VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
- }
- }
- }
- return result;
- }
- static void
- decode_digits_list_mode (struct linespec_state *self,
- linespec_p ls,
- struct symtabs_and_lines *values,
- struct symtab_and_line val)
- {
- int ix;
- struct symtab *elt;
- gdb_assert (self->list_mode);
- for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt);
- ++ix)
- {
-
- gdb_assert (elt != NULL);
- set_current_program_space (SYMTAB_PSPACE (elt));
-
- val.symtab = find_line_symtab (elt, val.line, NULL, NULL);
- if (val.symtab == NULL)
- val.symtab = elt;
- val.pspace = SYMTAB_PSPACE (elt);
- val.pc = 0;
- val.explicit_line = 1;
- add_sal_to_sals (self, values, &val, NULL, 0);
- }
- }
- static void
- decode_digits_ordinary (struct linespec_state *self,
- linespec_p ls,
- int line,
- struct symtabs_and_lines *sals,
- struct linetable_entry **best_entry)
- {
- int ix;
- struct symtab *elt;
- for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt); ++ix)
- {
- int i;
- VEC (CORE_ADDR) *pcs;
- CORE_ADDR pc;
-
- gdb_assert (elt != NULL);
- set_current_program_space (SYMTAB_PSPACE (elt));
- pcs = find_pcs_for_symtab_line (elt, line, best_entry);
- for (i = 0; VEC_iterate (CORE_ADDR, pcs, i, pc); ++i)
- {
- struct symtab_and_line sal;
- init_sal (&sal);
- sal.pspace = SYMTAB_PSPACE (elt);
- sal.symtab = elt;
- sal.line = line;
- sal.pc = pc;
- add_sal_to_sals_basic (sals, &sal);
- }
- VEC_free (CORE_ADDR, pcs);
- }
- }
- static struct line_offset
- linespec_parse_variable (struct linespec_state *self, const char *variable)
- {
- int index = 0;
- const char *p;
- struct line_offset offset = {0, LINE_OFFSET_NONE};
- p = (variable[1] == '$') ? variable + 2 : variable + 1;
- if (*p == '$')
- ++p;
- while (*p >= '0' && *p <= '9')
- ++p;
- if (!*p)
- {
-
- struct value *val_history;
- sscanf ((variable[1] == '$') ? variable + 2 : variable + 1, "%d", &index);
- val_history
- = access_value_history ((variable[1] == '$') ? -index : index);
- if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
- error (_("History values used in line "
- "specs must have integer values."));
- offset.offset = value_as_long (val_history);
- }
- else
- {
-
- LONGEST valx;
- struct internalvar *ivar;
-
- ivar = lookup_only_internalvar (variable + 1);
- if (ivar == NULL)
-
- offset.sign = LINE_OFFSET_UNKNOWN;
- else
- {
-
- if (!get_internalvar_integer (ivar, &valx))
- error (_("Convenience variables used in line "
- "specs must have integer values."));
- else
- offset.offset = valx;
- }
- }
- return offset;
- }
- static int
- collect_symbols (struct symbol *sym, void *data)
- {
- struct collect_info *info = data;
-
- if (SYMBOL_CLASS (sym) == LOC_BLOCK || info->state->list_mode)
- VEC_safe_push (symbolp, info->result.symbols, sym);
- return 1;
- }
- static void
- minsym_found (struct linespec_state *self, struct objfile *objfile,
- struct minimal_symbol *msymbol,
- struct symtabs_and_lines *result)
- {
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc;
- struct symtab_and_line sal;
- sal = find_pc_sect_line (MSYMBOL_VALUE_ADDRESS (objfile, msymbol),
- (struct obj_section *) 0, 0);
- sal.section = MSYMBOL_OBJ_SECTION (objfile, msymbol);
-
- 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 (self->funfirstline)
- 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);
- }
- struct collect_minsyms
- {
-
- struct objfile *objfile;
-
- struct symtab *symtab;
-
- int funfirstline;
-
- int list_mode;
-
- VEC (bound_minimal_symbol_d) *msyms;
- };
- static int
- classify_mtype (enum minimal_symbol_type t)
- {
- switch (t)
- {
- case mst_file_text:
- case mst_file_data:
- case mst_file_bss:
-
- return 1;
- case mst_solib_trampoline:
-
- return 2;
- default:
-
- return 0;
- }
- }
- static int
- compare_msyms (const void *a, const void *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);
- return classify_mtype (ta) - classify_mtype (tb);
- }
- static void
- add_minsym (struct minimal_symbol *minsym, void *d)
- {
- struct collect_minsyms *info = 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;
- }
-
- if (!info->list_mode)
- switch (minsym->type)
- {
- case mst_slot_got_plt:
- case mst_data:
- case mst_bss:
- case mst_abs:
- case mst_file_data:
- case mst_file_bss:
- {
-
- struct gdbarch *gdbarch = get_objfile_arch (info->objfile);
- CORE_ADDR addr = gdbarch_convert_from_func_ptr_addr
- (gdbarch, BMSYMBOL_VALUE_ADDRESS (mo),
- ¤t_target);
- if (addr == BMSYMBOL_VALUE_ADDRESS (mo))
- return;
- }
- }
- VEC_safe_push (bound_minimal_symbol_d, info->msyms, &mo);
- }
- static void
- search_minsyms_for_name (struct collect_info *info, const char *name,
- struct program_space *search_pspace,
- struct symtab *symtab)
- {
- 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;
- cleanup = make_cleanup (VEC_cleanup (bound_minimal_symbol_d), &local.msyms);
- if (symtab == NULL)
- {
- struct program_space *pspace;
- ALL_PSPACES (pspace)
- {
- struct objfile *objfile;
- if (search_pspace != NULL && search_pspace != pspace)
- continue;
- if (pspace->executing_startup)
- continue;
- set_current_program_space (pspace);
- ALL_OBJFILES (objfile)
- {
- local.objfile = objfile;
- iterate_over_minimal_symbols (objfile, name, add_minsym, &local);
- }
- }
- }
- else
- {
- 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))
- {
- int classification;
- int ix;
- bound_minimal_symbol_d *item;
- qsort (VEC_address (bound_minimal_symbol_d, local.msyms),
- VEC_length (bound_minimal_symbol_d, local.msyms),
- sizeof (bound_minimal_symbol_d),
- compare_msyms);
-
- item = VEC_index (bound_minimal_symbol_d, local.msyms, 0);
- classification = classify_mtype (MSYMBOL_TYPE (item->minsym));
- for (ix = 0;
- VEC_iterate (bound_minimal_symbol_d, local.msyms, ix, item);
- ++ix)
- {
- if (classify_mtype (MSYMBOL_TYPE (item->minsym)) != classification)
- break;
- VEC_safe_push (bound_minimal_symbol_d,
- info->result.minimal_symbols, item);
- }
- }
- do_cleanups (cleanup);
- }
- static void
- add_matching_symbols_to_info (const char *name,
- struct collect_info *info,
- struct program_space *pspace)
- {
- int ix;
- struct symtab *elt;
- for (ix = 0; VEC_iterate (symtab_ptr, info->file_symtabs, ix, elt); ++ix)
- {
- if (elt == NULL)
- {
- iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN,
- collect_symbols, info,
- pspace, 1);
- 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);
-
- 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 (prev_len == VEC_length (symbolp, info->result.symbols)
- && elt->language == language_asm)
- search_minsyms_for_name (info, name, pspace, elt);
- }
- }
- }
- static int
- symbol_to_sal (struct symtab_and_line *result,
- int funfirstline, struct symbol *sym)
- {
- if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- *result = find_function_start_sal (sym, funfirstline);
- return 1;
- }
- else
- {
- if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
- {
- init_sal (result);
- result->symtab = symbol_symtab (sym);
- result->line = SYMBOL_LINE (sym);
- result->pc = SYMBOL_VALUE_ADDRESS (sym);
- result->pspace = SYMTAB_PSPACE (result->symtab);
- result->explicit_pc = 1;
- return 1;
- }
- else if (funfirstline)
- {
-
- }
- else if (SYMBOL_LINE (sym) != 0)
- {
-
- init_sal (result);
- result->symtab = symbol_symtab (sym);
- result->line = SYMBOL_LINE (sym);
- result->pspace = SYMTAB_PSPACE (result->symtab);
- return 1;
- }
- }
- return 0;
- }
- void
- init_linespec_result (struct linespec_result *lr)
- {
- memset (lr, 0, sizeof (*lr));
- }
- void
- destroy_linespec_result (struct linespec_result *ls)
- {
- int i;
- struct linespec_sals *lsal;
- xfree (ls->addr_string);
- for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
- {
- xfree (lsal->canonical);
- xfree (lsal->sals.sals);
- }
- VEC_free (linespec_sals, ls->sals);
- }
- static void
- cleanup_linespec_result (void *a)
- {
- destroy_linespec_result (a);
- }
- struct cleanup *
- make_cleanup_destroy_linespec_result (struct linespec_result *ls)
- {
- return make_cleanup (cleanup_linespec_result, ls);
- }