const char *name,
const domain_enum domain);
-static void print_symbol_info (domain_enum,
- struct symtab *, struct symbol *, int, char *);
-
static void print_msymbol_info (struct minimal_symbol *);
-static void symtab_symbol_info (char *, domain_enum, int);
-
void _initialize_symtab (void);
/* */
struct objfile *objfile;
char *real_path = NULL;
char *full_path = NULL;
+ struct cleanup *cleanup;
+
+ cleanup = make_cleanup (null_cleanup, NULL);
/* Here we are interested in canonicalizing an absolute path, not
absolutizing a relative path. */
{
if (FILENAME_CMP (name, s->filename) == 0)
{
+ do_cleanups (cleanup);
return s;
}
if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
{
+ do_cleanups (cleanup);
return s;
}
}
make_cleanup (xfree, rp);
if (FILENAME_CMP (real_path, rp) == 0)
{
+ do_cleanups (cleanup);
return s;
}
}
ALL_SYMTABS (objfile, s)
{
if (FILENAME_CMP (lbasename (s->filename), name) == 0)
- return s;
+ {
+ do_cleanups (cleanup);
+ return s;
+ }
}
/* Same search rules as above apply here, but now we look thru the
}
if (s != NULL)
- return s;
+ {
+ do_cleanups (cleanup);
+ return s;
+ }
if (!found)
- return NULL;
+ {
+ do_cleanups (cleanup);
+ return NULL;
+ }
/* At this point, we have located the psymtab for this file, but
the conversion to a symtab has failed. This usually happens
PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has
been created. So, we need to run through the symtabs again in
order to find the file.
- XXX - This is a crock, and should be fixed inside of the the
+ XXX - This is a crock, and should be fixed inside of the
symbol parsing routines. */
goto got_symtab;
}
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id);
struct fn_field *method = &f[signature_id];
char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
- char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
+ const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
char *newname = type_name_no_tag (type);
/* Does the form of physname indicate that it is the full mangled name
}
}
- if (case_sensitivity == case_sensitive_off)
- {
- char *copy;
- int len, i;
-
- len = strlen (name);
- copy = (char *) alloca (len + 1);
- for (i= 0; i < len; i++)
- copy[i] = tolower (name[i]);
- copy[len] = 0;
- modified_name = copy;
- }
-
returnval = lookup_symbol_aux (modified_name, block, domain, lang,
is_a_field_of_this);
do_cleanups (cleanup);
struct blockvector *bv;
struct minimal_symbol *msymbol;
struct minimal_symbol *mfunsym;
+ struct objfile *objfile;
/* Info on best line seen so far, and where it starts, and its file. */
}
bv = BLOCKVECTOR (s);
+ objfile = s->objfile;
/* Look at all the symtabs that share this blockvector.
They all have the same apriori range, that we found was right;
but they have different line tables. */
- for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+ ALL_OBJFILE_SYMTABS (objfile, s)
{
+ if (BLOCKVECTOR (s) != bv)
+ continue;
+
/* Find the best line in this symtab. */
l = LINETABLE (s);
if (!l)
struct symbol *sym;
struct symtab_and_line start_sal;
struct cleanup *old_chain;
- CORE_ADDR pc;
+ CORE_ADDR pc, saved_pc;
struct obj_section *section;
const char *name;
struct objfile *objfile;
struct gdbarch *gdbarch;
struct block *b, *function_block;
+ int force_skip, skip;
/* Do not change the SAL is PC was specified explicitly. */
if (sal->explicit_pc)
gdbarch = get_objfile_arch (objfile);
- /* If the function is in an unmapped overlay, use its unmapped LMA address,
- so that gdbarch_skip_prologue has something unique to work on. */
- if (section_is_overlay (section) && !section_is_mapped (section))
- pc = overlay_unmapped_address (pc, section);
-
- /* Skip "first line" of function (which is actually its prologue). */
- pc += gdbarch_deprecated_function_start_offset (gdbarch);
- pc = gdbarch_skip_prologue (gdbarch, pc);
+ /* Process the prologue in two passes. In the first pass try to skip the
+ prologue (SKIP is true) and verify there is a real need for it (indicated
+ by FORCE_SKIP). If no such reason was found run a second pass where the
+ prologue is not skipped (SKIP is false). */
- /* For overlays, map pc back into its mapped VMA range. */
- pc = overlay_mapped_address (pc, section);
+ skip = 1;
+ force_skip = 1;
- /* Calculate line number. */
- start_sal = find_pc_sect_line (pc, section, 0);
+ /* Be conservative - allow direct PC (without skipping prologue) only if we
+ have proven the CU (Compilation Unit) supports it. sal->SYMTAB does not
+ have to be set by the caller so we use SYM instead. */
+ if (sym && SYMBOL_SYMTAB (sym)->locations_valid)
+ force_skip = 0;
- /* Check if gdbarch_skip_prologue left us in mid-line, and the next
- line is still part of the same function. */
- if (start_sal.pc != pc
- && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
- && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
- : (lookup_minimal_symbol_by_pc_section (start_sal.end, section)
- == lookup_minimal_symbol_by_pc_section (pc, section))))
+ saved_pc = pc;
+ do
{
- /* First pc of next line */
- pc = start_sal.end;
- /* Recalculate the line number (might not be N+1). */
- start_sal = find_pc_sect_line (pc, section, 0);
- }
+ pc = saved_pc;
- /* On targets with executable formats that don't have a concept of
- constructors (ELF with .init has, PE doesn't), gcc emits a call
- to `__main' in `main' between the prologue and before user
- code. */
- if (gdbarch_skip_main_prologue_p (gdbarch)
- && name && strcmp (name, "main") == 0)
- {
- pc = gdbarch_skip_main_prologue (gdbarch, pc);
- /* Recalculate the line number (might not be N+1). */
+ /* If the function is in an unmapped overlay, use its unmapped LMA address,
+ so that gdbarch_skip_prologue has something unique to work on. */
+ if (section_is_overlay (section) && !section_is_mapped (section))
+ pc = overlay_unmapped_address (pc, section);
+
+ /* Skip "first line" of function (which is actually its prologue). */
+ pc += gdbarch_deprecated_function_start_offset (gdbarch);
+ if (skip)
+ pc = gdbarch_skip_prologue (gdbarch, pc);
+
+ /* For overlays, map pc back into its mapped VMA range. */
+ pc = overlay_mapped_address (pc, section);
+
+ /* Calculate line number. */
start_sal = find_pc_sect_line (pc, section, 0);
+
+ /* Check if gdbarch_skip_prologue left us in mid-line, and the next
+ line is still part of the same function. */
+ if (skip && start_sal.pc != pc
+ && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
+ && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+ : (lookup_minimal_symbol_by_pc_section (start_sal.end, section)
+ == lookup_minimal_symbol_by_pc_section (pc, section))))
+ {
+ /* First pc of next line */
+ pc = start_sal.end;
+ /* Recalculate the line number (might not be N+1). */
+ start_sal = find_pc_sect_line (pc, section, 0);
+ }
+
+ /* On targets with executable formats that don't have a concept of
+ constructors (ELF with .init has, PE doesn't), gcc emits a call
+ to `__main' in `main' between the prologue and before user
+ code. */
+ if (gdbarch_skip_main_prologue_p (gdbarch)
+ && name && strcmp (name, "main") == 0)
+ {
+ pc = gdbarch_skip_main_prologue (gdbarch, pc);
+ /* Recalculate the line number (might not be N+1). */
+ start_sal = find_pc_sect_line (pc, section, 0);
+ force_skip = 1;
+ }
}
+ while (!force_skip && skip--);
/* If we still don't have a valid source line, try to find the first
PC in the lineinfo table that belongs to the same function. This
the case with the DJGPP target using "gcc -gcoff" when the
compiler inserted code after the prologue to make sure the stack
is aligned. */
- if (sym && start_sal.symtab == NULL)
+ if (!force_skip && sym && start_sal.symtab == NULL)
{
pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym));
/* Recalculate the line number. */
/* Is FILE in tab? */
for (p = tab; p < tab + tab_cur_size; p++)
- if (strcmp (*p, file) == 0)
+ if (filename_cmp (*p, file) == 0)
return 1;
/* No; maybe add it to tab. */
{
for (i = 0; i < nfiles; i++)
{
- if (strcmp (files[i], lbasename (file)) == 0)
+ if (filename_cmp (files[i], lbasename (file)) == 0)
return 1;
}
}
{
int nfiles;
char **files;
- char *regexp;
+
+ /* It is true if PREG contains valid data, false otherwise. */
+ unsigned preg_p : 1;
+ regex_t preg;
};
/* A callback for expand_symtabs_matching. */
{
struct search_symbols_data *data = user_data;
- return data->regexp == NULL || re_exec (symname);
+ return !data->preg_p || regexec (&data->preg, symname, 0, NULL, 0) == 0;
}
/* Search the symbol table for matches to the regular expression REGEXP,
returning the results in *MATCHES.
Only symbols of KIND are searched:
+ VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
+ and constants (enums)
FUNCTIONS_DOMAIN - search all functions
TYPES_DOMAIN - search all type names
- VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
- and constants (enums)
+ ALL_DOMAIN - an internal error for this function
free_search_symbols should be called when *MATCHES is no longer needed.
separately alphabetized. */
void
-search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
+search_symbols (char *regexp, enum search_domain kind,
+ int nfiles, char *files[],
struct symbol_search **matches)
{
struct symtab *s;
char *val;
int found_misc = 0;
static const enum minimal_symbol_type types[]
- = {mst_data, mst_text, mst_abs, mst_unknown};
+ = {mst_data, mst_text, mst_abs};
static const enum minimal_symbol_type types2[]
- = {mst_bss, mst_file_text, mst_abs, mst_unknown};
+ = {mst_bss, mst_file_text, mst_abs};
static const enum minimal_symbol_type types3[]
- = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
+ = {mst_file_data, mst_solib_trampoline, mst_abs};
static const enum minimal_symbol_type types4[]
- = {mst_file_bss, mst_text, mst_abs, mst_unknown};
+ = {mst_file_bss, mst_text_gnu_ifunc, mst_abs};
enum minimal_symbol_type ourtype;
enum minimal_symbol_type ourtype2;
enum minimal_symbol_type ourtype3;
struct symbol_search *sr;
struct symbol_search *psr;
struct symbol_search *tail;
- struct cleanup *old_chain = NULL;
struct search_symbols_data datum;
- if (kind < VARIABLES_DOMAIN)
- error (_("must search on specific domain"));
+ /* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current
+ CLEANUP_CHAIN is freed only in the case of an error. */
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+ struct cleanup *retval_chain;
+
+ gdb_assert (kind <= TYPES_DOMAIN);
- ourtype = types[(int) (kind - VARIABLES_DOMAIN)];
- ourtype2 = types2[(int) (kind - VARIABLES_DOMAIN)];
- ourtype3 = types3[(int) (kind - VARIABLES_DOMAIN)];
- ourtype4 = types4[(int) (kind - VARIABLES_DOMAIN)];
+ ourtype = types[kind];
+ ourtype2 = types2[kind];
+ ourtype3 = types3[kind];
+ ourtype4 = types4[kind];
sr = *matches = NULL;
tail = NULL;
+ datum.preg_p = 0;
if (regexp != NULL)
{
and <TYPENAME> or <OPERATOR>. */
char *opend;
char *opname = operator_chars (regexp, &opend);
+ int errcode;
if (*opname)
{
}
}
- if (0 != (val = re_comp (regexp)))
- error (_("Invalid regexp (%s): %s"), val, regexp);
+ errcode = regcomp (&datum.preg, regexp,
+ REG_NOSUB | (case_sensitivity == case_sensitive_off
+ ? REG_ICASE : 0));
+ if (errcode != 0)
+ {
+ char *err = get_regcomp_error (errcode, &datum.preg);
+
+ make_cleanup (xfree, err);
+ error (_("Invalid regexp (%s): %s"), err, regexp);
+ }
+ datum.preg_p = 1;
+ make_regfree_cleanup (&datum.preg);
}
/* Search through the partial symtabs *first* for all symbols
datum.nfiles = nfiles;
datum.files = files;
- datum.regexp = regexp;
ALL_OBJFILES (objfile)
{
if (objfile->sf)
&datum);
}
+ retval_chain = old_chain;
+
/* Here, we search through the minimal symbol tables for functions
and variables that match, and force their symbols to be read.
This is in particular necessary for demangled variable names,
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (regexp == NULL
- || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
+ if (!datum.preg_p
+ || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
{
QUIT;
if (file_matches (real_symtab->filename, files, nfiles)
- && ((regexp == NULL
- || re_exec (SYMBOL_NATURAL_NAME (sym)) != 0)
+ && ((!datum.preg_p
+ || regexec (&datum.preg, SYMBOL_NATURAL_NAME (sym), 0,
+ NULL, 0) == 0)
&& ((kind == VARIABLES_DOMAIN
&& SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_UNRESOLVED
tail = sort_search_symbols (&dummy, nfound);
sr = dummy.next;
- old_chain = make_cleanup_free_search_symbols (sr);
+ make_cleanup_free_search_symbols (sr);
}
else
tail = sort_search_symbols (prevtail, nfound);
MSYMBOL_TYPE (msymbol) == ourtype3 ||
MSYMBOL_TYPE (msymbol) == ourtype4)
{
- if (regexp == NULL
- || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0)
+ if (!datum.preg_p
+ || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
+ NULL, 0) == 0)
{
/* Functions: Look up by address. */
if (kind != FUNCTIONS_DOMAIN ||
if (tail == NULL)
{
sr = psr;
- old_chain = make_cleanup_free_search_symbols (sr);
+ make_cleanup_free_search_symbols (sr);
}
else
tail->next = psr;
}
}
+ discard_cleanups (retval_chain);
+ do_cleanups (old_chain);
*matches = sr;
- if (sr != NULL)
- discard_cleanups (old_chain);
}
/* Helper function for symtab_symbol_info, this function uses
regarding the match to gdb_stdout. */
static void
-print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym,
+print_symbol_info (enum search_domain kind,
+ struct symtab *s, struct symbol *sym,
int block, char *last)
{
- if (last == NULL || strcmp (last, s->filename) != 0)
+ if (last == NULL || filename_cmp (last, s->filename) != 0)
{
fputs_filtered ("\nFile ", gdb_stdout);
fputs_filtered (s->filename, gdb_stdout);
matches. */
static void
-symtab_symbol_info (char *regexp, domain_enum kind, int from_tty)
+symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
{
static const char * const classnames[] =
- {"variable", "function", "type", "method"};
+ {"variable", "function", "type"};
struct symbol_search *symbols;
struct symbol_search *p;
struct cleanup *old_chain;
char *last_filename = NULL;
int first = 1;
+ gdb_assert (kind <= TYPES_DOMAIN);
+
/* Must make sure that if we're interrupted, symbols gets freed. */
search_symbols (regexp, kind, 0, (char **) NULL, &symbols);
old_chain = make_cleanup_free_search_symbols (symbols);
printf_filtered (regexp
? "All %ss matching regular expression \"%s\":\n"
: "All defined %ss:\n",
- classnames[(int) (kind - VARIABLES_DOMAIN)], regexp);
+ classnames[kind], regexp);
for (p = symbols; p != NULL; p = p->next)
{
struct cleanup *old_chain;
char *string = NULL;
int len = 0;
- char **files = NULL;
+ char **files = NULL, *file_name;
int nfiles = 0;
if (regexp)
if (colon && *(colon + 1) != ':')
{
int colon_index;
- char * file_name;
colon_index = colon - regexp;
file_name = alloca (colon_index + 1);
}
\f
+/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN.
+
+ Either sym_text[sym_text_len] != '(' and then we search for any
+ symbol starting with SYM_TEXT text.
+
+ Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to
+ be terminated at that point. Partial symbol tables do not have parameters
+ information. */
+
+static int
+compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
+{
+ int (*ncmp) (const char *, const char *, size_t);
+
+ ncmp = (case_sensitivity == case_sensitive_on ? strncmp : strncasecmp);
+
+ if (ncmp (name, sym_text, sym_text_len) != 0)
+ return 0;
+
+ if (sym_text[sym_text_len] == '(')
+ {
+ /* User searches for `name(someth...'. Require NAME to be terminated.
+ Normally psymtabs and gdbindex have no parameter types so '\0' will be
+ present but accept even parameters presence. In this case this
+ function is in fact strcmp_iw but whitespace skipping is not supported
+ for tab completion. */
+
+ if (name[sym_text_len] != '\0' && name[sym_text_len] != '(')
+ return 0;
+ }
+
+ return 1;
+}
+
/* Helper routine for make_symbol_completion_list. */
static int return_val_size;
int newsize;
/* Clip symbols that cannot match. */
-
- if (strncmp (symname, sym_text, sym_text_len) != 0)
- {
- return;
- }
+ if (!compare_symbol_name (symname, sym_text, sym_text_len))
+ return;
/* We have a match for a completion, so add SYMNAME to the current list
of matches. Note that the name is moved to freshly malloc'd space. */
}
/* Type of the user_data argument passed to add_macro_name or
- add_partial_symbol_name. The contents are simply whatever is
+ expand_partial_symbol_name. The contents are simply whatever is
needed by completion_list_add_name. */
struct add_name_data
{
datum->text, datum->word);
}
-/* A callback for map_partial_symbol_names. */
-static void
-add_partial_symbol_name (const char *name, void *user_data)
+/* A callback for expand_partial_symbol_names. */
+static int
+expand_partial_symbol_name (const char *name, void *user_data)
{
struct add_name_data *datum = (struct add_name_data *) user_data;
- completion_list_add_name ((char *) name,
- datum->sym_text, datum->sym_text_len,
- datum->text, datum->word);
+ return compare_symbol_name (name, datum->sym_text, datum->sym_text_len);
}
char **
sym_text_len = strlen (sym_text);
+ /* Prepare SYM_TEXT_LEN for compare_symbol_name. */
+
+ if (current_language->la_language == language_cplus
+ || current_language->la_language == language_java
+ || current_language->la_language == language_fortran)
+ {
+ /* These languages may have parameters entered by user but they are never
+ present in the partial symbol tables. */
+
+ const char *cs = memchr (sym_text, '(', sym_text_len);
+
+ if (cs)
+ sym_text_len = cs - sym_text;
+ }
+ gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
+
return_val_size = 100;
return_val_index = 0;
return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
datum.word = word;
/* Look through the partial symtabs for all symbols which begin
- by matching SYM_TEXT. Add each one that you find to the list. */
- map_partial_symbol_names (add_partial_symbol_name, &datum);
+ by matching SYM_TEXT. Expand all CUs that you find to the list.
+ The real names will get added by COMPLETION_LIST_ADD_SYMBOL below. */
+ expand_partial_symbol_names (expand_partial_symbol_name, &datum);
/* At this point scan through the misc symbol vectors and add each
symbol you find to the list. Eventually we want to ignore
for (i = 0; illegal_aliens[i]; i++)
{
- if (strcmp (fname, illegal_aliens[i]) == 0)
+ if (filename_cmp (fname, illegal_aliens[i]) == 0)
return 1;
}
return 0;
if (not_interesting_fname (filename))
return;
if (!filename_seen (filename, 1, data->first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
- && strncasecmp (filename, data->text, data->text_len) == 0
-#else
- && strncmp (filename, data->text, data->text_len) == 0
-#endif
- )
+ && filename_ncmp (filename, data->text, data->text_len) == 0)
{
/* This file matches for a completion; add it to the
current list of matches. */
if (base_name != filename
&& !filename_seen (base_name, 1, data->first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
- && strncasecmp (base_name, data->text, data->text_len) == 0
-#else
- && strncmp (base_name, data->text, data->text_len) == 0
-#endif
- )
+ && filename_ncmp (base_name, data->text, data->text_len) == 0)
add_filename_to_list (base_name, data->text, data->word,
data->list, data->list_used, data->list_alloced);
}
if (not_interesting_fname (s->filename))
continue;
if (!filename_seen (s->filename, 1, &first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
- && strncasecmp (s->filename, text, text_len) == 0
-#else
- && strncmp (s->filename, text, text_len) == 0
-#endif
- )
+ && filename_ncmp (s->filename, text, text_len) == 0)
{
/* This file matches for a completion; add it to the current
list of matches. */
base_name = lbasename (s->filename);
if (base_name != s->filename
&& !filename_seen (base_name, 1, &first)
-#if HAVE_DOS_BASED_FILE_SYSTEM
- && strncasecmp (base_name, text, text_len) == 0
-#else
- && strncmp (base_name, text, text_len) == 0
-#endif
- )
+ && filename_ncmp (base_name, text, text_len) == 0)
add_filename_to_list (base_name, text, word,
&list, &list_used, &list_alloced);
}
sals = decode_line_1 (&string, funfirstline,
cursal.symtab, cursal.line,
- (char ***) NULL, NULL);
+ NULL);
if (*string)
error (_("Junk at end of line specification: %s"), string);