Index: gdb/symtab.c |
diff --git a/gdb/symtab.c b/gdb/symtab.c |
index ab6a1aa40cbafe1054e76313b084c437fdc4cc1e..183e115712437e6ac6f68ce4a9b8ec5c85c95074 100644 |
--- a/gdb/symtab.c |
+++ b/gdb/symtab.c |
@@ -33,12 +33,12 @@ |
#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" |
@@ -65,8 +65,6 @@ |
/* Prototypes for local functions */ |
-static void completion_list_add_name (char *, char *, int, char *, char *); |
- |
static void rbreak_command (char *, int); |
static void types_info (char *, int); |
@@ -77,8 +75,6 @@ static void variables_info (char *, int); |
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, |
@@ -110,6 +106,9 @@ void _initialize_symtab (void); |
/* */ |
+/* 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. */ |
@@ -122,7 +121,7 @@ int basenames_may_differ = 0; |
const char multiple_symbols_ask[] = "ask"; |
const char multiple_symbols_all[] = "all"; |
const char multiple_symbols_cancel[] = "cancel"; |
-static const char *multiple_symbols_modes[] = |
+static const char *const multiple_symbols_modes[] = |
{ |
multiple_symbols_ask, |
multiple_symbols_all, |
@@ -145,6 +144,34 @@ multiple_symbols_select_mode (void) |
const struct block *block_found; |
+/* 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. */ |
+ |
+int |
+compare_filenames_for_search (const char *filename, const char *search_name, |
+ int search_len) |
+{ |
+ int len = strlen (filename); |
+ |
+ if (len < search_len) |
+ return 0; |
+ |
+ /* The tail of FILENAME must match. */ |
+ if (FILENAME_CMP (filename + len - search_len, search_name) != 0) |
+ return 0; |
+ |
+ /* Either the names must completely match, or the character |
+ preceding the trailing SEARCH_NAME segment of FILENAME must be a |
+ directory separator. */ |
+ return (len == search_len |
+ || 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. |
@@ -167,17 +194,25 @@ iterate_over_some_symtabs (const char *name, |
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 (callback (s, data)) |
+ return 1; |
+ } |
+ |
/* Before we invoke realpath, which can get expensive when many |
files are involved, do a quick comparison of the basenames. */ |
if (! basenames_may_differ |
@@ -196,6 +231,13 @@ iterate_over_some_symtabs (const char *name, |
if (callback (s, data)) |
return 1; |
} |
+ |
+ if (fp != NULL && !is_abs && compare_filenames_for_search (fp, name, |
+ name_len)) |
+ { |
+ if (callback (s, data)) |
+ return 1; |
+ } |
} |
if (real_path != NULL) |
@@ -212,24 +254,16 @@ iterate_over_some_symtabs (const char *name, |
if (callback (s, data)) |
return 1; |
} |
+ |
+ if (!is_abs && compare_filenames_for_search (rp, name, name_len)) |
+ { |
+ if (callback (s, data)) |
+ return 1; |
+ } |
} |
} |
} |
- /* Now, search for a matching tail (only if name doesn't have any dirs). */ |
- |
- if (lbasename (name) == name) |
- { |
- for (s = first; s != NULL && s != after_last; s = s->next) |
- { |
- if (FILENAME_CMP (lbasename (s->filename), name) == 0) |
- { |
- if (callback (s, data)) |
- return 1; |
- } |
- } |
- } |
- |
return 0; |
} |
@@ -329,9 +363,9 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) |
char *mangled_name; |
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); |
+ const char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id); |
const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id); |
- char *newname = type_name_no_tag (type); |
+ const char *newname = type_name_no_tag (type); |
/* Does the form of physname indicate that it is the full mangled name |
of a constructor (not just the args)? */ |
@@ -422,6 +456,7 @@ symbol_init_cplus_specific (struct general_symbol_info *gsymbol, |
correctly allocated. For C++ symbols a cplus_specific struct is |
allocated so OBJFILE must not be NULL. If this is a non C++ symbol |
OBJFILE can be NULL. */ |
+ |
void |
symbol_set_demangled_name (struct general_symbol_info *gsymbol, |
char *name, |
@@ -439,7 +474,8 @@ symbol_set_demangled_name (struct general_symbol_info *gsymbol, |
} |
/* Return the demangled name of GSYMBOL. */ |
-char * |
+ |
+const char * |
symbol_get_demangled_name (const struct general_symbol_info *gsymbol) |
{ |
if (gsymbol->language == language_cplus) |
@@ -456,12 +492,14 @@ symbol_get_demangled_name (const struct general_symbol_info *gsymbol) |
/* Initialize the language dependent portion of a symbol |
depending upon the language for the symbol. */ |
+ |
void |
symbol_set_language (struct general_symbol_info *gsymbol, |
enum language language) |
{ |
gsymbol->language = language; |
if (gsymbol->language == language_d |
+ || gsymbol->language == language_go |
|| gsymbol->language == language_java |
|| gsymbol->language == language_objc |
|| gsymbol->language == language_fortran) |
@@ -487,6 +525,7 @@ struct demangled_name_entry |
}; |
/* Hash function for the demangled name hash. */ |
+ |
static hashval_t |
hash_demangled_name_entry (const void *data) |
{ |
@@ -496,6 +535,7 @@ hash_demangled_name_entry (const void *data) |
} |
/* Equality function for the demangled name hash. */ |
+ |
static int |
eq_demangled_name_entry (const void *a, const void *b) |
{ |
@@ -580,6 +620,22 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol, |
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 |
@@ -644,12 +700,14 @@ symbol_set_names (struct general_symbol_info *gsymbol, |
name with the symbol, we don't need to use the same trick |
as Java. */ |
if (!copy_name) |
- gsymbol->name = (char *) linkage_name; |
+ gsymbol->name = linkage_name; |
else |
{ |
- gsymbol->name = obstack_alloc (&objfile->objfile_obstack, len + 1); |
- memcpy (gsymbol->name, linkage_name, len); |
- gsymbol->name[len] = '\0'; |
+ char *name = obstack_alloc (&objfile->objfile_obstack, len + 1); |
+ |
+ memcpy (name, linkage_name, len); |
+ name[len] = '\0'; |
+ gsymbol->name = name; |
} |
symbol_set_demangled_name (gsymbol, NULL, NULL); |
@@ -700,7 +758,11 @@ symbol_set_names (struct general_symbol_info *gsymbol, |
&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); |
@@ -755,13 +817,14 @@ symbol_set_names (struct general_symbol_info *gsymbol, |
/* Return the source code name of a symbol. In languages where |
demangling is necessary, this is the demangled name. */ |
-char * |
+const char * |
symbol_natural_name (const struct general_symbol_info *gsymbol) |
{ |
switch (gsymbol->language) |
{ |
case language_cplus: |
case language_d: |
+ case language_go: |
case language_java: |
case language_objc: |
case language_fortran: |
@@ -782,36 +845,39 @@ symbol_natural_name (const struct general_symbol_info *gsymbol) |
/* Return the demangled name for a symbol based on the language for |
that symbol. If no demangled name exists, return NULL. */ |
-char * |
+ |
+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 |
linkage name of the symbol, depending on how it will be searched for. |
If there is no distinct demangled name, then returns the same value |
(same pointer) as SYMBOL_LINKAGE_NAME. */ |
-char * |
+ |
+const char * |
symbol_search_name (const struct general_symbol_info *gsymbol) |
{ |
if (gsymbol->language == language_ada) |
@@ -821,6 +887,7 @@ symbol_search_name (const struct general_symbol_info *gsymbol) |
} |
/* Initialize the structure fields to zero values. */ |
+ |
void |
init_sal (struct symtab_and_line *sal) |
{ |
@@ -832,6 +899,7 @@ init_sal (struct symtab_and_line *sal) |
sal->end = 0; |
sal->explicit_pc = 0; |
sal->explicit_line = 0; |
+ sal->probe = NULL; |
} |
@@ -1078,7 +1146,7 @@ demangle_for_lookup (const char *name, enum language lang, |
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) |
{ |
@@ -1119,6 +1187,15 @@ demangle_for_lookup (const char *name, enum language lang, |
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; |
@@ -1133,11 +1210,11 @@ demangle_for_lookup (const char *name, enum language lang, |
BLOCK_FOUND is set to the block in which NAME is found (in the case of |
a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ |
-/* This function has a bunch of loops in it and it would seem to be |
- attractive to put in some QUIT's (though I'm not really sure |
- whether it can run long enough to be really important). But there |
+/* This function (or rather its subordinates) have a bunch of loops and |
+ it would seem to be attractive to put in some QUIT's (though I'm not really |
+ sure whether it can run long enough to be really important). But there |
are a few calls for which it would appear to be bad news to quit |
- out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note |
+ out of here: e.g., find_proc_desc in alpha-mdebug-tdep.c. (Note |
that there is C++ code below which can error(), but that probably |
doesn't affect these calls since they are looking for a known |
variable and thus can probably assume it will never hit the C++ |
@@ -1187,7 +1264,10 @@ lookup_language_this (const struct language_defn *lang, |
sym = lookup_block_symbol (block, lang->la_name_of_this, VAR_DOMAIN); |
if (sym != NULL) |
- return sym; |
+ { |
+ block_found = block; |
+ return sym; |
+ } |
if (BLOCK_FUNCTION (block)) |
break; |
block = BLOCK_SUPERBLOCK (block); |
@@ -1197,9 +1277,7 @@ lookup_language_this (const struct language_defn *lang, |
} |
/* Behave like lookup_symbol except that NAME is the natural name |
- of the symbol that we're looking for and, if LINKAGE_NAME is |
- non-NULL, ensure that the symbol's linkage name matches as |
- well. */ |
+ (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, |
@@ -1399,17 +1477,17 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile, |
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); |
@@ -1420,42 +1498,98 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile, |
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; |
+ |
+ if (objfile->sf) |
+ objfile->sf->qf->pre_expand_symtabs_matching (objfile, block_index, |
+ name, domain); |
+ |
+ 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; |
+ } |
+ |
+ 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. */ |
- ALL_OBJFILE_SYMTABS (objfile, s) |
- if (s->primary) |
+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; |
} |
@@ -1570,6 +1704,46 @@ lookup_symbol_static (const char *name, |
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). */ |
@@ -1580,6 +1754,7 @@ lookup_symbol_global (const char *name, |
{ |
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); |
@@ -1588,18 +1763,14 @@ lookup_symbol_global (const char *name, |
if (sym != NULL) |
return sym; |
- sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain); |
- if (sym != NULL) |
- 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); |
- ALL_OBJFILES (objfile) |
- { |
- sym = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK, name, domain); |
- if (sym) |
- return sym; |
- } |
- |
- return NULL; |
+ return lookup_data.result; |
} |
int |
@@ -1707,17 +1878,16 @@ basic_lookup_transparent_type (const char *name) |
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) |
@@ -1740,7 +1910,7 @@ basic_lookup_transparent_type (const char *name) |
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); |
@@ -1762,7 +1932,6 @@ basic_lookup_transparent_type (const char *name) |
return (struct type *) 0; |
} |
- |
/* Find the name of the file containing main(). */ |
/* FIXME: What about languages without main() or specially linked |
executables that have no main() ? */ |
@@ -1801,14 +1970,14 @@ struct symbol * |
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)) |
@@ -1826,9 +1995,9 @@ lookup_block_symbol (const struct block *block, const char *name, |
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)) |
@@ -1858,17 +2027,17 @@ lookup_block_symbol (const struct block *block, const char *name, |
void |
iterate_over_symbols (const struct block *block, const char *name, |
const domain_enum domain, |
- int (*callback) (struct symbol *, void *), |
+ symbol_found_callback_ftype *callback, |
void *data) |
{ |
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)) |
@@ -1958,7 +2127,7 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) |
} |
if (section != 0) |
{ |
- struct dict_iterator iter; |
+ struct block_iterator iter; |
struct symbol *sym = NULL; |
ALL_BLOCK_SYMBOLS (b, iter, sym) |
@@ -2554,7 +2723,8 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr) |
address for that function that has an entry in SYMTAB's line info |
table. If such an entry cannot be found, return FUNC_ADDR |
unaltered. */ |
-CORE_ADDR |
+ |
+static CORE_ADDR |
skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab) |
{ |
CORE_ADDR func_start, func_end; |
@@ -2625,6 +2795,7 @@ find_function_start_sal (struct symbol *sym, int funfirstline) |
If the PC was explicitly specified, the SAL is not changed. |
If the line number was explicitly specified, at most the SAL's PC |
is updated. If SAL is already past the prologue, then do nothing. */ |
+ |
void |
skip_prologue_sal (struct symtab_and_line *sal) |
{ |
@@ -2729,7 +2900,7 @@ skip_prologue_sal (struct symtab_and_line *sal) |
to `__main' in `main' between the prologue and before user |
code. */ |
if (gdbarch_skip_main_prologue_p (gdbarch) |
- && name && strcmp (name, "main") == 0) |
+ && name && strcmp_iw (name, "main") == 0) |
{ |
pc = gdbarch_skip_main_prologue (gdbarch, pc); |
/* Recalculate the line number (might not be N+1). */ |
@@ -2797,6 +2968,7 @@ skip_prologue_sal (struct symtab_and_line *sal) |
some legitimate operator text, return a pointer to the |
beginning of the substring of the operator text. |
Otherwise, return "". */ |
+ |
static char * |
operator_chars (char *p, char **end) |
{ |
@@ -2931,55 +3103,93 @@ operator_chars (char *p, char **end) |
} |
-/* 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 |
@@ -2991,26 +3201,23 @@ output_source_filename (const char *name, int *first) |
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); |
} |
/* A callback for map_partial_symbol_filenames. */ |
+ |
static void |
output_partial_symbol_filename (const char *filename, const char *fullname, |
void *data) |
@@ -3023,31 +3230,39 @@ sources_info (char *ignore, int from_tty) |
{ |
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 ? fullname : s->filename, &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); |
} |
static int |
@@ -3069,6 +3284,7 @@ file_matches (const char *file, char *files[], int nfiles) |
} |
/* Free any memory associated with a search. */ |
+ |
void |
free_search_symbols (struct symbol_search *symbols) |
{ |
@@ -3096,6 +3312,7 @@ make_cleanup_free_search_symbols (struct symbol_search *symbols) |
/* Helper function for sort_search_symbols and qsort. Can only |
sort symbols, not minimal symbols. */ |
+ |
static int |
compare_search_syms (const void *sa, const void *sb) |
{ |
@@ -3109,6 +3326,7 @@ compare_search_syms (const void *sa, const void *sb) |
/* Sort the ``nfound'' symbols in the list after prevtail. Leave |
prevtail where it is, but update its next pointer to point to |
the first of the sorted symbols. */ |
+ |
static struct symbol_search * |
sort_search_symbols (struct symbol_search *prevtail, int nfound) |
{ |
@@ -3154,6 +3372,7 @@ struct search_symbols_data |
}; |
/* A callback for expand_symtabs_matching. */ |
+ |
static int |
search_symbols_file_matches (const char *filename, void *user_data) |
{ |
@@ -3163,9 +3382,9 @@ search_symbols_file_matches (const char *filename, void *user_data) |
} |
/* A callback for expand_symtabs_matching. */ |
+ |
static int |
-search_symbols_name_matches (const struct language_defn *language, |
- const char *symname, void *user_data) |
+search_symbols_name_matches (const char *symname, void *user_data) |
{ |
struct search_symbols_data *data = user_data; |
@@ -3196,11 +3415,10 @@ search_symbols (char *regexp, enum search_domain kind, |
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}; |
@@ -3296,7 +3514,9 @@ search_symbols (char *regexp, enum search_domain kind, |
{ |
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); |
@@ -3311,10 +3531,14 @@ search_symbols (char *regexp, enum search_domain kind, |
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)) |
{ |
@@ -3322,30 +3546,27 @@ search_symbols (char *regexp, enum search_domain kind, |
{ |
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; |
} |
} |
} |
@@ -3354,97 +3575,100 @@ search_symbols (char *regexp, enum search_domain kind, |
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; |
+ |
+ 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; |
- 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 *) |
@@ -3498,9 +3722,9 @@ print_symbol_info (enum search_domain kind, |
&& 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 |
@@ -3742,17 +3966,14 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len) |
/* 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. */ |
@@ -3765,9 +3986,7 @@ do_free_completion_list (void *list) |
/* 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 \ |
@@ -3778,8 +3997,9 @@ static char **return_val; |
characters. If so, add it to the current completion list. */ |
static void |
-completion_list_add_name (char *symname, char *sym_text, int sym_text_len, |
- char *text, char *word) |
+completion_list_add_name (const char *symname, |
+ const char *sym_text, int sym_text_len, |
+ const char *text, const char *word) |
{ |
int newsize; |
@@ -3813,13 +4033,7 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len, |
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); |
} |
} |
@@ -3827,13 +4041,14 @@ completion_list_add_name (char *symname, char *sym_text, int sym_text_len, |
again and feed all the selectors into the mill. */ |
static void |
-completion_list_objc_symbol (struct minimal_symbol *msymbol, char *sym_text, |
- int sym_text_len, char *text, char *word) |
+completion_list_objc_symbol (struct minimal_symbol *msymbol, |
+ const char *sym_text, int sym_text_len, |
+ const char *text, const char *word) |
{ |
static char *tmp = NULL; |
static unsigned int tmplen = 0; |
- char *method, *category, *selector; |
+ const char *method, *category, *selector; |
char *tmp2 = NULL; |
method = SYMBOL_NATURAL_NAME (msymbol); |
@@ -3959,6 +4174,7 @@ struct add_name_data |
/* A callback used with macro_for_each and macro_for_each_in_scope. |
This adds a macro's name to the current completion list. */ |
+ |
static void |
add_macro_name (const char *name, const struct macro_definition *ignore, |
struct macro_source_file *ignore2, int ignore3, |
@@ -3972,16 +4188,16 @@ add_macro_name (const char *name, const struct macro_definition *ignore, |
} |
/* A callback for expand_partial_symbol_names. */ |
+ |
static int |
-expand_partial_symbol_name (const struct language_defn *language, |
- const char *name, void *user_data) |
+expand_partial_symbol_name (const char *name, void *user_data) |
{ |
struct add_name_data *datum = (struct add_name_data *) user_data; |
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) |
{ |
@@ -3995,7 +4211,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, |
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. */ |
@@ -4036,9 +4252,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, |
/* 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 |
{ |
@@ -4074,10 +4288,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, |
} |
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; |
@@ -4192,17 +4403,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word, |
return (return_val); |
} |
-char ** |
+VEC (char_ptr) * |
default_make_symbol_completion_list (char *text, char *word) |
{ |
return default_make_symbol_completion_list_break_on (text, word, ""); |
} |
-/* 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); |
@@ -4211,7 +4422,7 @@ make_symbol_completion_list (char *text, char *word) |
/* 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) |
{ |
@@ -4221,13 +4432,13 @@ make_symbol_completion_list_fn (struct cmd_list_element *ignore, |
/* 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. */ |
@@ -4267,9 +4478,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile) |
/* 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 |
{ |
@@ -4280,10 +4489,7 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile) |
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). */ |
@@ -4326,18 +4532,11 @@ make_file_symbol_completion_list (char *text, char *word, char *srcfile) |
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. */ |
@@ -4358,8 +4557,7 @@ add_filename_to_list (const char *fname, char *text, char *word, |
new[text - word] = '\0'; |
strcat (new, fname); |
} |
- (*list)[*list_used] = new; |
- (*list)[++*list_used] = NULL; |
+ VEC_safe_push (char_ptr, *list, new); |
} |
static int |
@@ -4383,16 +4581,15 @@ not_interesting_fname (const char *fname) |
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. */ |
+ |
static void |
maybe_add_partial_symtab_filename (const char *filename, const char *fullname, |
void *user_data) |
@@ -4401,63 +4598,60 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname, |
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 |
{ |
@@ -4467,22 +4661,21 @@ make_source_files_completion_list (char *text, char *word) |
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; |
@@ -4671,27 +4864,6 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) |
return prologue_sal.pc; |
} |
-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; |
@@ -4743,6 +4915,13 @@ find_main_name (void) |
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) |
{ |
@@ -4859,5 +5038,13 @@ one base name, and gdb will do file name comparisons more efficiently."), |
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); |
} |