/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc.
+ Copyright (C) 1986-2013 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "objfiles.h"
#include "gdbcmd.h"
-#include "call-cmds.h"
#include "gdb_regex.h"
#include "expression.h"
#include "language.h"
#include "demangle.h"
#include "inferior.h"
-#include "linespec.h"
#include "source.h"
#include "filenames.h" /* for FILENAME_CMP */
#include "objc-lang.h"
#include "d-lang.h"
#include "ada-lang.h"
+#include "go-lang.h"
#include "p-lang.h"
#include "addrmap.h"
#include "macroscope.h"
#include "psymtab.h"
+#include "parser-defs.h"
/* Prototypes for local functions */
static void sources_info (char *, int);
-static void output_source_filename (const char *, int *);
-
static int find_line_common (struct linetable *, int, int *, int);
static struct symbol *lookup_symbol_aux (const char *name,
const struct block *block,
const domain_enum domain,
enum language language,
- int *is_a_field_of_this);
+ struct field_of_this_result *is_a_field_of_this);
static
struct symbol *lookup_symbol_aux_local (const char *name,
/* */
+/* When non-zero, print debugging messages related to symtab creation. */
+int symtab_create_debug = 0;
+
/* Non-zero if a file may be known by two different basenames.
This is the uncommon case, and significantly slows down gdb.
Default set to "off" to not slow down the common case. */
/* See whether FILENAME matches SEARCH_NAME using the rule that we
advertise to the user. (The manual's description of linespecs
- describes what we advertise). SEARCH_LEN is the length of
- SEARCH_NAME. We assume that SEARCH_NAME is a relative path.
- Returns true if they match, false otherwise. */
+ describes what we advertise). Returns true if they match, false
+ otherwise. */
int
-compare_filenames_for_search (const char *filename, const char *search_name,
- int search_len)
+compare_filenames_for_search (const char *filename, const char *search_name)
{
int len = strlen (filename);
- int offset;
+ size_t search_len = strlen (search_name);
if (len < search_len)
return 0;
/* Either the names must completely match, or the character
preceding the trailing SEARCH_NAME segment of FILENAME must be a
- directory separator. */
+ directory separator.
+
+ The check !IS_ABSOLUTE_PATH ensures SEARCH_NAME "/dir/file.c"
+ cannot match FILENAME "/path//dir/file.c" - as user has requested
+ absolute path. The sama applies for "c:\file.c" possibly
+ incorrectly hypothetically matching "d:\dir\c:\file.c".
+
+ The HAS_DRIVE_SPEC purpose is to make FILENAME "c:file.c"
+ compatible with SEARCH_NAME "file.c". In such case a compiler had
+ to put the "c:file.c" name into debug info. Such compatibility
+ works only on GDB built for DOS host. */
return (len == search_len
- || IS_DIR_SEPARATOR (filename[len - search_len - 1])
+ || (!IS_ABSOLUTE_PATH (search_name)
+ && IS_DIR_SEPARATOR (filename[len - search_len - 1]))
|| (HAS_DRIVE_SPEC (filename)
&& STRIP_DRIVE_SPEC (filename) == &filename[len - search_len]));
}
/* Check for a symtab of a specific name by searching some symtabs.
This is a helper function for callbacks of iterate_over_symtabs.
- The return value, NAME, FULL_PATH, REAL_PATH, CALLBACK, and DATA
+ The return value, NAME, REAL_PATH, CALLBACK, and DATA
are identical to the `map_symtabs_matching_filename' method of
quick_symbol_functions.
int
iterate_over_some_symtabs (const char *name,
- const char *full_path,
const char *real_path,
int (*callback) (struct symtab *symtab,
void *data),
struct symtab *after_last)
{
struct symtab *s = NULL;
- struct cleanup *cleanup;
const char* base_name = lbasename (name);
- int name_len = strlen (name);
- int is_abs = IS_ABSOLUTE_PATH (name);
for (s = first; s != NULL && s != after_last; s = s->next)
{
- /* Exact match is always ok. */
- if (FILENAME_CMP (name, s->filename) == 0)
- {
- if (callback (s, data))
- return 1;
- }
-
- if (!is_abs && compare_filenames_for_search (s->filename, name, name_len))
+ if (compare_filenames_for_search (s->filename, name))
{
if (callback (s, data))
return 1;
&& FILENAME_CMP (base_name, lbasename (s->filename)) != 0)
continue;
+ if (compare_filenames_for_search (symtab_to_fullname (s), name))
+ {
+ if (callback (s, data))
+ return 1;
+ }
+
/* If the user gave us an absolute path, try to find the file in
this symtab and use its absolute path. */
- if (full_path != NULL)
+ if (real_path != NULL)
{
- const char *fp = symtab_to_fullname (s);
-
- if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
- {
- if (callback (s, data))
- return 1;
- }
+ const char *fullname = symtab_to_fullname (s);
- if (fp != NULL && !is_abs && compare_filenames_for_search (fp, name,
- name_len))
+ gdb_assert (IS_ABSOLUTE_PATH (real_path));
+ gdb_assert (IS_ABSOLUTE_PATH (name));
+ if (FILENAME_CMP (real_path, fullname) == 0)
{
if (callback (s, data))
return 1;
}
}
-
- if (real_path != NULL)
- {
- char *fullname = symtab_to_fullname (s);
-
- if (fullname != NULL)
- {
- char *rp = gdb_realpath (fullname);
-
- make_cleanup (xfree, rp);
- if (FILENAME_CMP (real_path, rp) == 0)
- {
- if (callback (s, data))
- return 1;
- }
-
- if (!is_abs && compare_filenames_for_search (rp, name, name_len))
- {
- if (callback (s, data))
- return 1;
- }
- }
- }
}
return 0;
void *data),
void *data)
{
- struct symtab *s = NULL;
struct objfile *objfile;
char *real_path = NULL;
- char *full_path = NULL;
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
/* Here we are interested in canonicalizing an absolute path, not
absolutizing a relative path. */
if (IS_ABSOLUTE_PATH (name))
{
- full_path = xfullpath (name);
- make_cleanup (xfree, full_path);
real_path = gdb_realpath (name);
make_cleanup (xfree, real_path);
+ gdb_assert (IS_ABSOLUTE_PATH (real_path));
}
ALL_OBJFILES (objfile)
{
- if (iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ if (iterate_over_some_symtabs (name, real_path, callback, data,
objfile->symtabs, NULL))
{
do_cleanups (cleanups);
if (objfile->sf
&& objfile->sf->qf->map_symtabs_matching_filename (objfile,
name,
- full_path,
real_path,
callback,
data))
if (len == 0)
{
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
}
else if (physname[0] == 't' || physname[0] == 'Q')
{
/* The physname for template and qualified methods already includes
the class name. */
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ xsnprintf (buf, sizeof (buf), "__%s%s", const_prefix, volatile_prefix);
newname = NULL;
len = 0;
}
else
{
- sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+ xsnprintf (buf, sizeof (buf), "__%s%s%d", const_prefix,
+ volatile_prefix, len);
}
mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
+ strlen (buf) + len + strlen (physname) + 1);
void
symbol_set_demangled_name (struct general_symbol_info *gsymbol,
- char *name,
+ const char *name,
struct objfile *objfile)
{
if (gsymbol->language == language_cplus)
{
gsymbol->language = language;
if (gsymbol->language == language_d
+ || gsymbol->language == language_go
|| gsymbol->language == language_java
|| gsymbol->language == language_objc
|| gsymbol->language == language_fortran)
/* Objects of this type are stored in the demangled name hash table. */
struct demangled_name_entry
{
- char *mangled;
+ const char *mangled;
char demangled[1];
};
return demangled;
}
}
+ /* FIXME(dje): Continually adding languages here is clumsy.
+ Better to just call la_demangle if !auto, and if auto then call
+ a utility routine that tries successive languages in turn and reports
+ which one it finds. I realize the la_demangle options may be different
+ for different languages but there's already a FIXME for that. */
+ if (gsymbol->language == language_go
+ || gsymbol->language == language_auto)
+ {
+ demangled = go_demangle (mangled, 0);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_go;
+ return demangled;
+ }
+ }
+
/* We could support `gsymbol->language == language_fortran' here to provide
module namespaces also for inferiors with only minimal symbol table (ELF
symbols). Just the mangling standard is not standardized across compilers
linkage_name_copy = linkage_name;
}
- entry.mangled = (char *) lookup_name;
+ entry.mangled = lookup_name;
slot = ((struct demangled_name_entry **)
htab_find_slot (objfile->demangled_names_hash,
&entry, INSERT));
/* If this name is not in the hash table, add it. */
- if (*slot == NULL)
+ if (*slot == NULL
+ /* A C version of the symbol may have already snuck into the table.
+ This happens to, e.g., main.init (__go_init_main). Cope. */
+ || (gsymbol->language == language_go
+ && (*slot)->demangled[0] == '\0'))
{
char *demangled_name = symbol_find_demangled_name (gsymbol,
linkage_name_copy);
offsetof (struct demangled_name_entry,
demangled)
+ demangled_len + 1);
- (*slot)->mangled = (char *) lookup_name;
+ (*slot)->mangled = lookup_name;
}
else
{
+ char *mangled_ptr;
+
/* If we must copy the mangled name, put it directly after
the demangled name so we can have a single
allocation. */
offsetof (struct demangled_name_entry,
demangled)
+ lookup_len + demangled_len + 2);
- (*slot)->mangled = &((*slot)->demangled[demangled_len + 1]);
- strcpy ((*slot)->mangled, lookup_name);
+ mangled_ptr = &((*slot)->demangled[demangled_len + 1]);
+ strcpy (mangled_ptr, lookup_name);
+ (*slot)->mangled = mangled_ptr;
}
if (demangled_name != NULL)
{
case language_cplus:
case language_d:
+ case language_go:
case language_java:
case language_objc:
case language_fortran:
const char *
symbol_demangled_name (const struct general_symbol_info *gsymbol)
{
+ const char *dem_name = NULL;
+
switch (gsymbol->language)
{
case language_cplus:
case language_d:
+ case language_go:
case language_java:
case language_objc:
case language_fortran:
- if (symbol_get_demangled_name (gsymbol) != NULL)
- return symbol_get_demangled_name (gsymbol);
+ dem_name = symbol_get_demangled_name (gsymbol);
break;
case language_ada:
- if (symbol_get_demangled_name (gsymbol) != NULL)
- return symbol_get_demangled_name (gsymbol);
- else
- return ada_decode_symbol (gsymbol);
+ dem_name = symbol_get_demangled_name (gsymbol);
+ if (dem_name == NULL)
+ dem_name = ada_decode_symbol (gsymbol);
break;
default:
break;
}
- return NULL;
+ return dem_name;
}
/* Return the search name of a symbol---generally the demangled or
sal->end = 0;
sal->explicit_pc = 0;
sal->explicit_line = 0;
+ sal->probe = NULL;
}
\f
modified_name = name;
- /* If we are using C++, D, or Java, demangle the name before doing a
+ /* If we are using C++, D, Go, or Java, demangle the name before doing a
lookup, so we can always binary search. */
if (lang == language_cplus)
{
make_cleanup (xfree, demangled_name);
}
}
+ else if (lang == language_go)
+ {
+ demangled_name = go_demangle (name, 0);
+ if (demangled_name)
+ {
+ modified_name = demangled_name;
+ make_cleanup (xfree, demangled_name);
+ }
+ }
*result_name = modified_name;
return cleanup;
struct symbol *
lookup_symbol_in_language (const char *name, const struct block *block,
const domain_enum domain, enum language lang,
- int *is_a_field_of_this)
+ struct field_of_this_result *is_a_field_of_this)
{
const char *modified_name;
struct symbol *returnval;
struct symbol *
lookup_symbol (const char *name, const struct block *block,
- domain_enum domain, int *is_a_field_of_this)
+ domain_enum domain,
+ struct field_of_this_result *is_a_field_of_this)
{
return lookup_symbol_in_language (name, block, domain,
current_language->la_language,
return NULL;
}
+/* Given TYPE, a structure/union,
+ return 1 if the component named NAME from the ultimate target
+ structure/union is defined, otherwise, return 0. */
+
+static int
+check_field (struct type *type, const char *name,
+ struct field_of_this_result *is_a_field_of_this)
+{
+ int i;
+
+ /* The type may be a stub. */
+ CHECK_TYPEDEF (type);
+
+ for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+ {
+ const char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+ if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
+ {
+ is_a_field_of_this->type = type;
+ is_a_field_of_this->field = &TYPE_FIELD (type, i);
+ return 1;
+ }
+ }
+
+ /* C++: If it was not found as a data field, then try to return it
+ as a pointer to a method. */
+
+ for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+ {
+ if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0)
+ {
+ is_a_field_of_this->type = type;
+ is_a_field_of_this->fn_field = &TYPE_FN_FIELDLIST (type, i);
+ return 1;
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ if (check_field (TYPE_BASECLASS (type, i), name, is_a_field_of_this))
+ return 1;
+
+ return 0;
+}
+
/* Behave like lookup_symbol except that NAME is the natural name
(e.g., demangled name) of the symbol that we're looking for. */
static struct symbol *
lookup_symbol_aux (const char *name, const struct block *block,
const domain_enum domain, enum language language,
- int *is_a_field_of_this)
+ struct field_of_this_result *is_a_field_of_this)
{
struct symbol *sym;
const struct language_defn *langdef;
/* Make sure we do something sensible with is_a_field_of_this, since
the callers that set this parameter to some non-null value will
- certainly use it later and expect it to be either 0 or 1.
- If we don't set it, the contents of is_a_field_of_this are
- undefined. */
+ certainly use it later. If we don't set it, the contents of
+ is_a_field_of_this are undefined. */
if (is_a_field_of_this != NULL)
- *is_a_field_of_this = 0;
+ memset (is_a_field_of_this, 0, sizeof (*is_a_field_of_this));
/* Search specified block and its superiors. Don't search
STATIC_BLOCK or GLOBAL_BLOCK. */
langdef = language_def (language);
- if (is_a_field_of_this != NULL)
+ /* Don't do this check if we are searching for a struct. It will
+ not be found by check_field, but will be found by other
+ means. */
+ if (is_a_field_of_this != NULL && domain != STRUCT_DOMAIN)
{
struct symbol *sym = lookup_language_this (langdef, block);
error (_("Internal error: `%s' is not an aggregate"),
langdef->la_name_of_this);
- if (check_field (t, name))
- {
- *is_a_field_of_this = 1;
- return NULL;
- }
+ if (check_field (t, name, is_a_field_of_this))
+ return NULL;
}
}
objfile = objfile_separate_debug_iterate (main_objfile, objfile))
{
/* Go through symtabs. */
- ALL_OBJFILE_SYMTABS (objfile, s)
- {
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, domain);
- if (sym)
- {
- block_found = block;
- return fixup_symbol_section (sym, (struct objfile *)objfile);
- }
- }
+ ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, domain);
+ if (sym)
+ {
+ block_found = block;
+ return fixup_symbol_section (sym, (struct objfile *)objfile);
+ }
+ }
sym = lookup_symbol_aux_quick ((struct objfile *) objfile, GLOBAL_BLOCK,
name, domain);
return NULL;
}
-/* Check to see if the symbol is defined in one of the symtabs.
- BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
+/* Check to see if the symbol is defined in one of the OBJFILE's
+ symtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
depending on whether or not we want to search global symbols or
static symbols. */
+static struct symbol *
+lookup_symbol_aux_objfile (struct objfile *objfile, int block_index,
+ const char *name, const domain_enum domain)
+{
+ struct symbol *sym = NULL;
+ struct blockvector *bv;
+ const struct block *block;
+ struct symtab *s;
+
+ ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = lookup_block_symbol (block, name, domain);
+ if (sym)
+ {
+ block_found = block;
+ return fixup_symbol_section (sym, objfile);
+ }
+ }
+
+ return NULL;
+}
+
+/* Same as lookup_symbol_aux_objfile, except that it searches all
+ objfiles. Return the first match found. */
+
static struct symbol *
lookup_symbol_aux_symtabs (int block_index, const char *name,
const domain_enum domain)
{
struct symbol *sym;
struct objfile *objfile;
- struct blockvector *bv;
- const struct block *block;
- struct symtab *s;
ALL_OBJFILES (objfile)
{
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile,
- block_index,
- name, domain);
+ sym = lookup_symbol_aux_objfile (objfile, block_index, name, domain);
+ if (sym)
+ return sym;
+ }
- ALL_OBJFILE_SYMTABS (objfile, s)
- if (s->primary)
+ return NULL;
+}
+
+/* Wrapper around lookup_symbol_aux_objfile for search_symbols.
+ Look up LINKAGE_NAME in DOMAIN in the global and static blocks of OBJFILE
+ and all related objfiles. */
+
+static struct symbol *
+lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
+ const char *linkage_name,
+ domain_enum domain)
+{
+ enum language lang = current_language->la_language;
+ const char *modified_name;
+ struct cleanup *cleanup = demangle_for_lookup (linkage_name, lang,
+ &modified_name);
+ struct objfile *main_objfile, *cur_objfile;
+
+ if (objfile->separate_debug_objfile_backlink)
+ main_objfile = objfile->separate_debug_objfile_backlink;
+ else
+ main_objfile = objfile;
+
+ for (cur_objfile = main_objfile;
+ cur_objfile;
+ cur_objfile = objfile_separate_debug_iterate (main_objfile, cur_objfile))
+ {
+ struct symbol *sym;
+
+ sym = lookup_symbol_aux_objfile (cur_objfile, GLOBAL_BLOCK,
+ modified_name, domain);
+ if (sym == NULL)
+ sym = lookup_symbol_aux_objfile (cur_objfile, STATIC_BLOCK,
+ modified_name, domain);
+ if (sym != NULL)
{
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, block_index);
- sym = lookup_block_symbol (block, name, domain);
- if (sym)
- {
- block_found = block;
- return fixup_symbol_section (sym, objfile);
- }
+ do_cleanups (cleanup);
+ return sym;
}
- }
+ }
+ do_cleanups (cleanup);
return NULL;
}
%s may be an inlined function, or may be a template function\n\
(if a template, try specifying an instantiation: %s<type>)."),
kind == GLOBAL_BLOCK ? "global" : "static",
- name, symtab->filename, name, name);
+ name, symtab_to_filename_for_display (symtab), name, name);
}
return fixup_symbol_section (sym, objfile);
}
return NULL;
}
+/* Private data to be used with lookup_symbol_global_iterator_cb. */
+
+struct global_sym_lookup_data
+{
+ /* The name of the symbol we are searching for. */
+ const char *name;
+
+ /* The domain to use for our search. */
+ domain_enum domain;
+
+ /* The field where the callback should store the symbol if found.
+ It should be initialized to NULL before the search is started. */
+ struct symbol *result;
+};
+
+/* A callback function for gdbarch_iterate_over_objfiles_in_search_order.
+ It searches by name for a symbol in the GLOBAL_BLOCK of the given
+ OBJFILE. The arguments for the search are passed via CB_DATA,
+ which in reality is a pointer to struct global_sym_lookup_data. */
+
+static int
+lookup_symbol_global_iterator_cb (struct objfile *objfile,
+ void *cb_data)
+{
+ struct global_sym_lookup_data *data =
+ (struct global_sym_lookup_data *) cb_data;
+
+ gdb_assert (data->result == NULL);
+
+ data->result = lookup_symbol_aux_objfile (objfile, GLOBAL_BLOCK,
+ data->name, data->domain);
+ if (data->result == NULL)
+ data->result = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK,
+ data->name, data->domain);
+
+ /* If we found a match, tell the iterator to stop. Otherwise,
+ keep going. */
+ return (data->result != NULL);
+}
+
/* Lookup a symbol in all files' global blocks (searching psymtabs if
necessary). */
{
struct symbol *sym = NULL;
struct objfile *objfile = NULL;
+ struct global_sym_lookup_data lookup_data;
/* Call library-specific lookup procedure. */
objfile = lookup_objfile_from_block (block);
if (sym != NULL)
return sym;
- sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain);
- if (sym != NULL)
- return sym;
-
- ALL_OBJFILES (objfile)
- {
- sym = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK, name, domain);
- if (sym)
- return sym;
- }
+ memset (&lookup_data, 0, sizeof (lookup_data));
+ lookup_data.name = name;
+ lookup_data.domain = domain;
+ gdbarch_iterate_over_objfiles_in_search_order
+ (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (),
+ lookup_symbol_global_iterator_cb, &lookup_data, objfile);
- return NULL;
+ return lookup_data.result;
}
int
Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n\
(if a template, try specifying an instantiation: %s<type>)."),
- name, symtab->filename, name, name);
+ name, symtab_to_filename_for_display (symtab), name, name);
}
if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
return SYMBOL_TYPE (sym);
ALL_OBJFILES (objfile)
{
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile,
- GLOBAL_BLOCK,
- name, STRUCT_DOMAIN);
-
- ALL_OBJFILE_SYMTABS (objfile, s)
- if (s->primary)
- {
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- {
- return SYMBOL_TYPE (sym);
- }
- }
+ ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
+ if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ {
+ return SYMBOL_TYPE (sym);
+ }
+ }
}
ALL_OBJFILES (objfile)
ALL_OBJFILES (objfile)
{
- if (objfile->sf)
- objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK,
- name, STRUCT_DOMAIN);
-
- ALL_OBJFILE_SYMTABS (objfile, s)
+ ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
lookup_block_symbol (const struct block *block, const char *name,
const domain_enum domain)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym;
if (!BLOCK_FUNCTION (block))
{
- for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+ for (sym = block_iter_name_first (block, name, &iter);
sym != NULL;
- sym = dict_iter_name_next (name, &iter))
+ sym = block_iter_name_next (name, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
struct symbol *sym_found = NULL;
- for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+ for (sym = block_iter_name_first (block, name, &iter);
sym != NULL;
- sym = dict_iter_name_next (name, &iter))
+ sym = block_iter_name_next (name, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
{
while (block)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym;
- for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+ for (sym = block_iter_name_first (block, name, &iter);
sym != NULL;
- sym = dict_iter_name_next (name, &iter))
+ sym = block_iter_name_next (name, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
struct symtab *s = NULL;
struct symtab *best_s = NULL;
struct objfile *objfile;
- struct program_space *pspace;
CORE_ADDR distance = 0;
struct minimal_symbol *msymbol;
- pspace = current_program_space;
-
/* If we know that this is not a text address, return failure. This is
necessary because we loop based on the block's high and low code
addresses, which do not include the data ranges, and because
}
if (section != 0)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym = NULL;
ALL_BLOCK_SYMBOLS (b, iter, sym)
if (best_s != NULL)
return (best_s);
+ /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs). */
+
ALL_OBJFILES (objfile)
{
struct symtab *result;
we will use a line one less than this,
with a range from the start of that file to the first line's pc. */
struct linetable_entry *alt = NULL;
- struct symtab *alt_symtab = 0;
/* Info on best line seen in this file. */
/* Is this file's first line closer than the first lines of other files?
If so, record this file, and its first line, as best alternate. */
if (item->pc > pc && (!alt || item->pc < alt->pc))
- {
- alt = item;
- alt_symtab = s;
- }
+ alt = item;
for (i = 0; i < len; i++, item++)
{
ALL_OBJFILES (objfile)
{
if (objfile->sf)
- objfile->sf->qf->expand_symtabs_with_filename (objfile,
- symtab->filename);
+ objfile->sf->qf->expand_symtabs_with_fullname (objfile,
+ symtab_to_fullname (symtab));
}
- /* Get symbol full file name if possible. */
- symtab_to_fullname (symtab);
-
ALL_SYMTABS (objfile, s)
{
struct linetable *l;
if (FILENAME_CMP (symtab->filename, s->filename) != 0)
continue;
- if (symtab->fullname != NULL
- && symtab_to_fullname (s) != NULL
- && FILENAME_CMP (symtab->fullname, s->fullname) != 0)
+ if (FILENAME_CMP (symtab_to_fullname (symtab),
+ symtab_to_fullname (s)) != 0)
continue;
l = LINETABLE (s);
ind = find_line_common (l, line, &exact, 0);
find_pcs_for_symtab_line (struct symtab *symtab, int line,
struct linetable_entry **best_item)
{
- int start = 0, ix;
- struct symbol *previous_function = NULL;
+ int start = 0;
VEC (CORE_ADDR) *result = NULL;
/* First, collect all the PCs that are at this line. */
struct block *b, *function_block;
int force_skip, skip;
- /* Do not change the SAL is PC was specified explicitly. */
+ /* Do not change the SAL if PC was specified explicitly. */
if (sal->explicit_pc)
return;
}
\f
-/* If FILE is not already in the table of files, return zero;
+/* Cache to watch for file names already seen by filename_seen. */
+
+struct filename_seen_cache
+{
+ /* Table of files seen so far. */
+ htab_t tab;
+ /* Initial size of the table. It automagically grows from here. */
+#define INITIAL_FILENAME_SEEN_CACHE_SIZE 100
+};
+
+/* filename_seen_cache constructor. */
+
+static struct filename_seen_cache *
+create_filename_seen_cache (void)
+{
+ struct filename_seen_cache *cache;
+
+ cache = XNEW (struct filename_seen_cache);
+ cache->tab = htab_create_alloc (INITIAL_FILENAME_SEEN_CACHE_SIZE,
+ filename_hash, filename_eq,
+ NULL, xcalloc, xfree);
+
+ return cache;
+}
+
+/* Empty the cache, but do not delete it. */
+
+static void
+clear_filename_seen_cache (struct filename_seen_cache *cache)
+{
+ htab_empty (cache->tab);
+}
+
+/* filename_seen_cache destructor.
+ This takes a void * argument as it is generally used as a cleanup. */
+
+static void
+delete_filename_seen_cache (void *ptr)
+{
+ struct filename_seen_cache *cache = ptr;
+
+ htab_delete (cache->tab);
+ xfree (cache);
+}
+
+/* If FILE is not already in the table of files in CACHE, return zero;
otherwise return non-zero. Optionally add FILE to the table if ADD
- is non-zero. If *FIRST is non-zero, forget the old table
- contents. */
+ is non-zero.
+
+ NOTE: We don't manage space for FILE, we assume FILE lives as long
+ as the caller needs. */
static int
-filename_seen (const char *file, int add, int *first)
+filename_seen (struct filename_seen_cache *cache, const char *file, int add)
{
- /* Table of files seen so far. */
- static const char **tab = NULL;
- /* Allocated size of tab in elements.
- Start with one 256-byte block (when using GNU malloc.c).
- 24 is the malloc overhead when range checking is in effect. */
- static int tab_alloc_size = (256 - 24) / sizeof (char *);
- /* Current size of tab in elements. */
- static int tab_cur_size;
- const char **p;
-
- if (*first)
- {
- if (tab == NULL)
- tab = (const char **) xmalloc (tab_alloc_size * sizeof (*tab));
- tab_cur_size = 0;
- }
+ void **slot;
/* Is FILE in tab? */
- for (p = tab; p < tab + tab_cur_size; p++)
- if (filename_cmp (*p, file) == 0)
- return 1;
+ slot = htab_find_slot (cache->tab, file, add ? INSERT : NO_INSERT);
+ if (*slot != NULL)
+ return 1;
/* No; maybe add it to tab. */
if (add)
- {
- if (tab_cur_size == tab_alloc_size)
- {
- tab_alloc_size *= 2;
- tab = (const char **) xrealloc ((char *) tab,
- tab_alloc_size * sizeof (*tab));
- }
- tab[tab_cur_size++] = file;
- }
+ *slot = (char *) file;
return 0;
}
+/* Data structure to maintain printing state for output_source_filename. */
+
+struct output_source_filename_data
+{
+ /* Cache of what we've seen so far. */
+ struct filename_seen_cache *filename_seen_cache;
+
+ /* Flag of whether we're printing the first one. */
+ int first;
+};
+
/* Slave routine for sources_info. Force line breaks at ,'s.
- NAME is the name to print and *FIRST is nonzero if this is the first
- name printed. Set *FIRST to zero. */
+ NAME is the name to print.
+ DATA contains the state for printing and watching for duplicates. */
static void
-output_source_filename (const char *name, int *first)
+output_source_filename (const char *name,
+ struct output_source_filename_data *data)
{
/* Since a single source file can result in several partial symbol
tables, we need to avoid printing it more than once. Note: if
symtabs; it doesn't hurt to check. */
/* Was NAME already seen? */
- if (filename_seen (name, 1, first))
+ if (filename_seen (data->filename_seen_cache, name, 1))
{
/* Yes; don't print it again. */
return;
}
+
/* No; print it and reset *FIRST. */
- if (*first)
- {
- *first = 0;
- }
- else
- {
- printf_filtered (", ");
- }
+ if (! data->first)
+ printf_filtered (", ");
+ data->first = 0;
wrap_here ("");
fputs_filtered (name, gdb_stdout);
{
struct symtab *s;
struct objfile *objfile;
- int first;
+ struct output_source_filename_data data;
+ struct cleanup *cleanups;
if (!have_full_symbols () && !have_partial_symbols ())
{
error (_("No symbol table is loaded. Use the \"file\" command."));
}
+ data.filename_seen_cache = create_filename_seen_cache ();
+ cleanups = make_cleanup (delete_filename_seen_cache,
+ data.filename_seen_cache);
+
printf_filtered ("Source files for which symbols have been read in:\n\n");
- first = 1;
+ data.first = 1;
ALL_SYMTABS (objfile, s)
{
const char *fullname = symtab_to_fullname (s);
- output_source_filename (fullname ? fullname : s->filename, &first);
+ output_source_filename (fullname, &data);
}
printf_filtered ("\n\n");
printf_filtered ("Source files for which symbols "
"will be read in on demand:\n\n");
- first = 1;
- map_partial_symbol_filenames (output_partial_symbol_filename, &first,
+ clear_filename_seen_cache (data.filename_seen_cache);
+ data.first = 1;
+ map_partial_symbol_filenames (output_partial_symbol_filename, &data,
1 /*need_fullname*/);
printf_filtered ("\n");
+
+ do_cleanups (cleanups);
}
+/* Compare FILE against all the NFILES entries of FILES. If BASENAMES is
+ non-zero compare only lbasename of FILES. */
+
static int
-file_matches (const char *file, char *files[], int nfiles)
+file_matches (const char *file, char *files[], int nfiles, int basenames)
{
int i;
{
for (i = 0; i < nfiles; i++)
{
- if (filename_cmp (files[i], lbasename (file)) == 0)
+ if (compare_filenames_for_search (file, (basenames
+ ? lbasename (files[i])
+ : files[i])))
return 1;
}
}
/* A callback for expand_symtabs_matching. */
static int
-search_symbols_file_matches (const char *filename, void *user_data)
+search_symbols_file_matches (const char *filename, void *user_data,
+ int basenames)
{
struct search_symbols_data *data = user_data;
- return file_matches (filename, data->files, data->nfiles);
+ return file_matches (filename, data->files, data->nfiles, basenames);
}
/* A callback for expand_symtabs_matching. */
struct blockvector *bv;
struct block *b;
int i = 0;
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym;
struct objfile *objfile;
struct minimal_symbol *msymbol;
- char *val;
int found_misc = 0;
static const enum minimal_symbol_type types[]
= {mst_data, mst_text, mst_abs};
{
if (objfile->sf)
objfile->sf->qf->expand_symtabs_matching (objfile,
- search_symbols_file_matches,
+ (nfiles == 0
+ ? NULL
+ : search_symbols_file_matches),
search_symbols_name_matches,
kind,
&datum);
The symbol will then be found during the scan of symtabs below.
For functions, find_pc_symtab should succeed if we have debug info
- for the function, for variables we have to call lookup_symbol
- to determine if the variable has debug info.
+ for the function, for variables we have to call
+ lookup_symbol_in_objfile_from_linkage_name to determine if the variable
+ has debug info.
If the lookup fails, set found_misc so that we will rescan to print
- any matching symbols without debug info. */
+ any matching symbols without debug info.
+ We only search the objfile the msymbol came from, we no longer search
+ all objfiles. In large programs (1000s of shared libs) searching all
+ objfiles is not worth the pain. */
if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
{
{
QUIT;
- if (MSYMBOL_TYPE (msymbol) == ourtype ||
- MSYMBOL_TYPE (msymbol) == ourtype2 ||
- MSYMBOL_TYPE (msymbol) == ourtype3 ||
- MSYMBOL_TYPE (msymbol) == ourtype4)
+ if (msymbol->created_by_gdb)
+ continue;
+
+ if (MSYMBOL_TYPE (msymbol) == ourtype
+ || MSYMBOL_TYPE (msymbol) == ourtype2
+ || MSYMBOL_TYPE (msymbol) == ourtype3
+ || MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (!datum.preg_p
|| regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
{
- if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
- {
- /* FIXME: carlton/2003-02-04: Given that the
- semantics of lookup_symbol keeps on changing
- slightly, it would be a nice idea if we had a
- function lookup_symbol_minsym that found the
- symbol associated to a given minimal symbol (if
- any). */
- if (kind == FUNCTIONS_DOMAIN
- || lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
- (struct block *) NULL,
- VAR_DOMAIN, 0)
- == NULL)
- found_misc = 1;
- }
+ /* Note: An important side-effect of these lookup functions
+ is to expand the symbol table if msymbol is found, for the
+ benefit of the next loop on ALL_PRIMARY_SYMTABS. */
+ if (kind == FUNCTIONS_DOMAIN
+ ? find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)) == NULL
+ : (lookup_symbol_in_objfile_from_linkage_name
+ (objfile, SYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
+ == NULL))
+ found_misc = 1;
}
}
}
ALL_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
- for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
- {
- struct symbol_search *prevtail = tail;
- int nfound = 0;
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ struct symbol_search *prevtail = tail;
+ int nfound = 0;
- b = BLOCKVECTOR_BLOCK (bv, i);
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- struct symtab *real_symtab = SYMBOL_SYMTAB (sym);
-
- QUIT;
-
- if (file_matches (real_symtab->filename, files, nfiles)
- && ((!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
- && SYMBOL_CLASS (sym) != LOC_BLOCK
- /* LOC_CONST can be used for more than just enums,
- e.g., c++ static const members.
- We only want to skip enums here. */
- && !(SYMBOL_CLASS (sym) == LOC_CONST
- && TYPE_CODE (SYMBOL_TYPE (sym))
- == TYPE_CODE_ENUM))
- || (kind == FUNCTIONS_DOMAIN
- && SYMBOL_CLASS (sym) == LOC_BLOCK)
- || (kind == TYPES_DOMAIN
- && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
- {
- /* match */
- psr = (struct symbol_search *)
- xmalloc (sizeof (struct symbol_search));
- psr->block = i;
- psr->symtab = real_symtab;
- psr->symbol = sym;
- psr->msymbol = NULL;
- psr->next = NULL;
- if (tail == NULL)
- sr = psr;
- else
- tail->next = psr;
- tail = psr;
- nfound ++;
- }
- }
- if (nfound > 0)
- {
- if (prevtail == NULL)
- {
- struct symbol_search dummy;
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ struct symtab *real_symtab = SYMBOL_SYMTAB (sym);
+
+ QUIT;
+
+ /* Check first sole REAL_SYMTAB->FILENAME. It does not need to be
+ a substring of symtab_to_fullname as it may contain "./" etc. */
+ if ((file_matches (real_symtab->filename, files, nfiles, 0)
+ || ((basenames_may_differ
+ || file_matches (lbasename (real_symtab->filename),
+ files, nfiles, 1))
+ && file_matches (symtab_to_fullname (real_symtab),
+ files, nfiles, 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
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ /* LOC_CONST can be used for more than just enums,
+ e.g., c++ static const members.
+ We only want to skip enums here. */
+ && !(SYMBOL_CLASS (sym) == LOC_CONST
+ && TYPE_CODE (SYMBOL_TYPE (sym))
+ == TYPE_CODE_ENUM))
+ || (kind == FUNCTIONS_DOMAIN
+ && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ || (kind == TYPES_DOMAIN
+ && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
+ {
+ /* match */
+ psr = (struct symbol_search *)
+ xmalloc (sizeof (struct symbol_search));
+ psr->block = i;
+ psr->symtab = real_symtab;
+ psr->symbol = sym;
+ psr->msymbol = NULL;
+ psr->next = NULL;
+ if (tail == NULL)
+ sr = psr;
+ else
+ tail->next = psr;
+ tail = psr;
+ nfound ++;
+ }
+ }
+ if (nfound > 0)
+ {
+ if (prevtail == NULL)
+ {
+ struct symbol_search dummy;
- dummy.next = sr;
- tail = sort_search_symbols (&dummy, nfound);
- sr = dummy.next;
+ dummy.next = sr;
+ tail = sort_search_symbols (&dummy, nfound);
+ sr = dummy.next;
- make_cleanup_free_search_symbols (sr);
- }
- else
- tail = sort_search_symbols (prevtail, nfound);
- }
- }
+ make_cleanup_free_search_symbols (sr);
+ }
+ else
+ tail = sort_search_symbols (prevtail, nfound);
+ }
+ }
}
/* If there are no eyes, avoid all contact. I mean, if there are
no debug symbols, then print directly from the msymbol_vector. */
- if (found_misc || kind != FUNCTIONS_DOMAIN)
+ if (found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
{
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- if (MSYMBOL_TYPE (msymbol) == ourtype ||
- MSYMBOL_TYPE (msymbol) == ourtype2 ||
- MSYMBOL_TYPE (msymbol) == ourtype3 ||
- MSYMBOL_TYPE (msymbol) == ourtype4)
+ if (msymbol->created_by_gdb)
+ continue;
+
+ if (MSYMBOL_TYPE (msymbol) == ourtype
+ || MSYMBOL_TYPE (msymbol) == ourtype2
+ || MSYMBOL_TYPE (msymbol) == ourtype3
+ || MSYMBOL_TYPE (msymbol) == ourtype4)
{
if (!datum.preg_p
|| regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0,
NULL, 0) == 0)
{
- /* Functions: Look up by address. */
- if (kind != FUNCTIONS_DOMAIN ||
- (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
+ /* For functions we can do a quick check of whether the
+ symbol might be found via find_pc_symtab. */
+ if (kind != FUNCTIONS_DOMAIN
+ || find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)) == NULL)
{
- /* Variables/Absolutes: Look up by name. */
- if (lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
- (struct block *) NULL, VAR_DOMAIN, 0)
- == NULL)
+ if (lookup_symbol_in_objfile_from_linkage_name
+ (objfile, SYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
+ == NULL)
{
/* match */
psr = (struct symbol_search *)
static void
print_symbol_info (enum search_domain kind,
struct symtab *s, struct symbol *sym,
- int block, char *last)
+ int block, const char *last)
{
- if (last == NULL || filename_cmp (last, s->filename) != 0)
+ const char *s_filename = symtab_to_filename_for_display (s);
+
+ if (last == NULL || filename_cmp (last, s_filename) != 0)
{
fputs_filtered ("\nFile ", gdb_stdout);
- fputs_filtered (s->filename, gdb_stdout);
+ fputs_filtered (s_filename, gdb_stdout);
fputs_filtered (":\n", gdb_stdout);
}
&& SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout);
/* variable, func, or typedef-that-is-c++-class. */
- else if (kind < TYPES_DOMAIN ||
- (kind == TYPES_DOMAIN &&
- SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
+ else if (kind < TYPES_DOMAIN
+ || (kind == TYPES_DOMAIN
+ && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
{
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
struct symbol_search *symbols;
struct symbol_search *p;
struct cleanup *old_chain;
- char *last_filename = NULL;
+ const char *last_filename = NULL;
int first = 1;
gdb_assert (kind <= TYPES_DOMAIN);
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[kind], regexp);
+ if (regexp != NULL)
+ printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+ classnames[kind], regexp);
+ else
+ printf_filtered (_("All defined %ss:\n"), classnames[kind]);
for (p = symbols; p != NULL; p = p->next)
{
{
if (first)
{
- printf_filtered ("\nNon-debugging symbols:\n");
+ printf_filtered (_("\nNon-debugging symbols:\n"));
first = 0;
}
print_msymbol_info (p->msymbol);
p->symbol,
p->block,
last_filename);
- last_filename = p->symtab->filename;
+ last_filename = symtab_to_filename_for_display (p->symtab);
}
}
{
if (p->msymbol == NULL)
{
- int newlen = (strlen (p->symtab->filename)
+ const char *fullname = symtab_to_fullname (p->symtab);
+
+ int newlen = (strlen (fullname)
+ strlen (SYMBOL_LINKAGE_NAME (p->symbol))
+ 4);
string = xrealloc (string, newlen);
len = newlen;
}
- strcpy (string, p->symtab->filename);
+ strcpy (string, fullname);
strcat (string, ":'");
strcat (string, SYMBOL_LINKAGE_NAME (p->symbol));
strcat (string, "'");
p->symtab,
p->symbol,
p->block,
- p->symtab->filename);
+ symtab_to_filename_for_display (p->symtab));
}
else
{
/* Free any memory associated with a completion list. */
static void
-free_completion_list (char ***list_ptr)
+free_completion_list (VEC (char_ptr) **list_ptr)
{
- int i = 0;
- char **list = *list_ptr;
+ int i;
+ char *p;
- while (list[i] != NULL)
- {
- xfree (list[i]);
- i++;
- }
- xfree (list);
+ for (i = 0; VEC_iterate (char_ptr, *list_ptr, i, p); ++i)
+ xfree (p);
+ VEC_free (char_ptr, *list_ptr);
}
/* Callback for make_cleanup. */
/* Helper routine for make_symbol_completion_list. */
-static int return_val_size;
-static int return_val_index;
-static char **return_val;
+static VEC (char_ptr) *return_val;
#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
completion_list_add_name \
const char *sym_text, int sym_text_len,
const char *text, const char *word)
{
- int newsize;
-
/* Clip symbols that cannot match. */
if (!compare_symbol_name (symname, sym_text, sym_text_len))
return;
strcat (new, symname);
}
- if (return_val_index + 3 > return_val_size)
- {
- newsize = (return_val_size *= 2) * sizeof (char *);
- return_val = (char **) xrealloc ((char *) return_val, newsize);
- }
- return_val[return_val_index++] = new;
- return_val[return_val_index] = NULL;
+ VEC_safe_push (char_ptr, return_val, new);
}
}
return compare_symbol_name (name, datum->sym_text, datum->sym_text_len);
}
-char **
+VEC (char_ptr) *
default_make_symbol_completion_list_break_on (char *text, char *word,
- const char *break_on)
+ const char *break_on,
+ enum type_code code)
{
/* Problem: All of the symbols have to be copied because readline
frees them. I'm not going to worry about this; hopefully there
struct objfile *objfile;
struct block *b;
const struct block *surrounding_static_block, *surrounding_global_block;
- struct dict_iterator iter;
+ struct block_iterator iter;
/* The symbol we are completing on. Points in same buffer as text. */
char *sym_text;
/* Length of sym_text. */
/* A double-quoted string is never a symbol, nor does it make sense
to complete it any other way. */
{
- return_val = (char **) xmalloc (sizeof (char *));
- return_val[0] = NULL;
- return return_val;
+ return NULL;
}
else
{
}
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 *));
- return_val[0] = NULL;
+ return_val = NULL;
back_to = make_cleanup (do_free_completion_list, &return_val);
datum.sym_text = sym_text;
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */
- ALL_MSYMBOLS (objfile, msymbol)
- {
- QUIT;
- COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
+ word);
- completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text, word);
- }
+ completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
+ word);
+ }
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars). Also catch fields of types defined in
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
- word);
- completion_list_add_fields (sym, sym_text, sym_text_len, text,
- word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+ word);
+ completion_list_add_fields (sym, sym_text, sym_text_len, text,
+ word);
+ }
+ else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
+ word);
}
/* Stop when we encounter an enclosing function. Do not stop for
/* Add fields from the file's types; symbols will be added below. */
- if (surrounding_static_block != NULL)
- ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
- completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF)
+ {
+ if (surrounding_static_block != NULL)
+ ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
+ completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
- if (surrounding_global_block != NULL)
- ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
- completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ if (surrounding_global_block != NULL)
+ ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
+ completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
+ }
/* Go through the symtabs and check the externs and statics for
symbols which match. */
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF
+ || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ if (code == TYPE_CODE_UNDEF
+ || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
}
- if (current_language->la_macro_expansion == macro_expansion_c)
+ /* Skip macros if we are completing a struct tag -- arguable but
+ usually what is expected. */
+ if (current_language->la_macro_expansion == macro_expansion_c
+ && code == TYPE_CODE_UNDEF)
{
struct macro_scope *scope;
return (return_val);
}
-char **
-default_make_symbol_completion_list (char *text, char *word)
+VEC (char_ptr) *
+default_make_symbol_completion_list (char *text, char *word,
+ enum type_code code)
{
- return default_make_symbol_completion_list_break_on (text, word, "");
+ return default_make_symbol_completion_list_break_on (text, word, "", code);
}
-/* Return a NULL terminated array of all symbols (regardless of class)
- which begin by matching TEXT. If the answer is no symbols, then
- the return value is an array which contains only a NULL pointer. */
+/* Return a vector of all symbols (regardless of class) which begin by
+ matching TEXT. If the answer is no symbols, then the return value
+ is NULL. */
-char **
+VEC (char_ptr) *
make_symbol_completion_list (char *text, char *word)
{
- return current_language->la_make_symbol_completion_list (text, word);
+ return current_language->la_make_symbol_completion_list (text, word,
+ TYPE_CODE_UNDEF);
+}
+
+/* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
+ symbols whose type code is CODE. */
+
+VEC (char_ptr) *
+make_symbol_completion_type (char *text, char *word, enum type_code code)
+{
+ gdb_assert (code == TYPE_CODE_UNION
+ || code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_CLASS
+ || code == TYPE_CODE_ENUM);
+ return current_language->la_make_symbol_completion_list (text, word, code);
}
/* Like make_symbol_completion_list, but suitable for use as a
completion function. */
-char **
+VEC (char_ptr) *
make_symbol_completion_list_fn (struct cmd_list_element *ignore,
char *text, char *word)
{
/* Like make_symbol_completion_list, but returns a list of symbols
defined in a source file FILE. */
-char **
+VEC (char_ptr) *
make_file_symbol_completion_list (char *text, char *word, char *srcfile)
{
struct symbol *sym;
struct symtab *s;
struct block *b;
- struct dict_iterator iter;
+ struct block_iterator iter;
/* The symbol we are completing on. Points in same buffer as text. */
char *sym_text;
/* Length of sym_text. */
/* A double-quoted string is never a symbol, nor does it make sense
to complete it any other way. */
{
- return_val = (char **) xmalloc (sizeof (char *));
- return_val[0] = NULL;
- return return_val;
+ return NULL;
}
else
{
sym_text_len = strlen (sym_text);
- return_val_size = 10;
- return_val_index = 0;
- return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
- return_val[0] = NULL;
+ return_val = NULL;
/* Find the symtab for SRCFILE (this loads it if it was not yet read
in). */
static void
add_filename_to_list (const char *fname, char *text, char *word,
- char ***list, int *list_used, int *list_alloced)
+ VEC (char_ptr) **list)
{
char *new;
size_t fnlen = strlen (fname);
- if (*list_used + 1 >= *list_alloced)
- {
- *list_alloced *= 2;
- *list = (char **) xrealloc ((char *) *list,
- *list_alloced * sizeof (char *));
- }
-
if (word == text)
{
/* Return exactly fname. */
new[text - word] = '\0';
strcat (new, fname);
}
- (*list)[*list_used] = new;
- (*list)[++*list_used] = NULL;
+ VEC_safe_push (char_ptr, *list, new);
}
static int
map_partial_symbol_filenames. */
struct add_partial_filename_data
{
- int *first;
+ struct filename_seen_cache *filename_seen_cache;
char *text;
char *word;
int text_len;
- char ***list;
- int *list_used;
- int *list_alloced;
+ VEC (char_ptr) **list;
};
/* A callback for map_partial_symbol_filenames. */
if (not_interesting_fname (filename))
return;
- if (!filename_seen (filename, 1, data->first)
+ if (!filename_seen (data->filename_seen_cache, filename, 1)
&& filename_ncmp (filename, data->text, data->text_len) == 0)
{
/* This file matches for a completion; add it to the
current list of matches. */
- add_filename_to_list (filename, data->text, data->word,
- data->list, data->list_used, data->list_alloced);
+ add_filename_to_list (filename, data->text, data->word, data->list);
}
else
{
const char *base_name = lbasename (filename);
if (base_name != filename
- && !filename_seen (base_name, 1, data->first)
+ && !filename_seen (data->filename_seen_cache, base_name, 1)
&& 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);
+ add_filename_to_list (base_name, data->text, data->word, data->list);
}
}
-/* Return a NULL terminated array of all source files whose names
- begin with matching TEXT. The file names are looked up in the
- symbol tables of this program. If the answer is no matchess, then
- the return value is an array which contains only a NULL pointer. */
+/* Return a vector of all source files whose names begin with matching
+ TEXT. The file names are looked up in the symbol tables of this
+ program. If the answer is no matchess, then the return value is
+ NULL. */
-char **
+VEC (char_ptr) *
make_source_files_completion_list (char *text, char *word)
{
struct symtab *s;
struct objfile *objfile;
- int first = 1;
- int list_alloced = 1;
- int list_used = 0;
size_t text_len = strlen (text);
- char **list = (char **) xmalloc (list_alloced * sizeof (char *));
+ VEC (char_ptr) *list = NULL;
const char *base_name;
struct add_partial_filename_data datum;
- struct cleanup *back_to;
-
- list[0] = NULL;
+ struct filename_seen_cache *filename_seen_cache;
+ struct cleanup *back_to, *cache_cleanup;
if (!have_full_symbols () && !have_partial_symbols ())
return list;
back_to = make_cleanup (do_free_completion_list, &list);
+ filename_seen_cache = create_filename_seen_cache ();
+ cache_cleanup = make_cleanup (delete_filename_seen_cache,
+ filename_seen_cache);
+
ALL_SYMTABS (objfile, s)
{
if (not_interesting_fname (s->filename))
continue;
- if (!filename_seen (s->filename, 1, &first)
+ if (!filename_seen (filename_seen_cache, s->filename, 1)
&& filename_ncmp (s->filename, text, text_len) == 0)
{
/* This file matches for a completion; add it to the current
list of matches. */
- add_filename_to_list (s->filename, text, word,
- &list, &list_used, &list_alloced);
+ add_filename_to_list (s->filename, text, word, &list);
}
else
{
command do when they parse file names. */
base_name = lbasename (s->filename);
if (base_name != s->filename
- && !filename_seen (base_name, 1, &first)
+ && !filename_seen (filename_seen_cache, base_name, 1)
&& filename_ncmp (base_name, text, text_len) == 0)
- add_filename_to_list (base_name, text, word,
- &list, &list_used, &list_alloced);
+ add_filename_to_list (base_name, text, word, &list);
}
}
- datum.first = &first;
+ datum.filename_seen_cache = filename_seen_cache;
datum.text = text;
datum.word = word;
datum.text_len = text_len;
datum.list = &list;
- datum.list_used = &list_used;
- datum.list_alloced = &list_alloced;
map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum,
0 /*need_fullname*/);
+
+ do_cleanups (cache_cleanup);
discard_cleanups (back_to);
return list;
line mark the prologue -> body transition. */
if (sal.line >= prologue_sal.line)
break;
+ /* Likewise if we are in a different symtab altogether
+ (e.g. within a file included via #include). */
+ if (sal.symtab != prologue_sal.symtab)
+ break;
/* The line number is smaller. Check that it's from the
same function, not something inlined. If it's inlined,
return prologue_sal.pc;
}
\f
-struct symtabs_and_lines
-decode_line_spec (char *string, int flags)
-{
- struct symtabs_and_lines sals;
- struct symtab_and_line cursal;
-
- if (string == 0)
- error (_("Empty line specification."));
-
- /* We use whatever is set as the current source line. We do not try
- and get a default or it will recursively call us! */
- 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;
-}
-
/* Track MAIN */
static char *name_of_main;
enum language language_of_main = language_unknown;
return;
}
+ new_main_name = go_main_name ();
+ if (new_main_name != NULL)
+ {
+ set_main_name (new_main_name);
+ return;
+ }
+
new_main_name = pascal_main_name ();
if (new_main_name != NULL)
{
NULL, NULL,
&setlist, &showlist);
+ add_setshow_boolean_cmd ("symtab-create", no_class, &symtab_create_debug,
+ _("Set debugging of symbol table creation."),
+ _("Show debugging of symbol table creation."), _("\
+When enabled, debugging messages are printed when building symbol tables."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
+
observer_attach_executable_changed (symtab_observer_executable_changed);
}