X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsymtab.c;h=68d654db2c97f955e63262572bc9fa576b31b803;hb=cfc594ee569f473094855682e5b2ec2738b0cf67;hp=318310a89673a29f6a3b03b136120687bd83e9b9;hpb=78e5175a52db89d5e51fdbcb020ef040f68fe5c1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/symtab.c b/gdb/symtab.c index 318310a896..68d654db2c 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1,6 +1,6 @@ /* 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. @@ -27,13 +27,11 @@ #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" @@ -63,6 +61,7 @@ #include "macroscope.h" #include "psymtab.h" +#include "parser-defs.h" /* Prototypes for local functions */ @@ -76,15 +75,13 @@ 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, 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, @@ -95,8 +92,7 @@ struct symbol *lookup_symbol_aux_local (const char *name, static struct symbol *lookup_symbol_aux_symtabs (int block_index, const char *name, - const domain_enum domain, - struct objfile *exclude_objfile); + const domain_enum domain); static struct symbol *lookup_symbol_aux_quick (struct objfile *objfile, @@ -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. */ @@ -147,15 +146,14 @@ 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. */ + describes what we advertise). 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) +compare_filenames_for_search (const char *filename, const char *search_name) { int len = strlen (filename); + size_t search_len = strlen (search_name); if (len < search_len) return 0; @@ -166,7 +164,12 @@ compare_filenames_for_search (const char *filename, const char *search_name, /* 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 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]) || (HAS_DRIVE_SPEC (filename) @@ -196,7 +199,6 @@ iterate_over_some_symtabs (const char *name, { struct symtab *s = NULL; 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) @@ -208,7 +210,7 @@ iterate_over_some_symtabs (const char *name, return 1; } - if (!is_abs && compare_filenames_for_search (s->filename, name, name_len)) + if (!is_abs && compare_filenames_for_search (s->filename, name)) { if (callback (s, data)) return 1; @@ -227,14 +229,13 @@ iterate_over_some_symtabs (const char *name, { const char *fp = symtab_to_fullname (s); - if (fp != NULL && FILENAME_CMP (full_path, fp) == 0) + if (FILENAME_CMP (full_path, fp) == 0) { if (callback (s, data)) return 1; } - if (fp != NULL && !is_abs && compare_filenames_for_search (fp, name, - name_len)) + if (!is_abs && compare_filenames_for_search (fp, name)) { if (callback (s, data)) return 1; @@ -243,25 +244,28 @@ iterate_over_some_symtabs (const char *name, if (real_path != NULL) { - char *fullname = symtab_to_fullname (s); + const char *fullname = symtab_to_fullname (s); + char *rp = gdb_realpath (fullname); + struct cleanup *cleanups = make_cleanup (xfree, rp); - if (fullname != NULL) - { - char *rp = gdb_realpath (fullname); - - make_cleanup (xfree, rp); - if (FILENAME_CMP (real_path, rp) == 0) + if (FILENAME_CMP (real_path, rp) == 0) + { + if (callback (s, data)) { - if (callback (s, data)) - return 1; + do_cleanups (cleanups); + return 1; } + } - if (!is_abs && compare_filenames_for_search (rp, name, name_len)) + if (!is_abs && compare_filenames_for_search (rp, name)) + { + if (callback (s, data)) { - if (callback (s, data)) - return 1; + do_cleanups (cleanups); + return 1; } - } + } + do_cleanups (cleanups); } } @@ -403,19 +407,20 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) 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); @@ -460,7 +465,7 @@ symbol_init_cplus_specific (struct general_symbol_info *gsymbol, void symbol_set_demangled_name (struct general_symbol_info *gsymbol, - char *name, + const char *name, struct objfile *objfile) { if (gsymbol->language == language_cplus) @@ -1224,7 +1229,7 @@ demangle_for_lookup (const char *name, enum language lang, 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; @@ -1242,7 +1247,8 @@ lookup_symbol_in_language (const char *name, const struct block *block, 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, @@ -1277,24 +1283,68 @@ lookup_language_this (const struct language_defn *lang, 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. */ @@ -1308,7 +1358,10 @@ lookup_symbol_aux (const char *name, const struct block *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); @@ -1328,11 +1381,8 @@ lookup_symbol_aux (const char *name, const struct block *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; } } @@ -1360,7 +1410,7 @@ lookup_static_symbol_aux (const char *name, const domain_enum domain) struct objfile *objfile; struct symbol *sym; - sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain, NULL); + sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain); if (sym != NULL) return sym; @@ -1513,10 +1563,6 @@ lookup_symbol_aux_objfile (struct objfile *objfile, int block_index, 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); @@ -1533,31 +1579,67 @@ lookup_symbol_aux_objfile (struct objfile *objfile, int block_index, } /* Same as lookup_symbol_aux_objfile, except that it searches all - objfiles except for EXCLUDE_OBJFILE. Return the first match found. - - If EXCLUDE_OBJFILE is NULL, then all objfiles are searched. */ + objfiles. Return the first match found. */ static struct symbol * lookup_symbol_aux_symtabs (int block_index, const char *name, - const domain_enum domain, - struct objfile *exclude_objfile) + const domain_enum domain) { struct symbol *sym; struct objfile *objfile; ALL_OBJFILES (objfile) { - if (objfile != exclude_objfile) - { - sym = lookup_symbol_aux_objfile (objfile, block_index, name, domain); - if (sym) - return sym; - } + 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. */ + +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) + { + do_cleanups (cleanup); + return sym; + } + } + + do_cleanups (cleanup); + return NULL; +} + /* A helper function for lookup_symbol_aux that interfaces with the "quick" symbol table functions. */ @@ -1669,6 +1751,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). */ @@ -1678,49 +1800,24 @@ lookup_symbol_global (const char *name, const domain_enum domain) { struct symbol *sym = NULL; - struct objfile *block_objfile = NULL; struct objfile *objfile = NULL; + struct global_sym_lookup_data lookup_data; /* Call library-specific lookup procedure. */ - block_objfile = lookup_objfile_from_block (block); - if (block_objfile != NULL) - sym = solib_global_lookup (block_objfile, name, domain); + objfile = lookup_objfile_from_block (block); + if (objfile != NULL) + sym = solib_global_lookup (objfile, name, domain); if (sym != NULL) return sym; - /* If BLOCK_OBJFILE is not NULL, then search this objfile first. - In case the global symbol is defined in multiple objfiles, - we have a better chance of finding the most relevant symbol. */ + 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); - if (block_objfile != NULL) - { - sym = lookup_symbol_aux_objfile (block_objfile, GLOBAL_BLOCK, - name, domain); - if (sym == NULL) - sym = lookup_symbol_aux_quick (block_objfile, GLOBAL_BLOCK, - name, domain); - if (sym != NULL) - return sym; - } - - /* Symbol not found in the BLOCK_OBJFILE, so try all the other - objfiles, starting with symtabs first, and then partial symtabs. */ - - sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain, block_objfile); - if (sym != NULL) - return sym; - - ALL_OBJFILES (objfile) - { - if (objfile != block_objfile) - { - sym = lookup_symbol_aux_quick (objfile, GLOBAL_BLOCK, name, domain); - if (sym) - return sym; - } - } - - return NULL; + return lookup_data.result; } int @@ -1823,11 +1920,6 @@ basic_lookup_transparent_type (const char *name) ALL_OBJFILES (objfile) { - if (objfile->sf) - objfile->sf->qf->pre_expand_symtabs_matching (objfile, - GLOBAL_BLOCK, - name, STRUCT_DOMAIN); - ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s) { bv = BLOCKVECTOR (s); @@ -1856,10 +1948,6 @@ basic_lookup_transparent_type (const char *name) ALL_OBJFILES (objfile) { - if (objfile->sf) - objfile->sf->qf->pre_expand_symtabs_matching (objfile, STATIC_BLOCK, - name, STRUCT_DOMAIN); - ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s) { bv = BLOCKVECTOR (s); @@ -2098,6 +2186,8 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section) if (best_s != NULL) return (best_s); + /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs). */ + ALL_OBJFILES (objfile) { struct symtab *result; @@ -2456,9 +2546,6 @@ find_line_symtab (struct symtab *symtab, int line, symtab->filename); } - /* Get symbol full file name if possible. */ - symtab_to_fullname (symtab); - ALL_SYMTABS (objfile, s) { struct linetable *l; @@ -2466,9 +2553,8 @@ find_line_symtab (struct symtab *symtab, int line, 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); @@ -2760,7 +2846,7 @@ skip_prologue_sal (struct symtab_and_line *sal) 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; @@ -3053,57 +3139,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 @@ -3115,20 +3237,16 @@ 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); @@ -3148,31 +3266,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, &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 @@ -3441,10 +3567,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)) { @@ -3452,6 +3582,9 @@ search_symbols (char *regexp, enum search_domain kind, { QUIT; + if (msymbol->created_by_gdb) + continue; + if (MSYMBOL_TYPE (msymbol) == ourtype || MSYMBOL_TYPE (msymbol) == ourtype2 || MSYMBOL_TYPE (msymbol) == ourtype3 @@ -3461,21 +3594,15 @@ search_symbols (char *regexp, enum search_domain kind, || 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; } } } @@ -3552,12 +3679,15 @@ search_symbols (char *regexp, enum search_domain kind, /* 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->created_by_gdb) + continue; + if (MSYMBOL_TYPE (msymbol) == ourtype || MSYMBOL_TYPE (msymbol) == ourtype2 || MSYMBOL_TYPE (msymbol) == ourtype3 @@ -3567,14 +3697,14 @@ search_symbols (char *regexp, enum search_domain kind, || 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 *) @@ -3683,10 +3813,11 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty) 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) { @@ -3696,7 +3827,7 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty) { if (first) { - printf_filtered ("\nNon-debugging symbols:\n"); + printf_filtered (_("\nNon-debugging symbols:\n")); first = 0; } print_msymbol_info (p->msymbol); @@ -3872,17 +4003,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. */ @@ -3895,9 +4023,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 \ @@ -3944,13 +4070,7 @@ completion_list_add_name (const char *symname, 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); } } @@ -4114,9 +4234,10 @@ expand_partial_symbol_name (const char *name, void *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) + 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 @@ -4169,9 +4290,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 { @@ -4207,10 +4326,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; @@ -4228,13 +4344,18 @@ default_make_symbol_completion_list_break_on (char *text, char *word, 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 @@ -4251,10 +4372,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word, 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 @@ -4267,13 +4395,16 @@ default_make_symbol_completion_list_break_on (char *text, char *word, /* 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. */ @@ -4284,7 +4415,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word, 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); } } @@ -4294,11 +4428,17 @@ default_make_symbol_completion_list_break_on (char *text, char *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; @@ -4325,26 +4465,41 @@ default_make_symbol_completion_list_break_on (char *text, char *word, 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) { @@ -4354,7 +4509,7 @@ 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; @@ -4400,9 +4555,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 { @@ -4413,10 +4566,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). */ @@ -4459,18 +4609,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. */ @@ -4491,8 +4634,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 @@ -4516,13 +4658,11 @@ 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. */ @@ -4535,63 +4675,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 { @@ -4601,22 +4738,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; @@ -4805,27 +4941,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; @@ -5000,5 +5115,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); }