/* Symbol table lookup for the GNU debugger, GDB.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
const domain_enum domain,
enum language language);
-static
-struct symbol *lookup_symbol_via_quick_fns (struct objfile *objfile,
- int block_index,
- const char *name,
- const domain_enum domain);
+static struct symbol *
+ lookup_symbol_in_objfile (struct objfile *objfile, int block_index,
+ const char *name, const domain_enum domain);
extern initialize_file_ftype _initialize_symtab;
enum language language_of_main;
};
+/* Program space key for finding its symbol cache. */
+
+static const struct program_space_data *symbol_cache_key;
+
+/* The default symbol cache size.
+ There is no extra cpu cost for large N (except when flushing the cache,
+ which is rare). The value here is just a first attempt. A better default
+ value may be higher or lower. A prime number can make up for a bad hash
+ computation, so that's why the number is what it is. */
+#define DEFAULT_SYMBOL_CACHE_SIZE 1021
+
+/* The maximum symbol cache size.
+ There's no method to the decision of what value to use here, other than
+ there's no point in allowing a user typo to make gdb consume all memory. */
+#define MAX_SYMBOL_CACHE_SIZE (1024*1024)
+
+/* symbol_cache_lookup returns this if a previous lookup failed to find the
+ symbol in any objfile. */
+#define SYMBOL_LOOKUP_FAILED ((struct symbol *) 1)
+
+/* Recording lookups that don't find the symbol is just as important, if not
+ more so, than recording found symbols. */
+
+enum symbol_cache_slot_state
+{
+ SYMBOL_SLOT_UNUSED,
+ SYMBOL_SLOT_NOT_FOUND,
+ SYMBOL_SLOT_FOUND
+};
+
+/* Symbols don't specify global vs static block.
+ So keep them in separate caches. */
+
+struct block_symbol_cache
+{
+ unsigned int hits;
+ unsigned int misses;
+ unsigned int collisions;
+
+ /* SYMBOLS is a variable length array of this size.
+ One can imagine that in general one cache (global/static) should be a
+ fraction of the size of the other, but there's no data at the moment
+ on which to decide. */
+ unsigned int size;
+
+ struct symbol_cache_slot
+ {
+ enum symbol_cache_slot_state state;
+
+ /* The objfile that was current when the symbol was looked up.
+ This is only needed for global blocks, but for simplicity's sake
+ we allocate the space for both. If data shows the extra space used
+ for static blocks is a problem, we can split things up then.
+
+ Global blocks need cache lookup to include the objfile context because
+ we need to account for gdbarch_iterate_over_objfiles_in_search_order
+ which can traverse objfiles in, effectively, any order, depending on
+ the current objfile, thus affecting which symbol is found. Normally,
+ only the current objfile is searched first, and then the rest are
+ searched in recorded order; but putting cache lookup inside
+ gdbarch_iterate_over_objfiles_in_search_order would be awkward.
+ Instead we just make the current objfile part of the context of
+ cache lookup. This means we can record the same symbol multiple times,
+ each with a different "current objfile" that was in effect when the
+ lookup was saved in the cache, but cache space is pretty cheap. */
+ const struct objfile *objfile_context;
+
+ union
+ {
+ struct symbol *found;
+ struct
+ {
+ char *name;
+ domain_enum domain;
+ } not_found;
+ } value;
+ } symbols[1];
+};
+
+/* The symbol cache.
+
+ Searching for symbols in the static and global blocks over multiple objfiles
+ again and again can be slow, as can searching very big objfiles. This is a
+ simple cache to improve symbol lookup performance, which is critical to
+ overall gdb performance.
+
+ Symbols are hashed on the name, its domain, and block.
+ They are also hashed on their objfile for objfile-specific lookups. */
+
+struct symbol_cache
+{
+ struct block_symbol_cache *global_symbols;
+ struct block_symbol_cache *static_symbols;
+};
+
/* When non-zero, print debugging messages related to symtab creation. */
unsigned int symtab_create_debug = 0;
+/* When non-zero, print debugging messages related to symbol lookup. */
+unsigned int symbol_lookup_debug = 0;
+
+/* The size of the cache is staged here. */
+static unsigned int new_symbol_cache_size = DEFAULT_SYMBOL_CACHE_SIZE;
+
+/* The current value of the symbol cache size.
+ This is saved so that if the user enters a value too big we can restore
+ the original value from here. */
+static unsigned int symbol_cache_size = DEFAULT_SYMBOL_CACHE_SIZE;
+
/* 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. */
case UNDEF_DOMAIN: return "UNDEF_DOMAIN";
case VAR_DOMAIN: return "VAR_DOMAIN";
case STRUCT_DOMAIN: return "STRUCT_DOMAIN";
+ case MODULE_DOMAIN: return "MODULE_DOMAIN";
case LABEL_DOMAIN: return "LABEL_DOMAIN";
case COMMON_BLOCK_DOMAIN: return "COMMON_BLOCK_DOMAIN";
default: gdb_assert_not_reached ("bad domain_enum");
}
}
-/* Set the primary field in SYMTAB. */
+/* See symtab.h. */
-void
-set_symtab_primary (struct symtab *symtab, int primary)
+struct symtab *
+compunit_primary_filetab (const struct compunit_symtab *cust)
{
- symtab->primary = primary;
+ gdb_assert (COMPUNIT_FILETABS (cust) != NULL);
- if (symtab_create_debug && primary)
- {
- fprintf_unfiltered (gdb_stdlog,
- "Created primary symtab %s for %s.\n",
- host_address_to_string (symtab),
- symtab_to_filename_for_display (symtab));
- }
+ /* The primary file symtab is the first one in the list. */
+ return COMPUNIT_FILETABS (cust);
+}
+
+/* See symtab.h. */
+
+enum language
+compunit_language (const struct compunit_symtab *cust)
+{
+ struct symtab *symtab = compunit_primary_filetab (cust);
+
+/* The language of the compunit symtab is the language of its primary
+ source file. */
+ return SYMTAB_LANGUAGE (symtab);
}
/* See whether FILENAME matches SEARCH_NAME using the rule that we
are identical to the `map_symtabs_matching_filename' method of
quick_symbol_functions.
- FIRST and AFTER_LAST indicate the range of symtabs to search.
- AFTER_LAST is one past the last symtab to search; NULL means to
+ FIRST and AFTER_LAST indicate the range of compunit symtabs to search.
+ Each symtab within the specified compunit symtab is also searched.
+ AFTER_LAST is one past the last compunit symtab to search; NULL means to
search until the end of the list. */
int
int (*callback) (struct symtab *symtab,
void *data),
void *data,
- struct symtab *first,
- struct symtab *after_last)
+ struct compunit_symtab *first,
+ struct compunit_symtab *after_last)
{
- struct symtab *s = NULL;
+ struct compunit_symtab *cust;
+ struct symtab *s;
const char* base_name = lbasename (name);
- for (s = first; s != NULL && s != after_last; s = s->next)
+ for (cust = first; cust != NULL && cust != after_last; cust = cust->next)
{
- if (compare_filenames_for_search (s->filename, name))
- {
- if (callback (s, data))
- return 1;
- continue;
- }
-
- /* Before we invoke realpath, which can get expensive when many
- files are involved, do a quick comparison of the basenames. */
- if (! basenames_may_differ
- && FILENAME_CMP (base_name, lbasename (s->filename)) != 0)
- continue;
-
- if (compare_filenames_for_search (symtab_to_fullname (s), name))
+ ALL_COMPUNIT_FILETABS (cust, s)
{
- if (callback (s, data))
- return 1;
- continue;
- }
+ if (compare_filenames_for_search (s->filename, name))
+ {
+ if (callback (s, data))
+ return 1;
+ continue;
+ }
- /* If the user gave us an absolute path, try to find the file in
- this symtab and use its absolute path. */
- if (real_path != NULL)
- {
- const char *fullname = symtab_to_fullname (s);
+ /* Before we invoke realpath, which can get expensive when many
+ files are involved, do a quick comparison of the basenames. */
+ if (! basenames_may_differ
+ && FILENAME_CMP (base_name, lbasename (s->filename)) != 0)
+ continue;
- gdb_assert (IS_ABSOLUTE_PATH (real_path));
- gdb_assert (IS_ABSOLUTE_PATH (name));
- if (FILENAME_CMP (real_path, fullname) == 0)
+ if (compare_filenames_for_search (symtab_to_fullname (s), name))
{
if (callback (s, data))
return 1;
continue;
}
+
+ /* If the user gave us an absolute path, try to find the file in
+ this symtab and use its absolute path. */
+ if (real_path != NULL)
+ {
+ const char *fullname = symtab_to_fullname (s);
+
+ gdb_assert (IS_ABSOLUTE_PATH (real_path));
+ gdb_assert (IS_ABSOLUTE_PATH (name));
+ if (FILENAME_CMP (real_path, fullname) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ continue;
+ }
+ }
}
}
ALL_OBJFILES (objfile)
{
if (iterate_over_some_symtabs (name, real_path, callback, data,
- objfile->symtabs, NULL))
+ objfile->compunit_symtabs, NULL))
{
do_cleanups (cleanups);
return;
return (mangled_name);
}
-/* Initialize the cplus_specific structure. 'cplus_specific' should
- only be allocated for use with cplus symbols. */
-
-static void
-symbol_init_cplus_specific (struct general_symbol_info *gsymbol,
- struct obstack *obstack)
-{
- /* A language_specific structure should not have been previously
- initialized. */
- gdb_assert (gsymbol->language_specific.cplus_specific == NULL);
- gdb_assert (obstack != NULL);
-
- gsymbol->language_specific.cplus_specific =
- OBSTACK_ZALLOC (obstack, struct cplus_specific);
-}
-
/* Set the demangled name of GSYMBOL to NAME. NAME must be already
- 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. */
+ correctly allocated. */
void
symbol_set_demangled_name (struct general_symbol_info *gsymbol,
const char *name,
struct obstack *obstack)
{
- if (gsymbol->language == language_cplus)
- {
- if (gsymbol->language_specific.cplus_specific == NULL)
- symbol_init_cplus_specific (gsymbol, obstack);
-
- gsymbol->language_specific.cplus_specific->demangled_name = name;
- }
- else if (gsymbol->language == language_ada)
+ if (gsymbol->language == language_ada)
{
if (name == NULL)
{
const char *
symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
{
- if (gsymbol->language == language_cplus)
- {
- if (gsymbol->language_specific.cplus_specific != NULL)
- return gsymbol->language_specific.cplus_specific->demangled_name;
- else
- return NULL;
- }
- else if (gsymbol->language == language_ada)
+ if (gsymbol->language == language_ada)
{
if (!gsymbol->ada_mangled)
return NULL;
struct obstack *obstack)
{
gsymbol->language = language;
- if (gsymbol->language == language_d
+ if (gsymbol->language == language_cplus
+ || gsymbol->language == language_d
|| gsymbol->language == language_go
|| gsymbol->language == language_java
|| gsymbol->language == language_objc
gdb_assert (gsymbol->ada_mangled == 0);
gsymbol->language_specific.obstack = obstack;
}
- else if (gsymbol->language == language_cplus)
- gsymbol->language_specific.cplus_specific = NULL;
else
{
memset (&gsymbol->language_specific, 0,
ALL_OBJFILES (objfile)
{
- struct symtab *s = NULL;
+ struct compunit_symtab *cust = NULL;
if (objfile->sf)
- s = objfile->sf->qf->find_pc_sect_symtab (objfile, msymbol,
- pc, section, 0);
- if (s != NULL)
+ cust = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile, msymbol,
+ pc, section, 0);
+ if (cust)
return;
}
}
\f
+/* Hash function for the symbol cache. */
+
+static unsigned int
+hash_symbol_entry (const struct objfile *objfile_context,
+ const char *name, domain_enum domain)
+{
+ unsigned int hash = (uintptr_t) objfile_context;
+
+ if (name != NULL)
+ hash += htab_hash_string (name);
+
+ hash += domain;
+
+ return hash;
+}
+
+/* Equality function for the symbol cache. */
+
+static int
+eq_symbol_entry (const struct symbol_cache_slot *slot,
+ const struct objfile *objfile_context,
+ const char *name, domain_enum domain)
+{
+ const char *slot_name;
+ domain_enum slot_domain;
+
+ if (slot->state == SYMBOL_SLOT_UNUSED)
+ return 0;
+
+ if (slot->objfile_context != objfile_context)
+ return 0;
+
+ if (slot->state == SYMBOL_SLOT_NOT_FOUND)
+ {
+ slot_name = slot->value.not_found.name;
+ slot_domain = slot->value.not_found.domain;
+ }
+ else
+ {
+ slot_name = SYMBOL_SEARCH_NAME (slot->value.found);
+ slot_domain = SYMBOL_DOMAIN (slot->value.found);
+ }
+
+ /* NULL names match. */
+ if (slot_name == NULL && name == NULL)
+ {
+ /* But there's no point in calling symbol_matches_domain in the
+ SYMBOL_SLOT_FOUND case. */
+ if (slot_domain != domain)
+ return 0;
+ }
+ else if (slot_name != NULL && name != NULL)
+ {
+ /* It's important that we use the same comparison that was done the
+ first time through. If the slot records a found symbol, then this
+ means using strcmp_iw on SYMBOL_SEARCH_NAME. See dictionary.c.
+ It also means using symbol_matches_domain for found symbols.
+ See block.c.
+
+ If the slot records a not-found symbol, then require a precise match.
+ We could still be lax with whitespace like strcmp_iw though. */
+
+ if (slot->state == SYMBOL_SLOT_NOT_FOUND)
+ {
+ if (strcmp (slot_name, name) != 0)
+ return 0;
+ if (slot_domain != domain)
+ return 0;
+ }
+ else
+ {
+ struct symbol *sym = slot->value.found;
+
+ if (strcmp_iw (slot_name, name) != 0)
+ return 0;
+ if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+ slot_domain, domain))
+ return 0;
+ }
+ }
+ else
+ {
+ /* Only one name is NULL. */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Given a cache of size SIZE, return the size of the struct (with variable
+ length array) in bytes. */
+
+static size_t
+symbol_cache_byte_size (unsigned int size)
+{
+ return (sizeof (struct block_symbol_cache)
+ + ((size - 1) * sizeof (struct symbol_cache_slot)));
+}
+
+/* Resize CACHE. */
+
+static void
+resize_symbol_cache (struct symbol_cache *cache, unsigned int new_size)
+{
+ /* If there's no change in size, don't do anything.
+ All caches have the same size, so we can just compare with the size
+ of the global symbols cache. */
+ if ((cache->global_symbols != NULL
+ && cache->global_symbols->size == new_size)
+ || (cache->global_symbols == NULL
+ && new_size == 0))
+ return;
+
+ xfree (cache->global_symbols);
+ xfree (cache->static_symbols);
+
+ if (new_size == 0)
+ {
+ cache->global_symbols = NULL;
+ cache->static_symbols = NULL;
+ }
+ else
+ {
+ size_t total_size = symbol_cache_byte_size (new_size);
+
+ cache->global_symbols = xcalloc (1, total_size);
+ cache->static_symbols = xcalloc (1, total_size);
+ cache->global_symbols->size = new_size;
+ cache->static_symbols->size = new_size;
+ }
+}
+
+/* Make a symbol cache of size SIZE. */
+
+static struct symbol_cache *
+make_symbol_cache (unsigned int size)
+{
+ struct symbol_cache *cache;
+
+ cache = XCNEW (struct symbol_cache);
+ resize_symbol_cache (cache, symbol_cache_size);
+ return cache;
+}
+
+/* Free the space used by CACHE. */
+
+static void
+free_symbol_cache (struct symbol_cache *cache)
+{
+ xfree (cache->global_symbols);
+ xfree (cache->static_symbols);
+ xfree (cache);
+}
+
+/* Return the symbol cache of PSPACE.
+ Create one if it doesn't exist yet. */
+
+static struct symbol_cache *
+get_symbol_cache (struct program_space *pspace)
+{
+ struct symbol_cache *cache = program_space_data (pspace, symbol_cache_key);
+
+ if (cache == NULL)
+ {
+ cache = make_symbol_cache (symbol_cache_size);
+ set_program_space_data (pspace, symbol_cache_key, cache);
+ }
+
+ return cache;
+}
+
+/* Delete the symbol cache of PSPACE.
+ Called when PSPACE is destroyed. */
+
+static void
+symbol_cache_cleanup (struct program_space *pspace, void *data)
+{
+ struct symbol_cache *cache = data;
+
+ free_symbol_cache (cache);
+}
+
+/* Set the size of the symbol cache in all program spaces. */
+
+static void
+set_symbol_cache_size (unsigned int new_size)
+{
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ struct symbol_cache *cache
+ = program_space_data (pspace, symbol_cache_key);
+
+ /* The pspace could have been created but not have a cache yet. */
+ if (cache != NULL)
+ resize_symbol_cache (cache, new_size);
+ }
+}
+
+/* Called when symbol-cache-size is set. */
+
+static void
+set_symbol_cache_size_handler (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ if (new_symbol_cache_size > MAX_SYMBOL_CACHE_SIZE)
+ {
+ /* Restore the previous value.
+ This is the value the "show" command prints. */
+ new_symbol_cache_size = symbol_cache_size;
+
+ error (_("Symbol cache size is too large, max is %u."),
+ MAX_SYMBOL_CACHE_SIZE);
+ }
+ symbol_cache_size = new_symbol_cache_size;
+
+ set_symbol_cache_size (symbol_cache_size);
+}
+
+/* Lookup symbol NAME,DOMAIN in BLOCK in the symbol cache of PSPACE.
+ OBJFILE_CONTEXT is the current objfile, which may be NULL.
+ The result is the symbol if found, SYMBOL_LOOKUP_FAILED if a previous lookup
+ failed (and thus this one will too), or NULL if the symbol is not present
+ in the cache.
+ *BSC_PTR, *SLOT_PTR are set to the cache and slot of the symbol, whether
+ found or not found. */
+
+static struct symbol *
+symbol_cache_lookup (struct symbol_cache *cache,
+ struct objfile *objfile_context, int block,
+ const char *name, domain_enum domain,
+ struct block_symbol_cache **bsc_ptr,
+ struct symbol_cache_slot **slot_ptr)
+{
+ struct block_symbol_cache *bsc;
+ unsigned int hash;
+ struct symbol_cache_slot *slot;
+
+ if (block == GLOBAL_BLOCK)
+ bsc = cache->global_symbols;
+ else
+ bsc = cache->static_symbols;
+ if (bsc == NULL)
+ {
+ *bsc_ptr = NULL;
+ *slot_ptr = NULL;
+ return NULL;
+ }
+
+ hash = hash_symbol_entry (objfile_context, name, domain);
+ slot = bsc->symbols + hash % bsc->size;
+ *bsc_ptr = bsc;
+ *slot_ptr = slot;
+
+ if (eq_symbol_entry (slot, objfile_context, name, domain))
+ {
+ if (symbol_lookup_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "%s block symbol cache hit%s for %s, %s\n",
+ block == GLOBAL_BLOCK ? "Global" : "Static",
+ slot->state == SYMBOL_SLOT_NOT_FOUND
+ ? " (not found)" : "",
+ name, domain_name (domain));
+ ++bsc->hits;
+ if (slot->state == SYMBOL_SLOT_NOT_FOUND)
+ return SYMBOL_LOOKUP_FAILED;
+ return slot->value.found;
+ }
+
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "%s block symbol cache miss for %s, %s\n",
+ block == GLOBAL_BLOCK ? "Global" : "Static",
+ name, domain_name (domain));
+ }
+ ++bsc->misses;
+ return NULL;
+}
+
+/* Clear out SLOT. */
+
+static void
+symbol_cache_clear_slot (struct symbol_cache_slot *slot)
+{
+ if (slot->state == SYMBOL_SLOT_NOT_FOUND)
+ xfree (slot->value.not_found.name);
+ slot->state = SYMBOL_SLOT_UNUSED;
+}
+
+/* Mark SYMBOL as found in SLOT.
+ OBJFILE_CONTEXT is the current objfile when the lookup was done, or NULL
+ if it's not needed to distinguish lookups (STATIC_BLOCK). It is *not*
+ necessarily the objfile the symbol was found in. */
+
+static void
+symbol_cache_mark_found (struct block_symbol_cache *bsc,
+ struct symbol_cache_slot *slot,
+ struct objfile *objfile_context,
+ struct symbol *symbol)
+{
+ if (bsc == NULL)
+ return;
+ if (slot->state != SYMBOL_SLOT_UNUSED)
+ {
+ ++bsc->collisions;
+ symbol_cache_clear_slot (slot);
+ }
+ slot->state = SYMBOL_SLOT_FOUND;
+ slot->objfile_context = objfile_context;
+ slot->value.found = symbol;
+}
+
+/* Mark symbol NAME, DOMAIN as not found in SLOT.
+ OBJFILE_CONTEXT is the current objfile when the lookup was done, or NULL
+ if it's not needed to distinguish lookups (STATIC_BLOCK). */
+
+static void
+symbol_cache_mark_not_found (struct block_symbol_cache *bsc,
+ struct symbol_cache_slot *slot,
+ struct objfile *objfile_context,
+ const char *name, domain_enum domain)
+{
+ if (bsc == NULL)
+ return;
+ if (slot->state != SYMBOL_SLOT_UNUSED)
+ {
+ ++bsc->collisions;
+ symbol_cache_clear_slot (slot);
+ }
+ slot->state = SYMBOL_SLOT_NOT_FOUND;
+ slot->objfile_context = objfile_context;
+ slot->value.not_found.name = xstrdup (name);
+ slot->value.not_found.domain = domain;
+}
+
+/* Flush the symbol cache of PSPACE. */
+
+static void
+symbol_cache_flush (struct program_space *pspace)
+{
+ struct symbol_cache *cache = program_space_data (pspace, symbol_cache_key);
+ int pass;
+ size_t total_size;
+
+ if (cache == NULL)
+ return;
+ if (cache->global_symbols == NULL)
+ {
+ gdb_assert (symbol_cache_size == 0);
+ gdb_assert (cache->static_symbols == NULL);
+ return;
+ }
+
+ /* If the cache is untouched since the last flush, early exit.
+ This is important for performance during the startup of a program linked
+ with 100s (or 1000s) of shared libraries. */
+ if (cache->global_symbols->misses == 0
+ && cache->static_symbols->misses == 0)
+ return;
+
+ gdb_assert (cache->global_symbols->size == symbol_cache_size);
+ gdb_assert (cache->static_symbols->size == symbol_cache_size);
+
+ for (pass = 0; pass < 2; ++pass)
+ {
+ struct block_symbol_cache *bsc
+ = pass == 0 ? cache->global_symbols : cache->static_symbols;
+ unsigned int i;
+
+ for (i = 0; i < bsc->size; ++i)
+ symbol_cache_clear_slot (&bsc->symbols[i]);
+ }
+
+ cache->global_symbols->hits = 0;
+ cache->global_symbols->misses = 0;
+ cache->global_symbols->collisions = 0;
+ cache->static_symbols->hits = 0;
+ cache->static_symbols->misses = 0;
+ cache->static_symbols->collisions = 0;
+}
+
+/* Dump CACHE. */
+
+static void
+symbol_cache_dump (const struct symbol_cache *cache)
+{
+ int pass;
+
+ if (cache->global_symbols == NULL)
+ {
+ printf_filtered (" <disabled>\n");
+ return;
+ }
+
+ for (pass = 0; pass < 2; ++pass)
+ {
+ const struct block_symbol_cache *bsc
+ = pass == 0 ? cache->global_symbols : cache->static_symbols;
+ unsigned int i;
+
+ if (pass == 0)
+ printf_filtered ("Global symbols:\n");
+ else
+ printf_filtered ("Static symbols:\n");
+
+ for (i = 0; i < bsc->size; ++i)
+ {
+ const struct symbol_cache_slot *slot = &bsc->symbols[i];
+
+ QUIT;
+
+ switch (slot->state)
+ {
+ case SYMBOL_SLOT_UNUSED:
+ break;
+ case SYMBOL_SLOT_NOT_FOUND:
+ printf_filtered (" [%-4u] = %s, %s (not found)\n", i,
+ host_address_to_string (slot->objfile_context),
+ slot->value.not_found.name);
+ break;
+ case SYMBOL_SLOT_FOUND:
+ printf_filtered (" [%-4u] = %s, %s\n", i,
+ host_address_to_string (slot->objfile_context),
+ SYMBOL_PRINT_NAME (slot->value.found));
+ break;
+ }
+ }
+ }
+}
+
+/* The "mt print symbol-cache" command. */
+
+static void
+maintenance_print_symbol_cache (char *args, int from_tty)
+{
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ struct symbol_cache *cache;
+
+ printf_filtered (_("Symbol cache for pspace %d\n%s:\n"),
+ pspace->num,
+ pspace->symfile_object_file != NULL
+ ? objfile_name (pspace->symfile_object_file)
+ : "(no object file)");
+
+ /* If the cache hasn't been created yet, avoid creating one. */
+ cache = program_space_data (pspace, symbol_cache_key);
+ if (cache == NULL)
+ printf_filtered (" <empty>\n");
+ else
+ symbol_cache_dump (cache);
+ }
+}
+
+/* The "mt flush-symbol-cache" command. */
+
+static void
+maintenance_flush_symbol_cache (char *args, int from_tty)
+{
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ symbol_cache_flush (pspace);
+ }
+}
+
+/* Print usage statistics of CACHE. */
+
+static void
+symbol_cache_stats (struct symbol_cache *cache)
+{
+ int pass;
+
+ if (cache->global_symbols == NULL)
+ {
+ printf_filtered (" <disabled>\n");
+ return;
+ }
+
+ for (pass = 0; pass < 2; ++pass)
+ {
+ const struct block_symbol_cache *bsc
+ = pass == 0 ? cache->global_symbols : cache->static_symbols;
+
+ QUIT;
+
+ if (pass == 0)
+ printf_filtered ("Global block cache stats:\n");
+ else
+ printf_filtered ("Static block cache stats:\n");
+
+ printf_filtered (" size: %u\n", bsc->size);
+ printf_filtered (" hits: %u\n", bsc->hits);
+ printf_filtered (" misses: %u\n", bsc->misses);
+ printf_filtered (" collisions: %u\n", bsc->collisions);
+ }
+}
+
+/* The "mt print symbol-cache-statistics" command. */
+
+static void
+maintenance_print_symbol_cache_statistics (char *args, int from_tty)
+{
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ struct symbol_cache *cache;
+
+ printf_filtered (_("Symbol cache statistics for pspace %d\n%s:\n"),
+ pspace->num,
+ pspace->symfile_object_file != NULL
+ ? objfile_name (pspace->symfile_object_file)
+ : "(no object file)");
+
+ /* If the cache hasn't been created yet, avoid creating one. */
+ cache = program_space_data (pspace, symbol_cache_key);
+ if (cache == NULL)
+ printf_filtered (" empty, no stats available\n");
+ else
+ symbol_cache_stats (cache);
+ }
+}
+
+/* This module's 'new_objfile' observer. */
+
+static void
+symtab_new_objfile_observer (struct objfile *objfile)
+{
+ /* Ideally we'd use OBJFILE->pspace, but OBJFILE may be NULL. */
+ symbol_cache_flush (current_program_space);
+}
+
+/* This module's 'free_objfile' observer. */
+
+static void
+symtab_free_objfile_observer (struct objfile *objfile)
+{
+ symbol_cache_flush (objfile->pspace);
+}
+\f
/* Debug symbols usually don't have section information. We need to dig that
out of the minimal symbols and stash that in the debug symbol. */
if (!sym)
return NULL;
+ if (!SYMBOL_OBJFILE_OWNED (sym))
+ return sym;
+
/* We either have an OBJFILE, or we can get at it from the sym's
symtab. Anything else is a bug. */
- gdb_assert (objfile || SYMBOL_SYMTAB (sym));
+ gdb_assert (objfile || symbol_symtab (sym));
if (objfile == NULL)
- objfile = SYMBOL_SYMTAB (sym)->objfile;
+ objfile = symbol_objfile (sym);
if (SYMBOL_OBJ_SECTION (objfile, sym))
return sym;
if (lang->la_name_of_this == NULL || block == NULL)
return NULL;
+ if (symbol_lookup_debug > 1)
+ {
+ struct objfile *objfile = lookup_objfile_from_block (block);
+
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_language_this (%s, %s (objfile %s))",
+ lang->la_name, host_address_to_string (block),
+ objfile_debug_name (objfile));
+ }
+
while (block)
{
struct symbol *sym;
sym = block_lookup_symbol (block, lang->la_name_of_this, VAR_DOMAIN);
if (sym != NULL)
{
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, " = %s (%s, block %s)\n",
+ SYMBOL_PRINT_NAME (sym),
+ host_address_to_string (sym),
+ host_address_to_string (block));
+ }
block_found = block;
return sym;
}
block = BLOCK_SUPERBLOCK (block);
}
+ if (symbol_lookup_debug > 1)
+ fprintf_unfiltered (gdb_stdlog, " = NULL\n");
return NULL;
}
struct symbol *sym;
const struct language_defn *langdef;
+ if (symbol_lookup_debug)
+ {
+ struct objfile *objfile = lookup_objfile_from_block (block);
+
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_aux (%s, %s (objfile %s), %s, %s)\n",
+ name, host_address_to_string (block),
+ objfile != NULL
+ ? objfile_debug_name (objfile) : "NULL",
+ domain_name (domain), language_str (language));
+ }
+
+ /* Initialize block_found so that the language la_lookup_symbol_nonlocal
+ routines don't have to set it (to NULL) if a primitive type is found.
+ We do this early so that block_found is also NULL if no symbol is
+ found (though this is not part of the API, and callers cannot assume
+ this). */
+ block_found = NULL;
+
/* 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. If we don't set it, the contents of
sym = lookup_local_symbol (name, block, domain, language);
if (sym != NULL)
- return sym;
+ {
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "lookup_symbol_aux (...) = %s\n",
+ host_address_to_string (sym));
+ }
+ return sym;
+ }
/* If requested to do so by the caller and if appropriate for LANGUAGE,
check to see if NAME is a field of `this'. */
langdef->la_name_of_this);
if (check_field (t, name, is_a_field_of_this))
- return NULL;
+ {
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_aux (...) = NULL\n");
+ }
+ return NULL;
+ }
}
}
/* Now do whatever is appropriate for LANGUAGE to look
up static and global variables. */
- sym = langdef->la_lookup_symbol_nonlocal (name, block, domain);
+ sym = langdef->la_lookup_symbol_nonlocal (langdef, name, block, domain);
if (sym != NULL)
- return sym;
+ {
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "lookup_symbol_aux (...) = %s\n",
+ host_address_to_string (sym));
+ }
+ return sym;
+ }
/* Now search all static file-level symbols. Not strictly correct,
but more useful than an error. */
- return lookup_static_symbol (name, domain);
+ sym = lookup_static_symbol (name, domain);
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "lookup_symbol_aux (...) = %s\n",
+ sym != NULL ? host_address_to_string (sym) : "NULL");
+ }
+ return sym;
}
/* Check to see if the symbol is defined in BLOCK or its superiors.
lookup_objfile_from_block (const struct block *block)
{
struct objfile *obj;
- struct symtab *s;
+ struct compunit_symtab *cust;
if (block == NULL)
return NULL;
block = block_global_block (block);
- /* Go through SYMTABS.
- Non-primary symtabs share the block vector with their primary symtabs
- so we use ALL_PRIMARY_SYMTABS here instead of ALL_SYMTABS. */
- ALL_PRIMARY_SYMTABS (obj, s)
- if (block == BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK))
+ /* Look through all blockvectors. */
+ ALL_COMPUNITS (obj, cust)
+ if (block == BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust),
+ GLOBAL_BLOCK))
{
if (obj->separate_debug_objfile_backlink)
obj = obj->separate_debug_objfile_backlink;
{
struct symbol *sym;
+ if (symbol_lookup_debug > 1)
+ {
+ struct objfile *objfile = lookup_objfile_from_block (block);
+
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_block (%s, %s (objfile %s), %s)",
+ name, host_address_to_string (block),
+ objfile_debug_name (objfile),
+ domain_name (domain));
+ }
+
sym = block_lookup_symbol (block, name, domain);
if (sym)
{
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, " = %s\n",
+ host_address_to_string (sym));
+ }
block_found = block;
return fixup_symbol_section (sym, NULL);
}
+ if (symbol_lookup_debug > 1)
+ fprintf_unfiltered (gdb_stdlog, " = NULL\n");
return NULL;
}
/* See symtab.h. */
struct symbol *
-lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
+lookup_global_symbol_from_objfile (struct objfile *main_objfile,
const char *name,
const domain_enum domain)
{
- const struct objfile *objfile;
- struct symbol *sym;
- const struct blockvector *bv;
- const struct block *block;
- struct symtab *s;
+ struct objfile *objfile;
for (objfile = main_objfile;
objfile;
objfile = objfile_separate_debug_iterate (main_objfile, objfile))
{
- /* Go through symtabs. */
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
- {
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = block_lookup_symbol (block, name, domain);
- if (sym)
- {
- block_found = block;
- return fixup_symbol_section (sym, (struct objfile *)objfile);
- }
- }
+ struct symbol *sym = lookup_symbol_in_objfile (objfile, GLOBAL_BLOCK,
+ name, domain);
- sym = lookup_symbol_via_quick_fns ((struct objfile *) objfile,
- GLOBAL_BLOCK, name, domain);
- if (sym)
+ if (sym != NULL)
return sym;
}
lookup_symbol_in_objfile_symtabs (struct objfile *objfile, int block_index,
const char *name, const domain_enum domain)
{
- struct symbol *sym = NULL;
- const struct blockvector *bv;
- const struct block *block;
- struct symtab *s;
+ struct compunit_symtab *cust;
+
+ gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK);
+
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_objfile_symtabs (%s, %s, %s, %s)",
+ objfile_debug_name (objfile),
+ block_index == GLOBAL_BLOCK
+ ? "GLOBAL_BLOCK" : "STATIC_BLOCK",
+ name, domain_name (domain));
+ }
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ ALL_OBJFILE_COMPUNITS (objfile, cust)
{
- bv = BLOCKVECTOR (s);
+ const struct blockvector *bv;
+ const struct block *block;
+ struct symbol *sym;
+
+ bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
- sym = block_lookup_symbol (block, name, domain);
+ sym = block_lookup_symbol_primary (block, name, domain);
if (sym)
{
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, " = %s (block %s)\n",
+ host_address_to_string (sym),
+ host_address_to_string (block));
+ }
block_found = block;
return fixup_symbol_section (sym, objfile);
}
}
+ if (symbol_lookup_debug > 1)
+ fprintf_unfiltered (gdb_stdlog, " = NULL\n");
return NULL;
}
/* Wrapper around lookup_symbol_in_objfile_symtabs for search_symbols.
Look up LINKAGE_NAME in DOMAIN in the global and static blocks of OBJFILE
- and all related objfiles. */
+ and all associated separate debug objfiles.
+
+ Normally we only look in OBJFILE, and not any separate debug objfiles
+ because the outer loop will cause them to be searched too. This case is
+ different. Here we're called from search_symbols where it will only
+ call us for the the objfile that contains a matching minsym. */
static struct symbol *
lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
static void ATTRIBUTE_NORETURN
error_in_psymtab_expansion (int block_index, const char *name,
- struct symtab *symtab)
+ struct compunit_symtab *cust)
{
error (_("\
Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n\
%s may be an inlined function, or may be a template function\n \
(if a template, try specifying an instantiation: %s<type>)."),
block_index == GLOBAL_BLOCK ? "global" : "static",
- name, symtab_to_filename_for_display (symtab), name, name);
+ name,
+ symtab_to_filename_for_display (compunit_primary_filetab (cust)),
+ name, name);
}
/* A helper function for various lookup routines that interfaces with
lookup_symbol_via_quick_fns (struct objfile *objfile, int block_index,
const char *name, const domain_enum domain)
{
- struct symtab *symtab;
+ struct compunit_symtab *cust;
const struct blockvector *bv;
const struct block *block;
struct symbol *sym;
if (!objfile->sf)
return NULL;
- symtab = objfile->sf->qf->lookup_symbol (objfile, block_index, name, domain);
- if (!symtab)
- return NULL;
- bv = BLOCKVECTOR (symtab);
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_via_quick_fns (%s, %s, %s, %s)\n",
+ objfile_debug_name (objfile),
+ block_index == GLOBAL_BLOCK
+ ? "GLOBAL_BLOCK" : "STATIC_BLOCK",
+ name, domain_name (domain));
+ }
+
+ cust = objfile->sf->qf->lookup_symbol (objfile, block_index, name, domain);
+ if (cust == NULL)
+ {
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_via_quick_fns (...) = NULL\n");
+ }
+ return NULL;
+ }
+
+ bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = block_lookup_symbol (block, name, domain);
if (!sym)
- error_in_psymtab_expansion (block_index, name, symtab);
+ error_in_psymtab_expansion (block_index, name, cust);
+
+ if (symbol_lookup_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_via_quick_fns (...) = %s (block %s)\n",
+ host_address_to_string (sym),
+ host_address_to_string (block));
+ }
+
block_found = block;
return fixup_symbol_section (sym, objfile);
}
/* See symtab.h. */
struct symbol *
-basic_lookup_symbol_nonlocal (const char *name,
+basic_lookup_symbol_nonlocal (const struct language_defn *langdef,
+ const char *name,
const struct block *block,
const domain_enum domain)
{
if (sym != NULL)
return sym;
+ /* If we didn't find a definition for a builtin type in the static block,
+ search for it now. This is actually the right thing to do and can be
+ a massive performance win. E.g., when debugging a program with lots of
+ shared libraries we could search all of them only to find out the
+ builtin type isn't defined in any of them. This is common for types
+ like "void". */
+ if (domain == VAR_DOMAIN)
+ {
+ struct gdbarch *gdbarch;
+
+ if (block == NULL)
+ gdbarch = target_gdbarch ();
+ else
+ gdbarch = block_gdbarch (block);
+ sym = language_lookup_primitive_type_as_symbol (langdef, gdbarch, name);
+ if (sym != NULL)
+ return sym;
+ }
+
return lookup_global_symbol (name, block, domain);
}
const domain_enum domain)
{
const struct block *static_block = block_static_block (block);
+ struct symbol *sym;
- if (static_block != NULL)
- return lookup_symbol_in_block (name, static_block, domain);
- else
+ if (static_block == NULL)
return NULL;
+
+ if (symbol_lookup_debug)
+ {
+ struct objfile *objfile = lookup_objfile_from_block (static_block);
+
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_static_block (%s, %s (objfile %s),"
+ " %s)\n",
+ name,
+ host_address_to_string (block),
+ objfile_debug_name (objfile),
+ domain_name (domain));
+ }
+
+ sym = lookup_symbol_in_block (name, static_block, domain);
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_static_block (...) = %s\n",
+ sym != NULL ? host_address_to_string (sym) : "NULL");
+ }
+ return sym;
}
/* Perform the standard symbol lookup of NAME in OBJFILE:
{
struct symbol *result;
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_objfile (%s, %s, %s, %s)\n",
+ objfile_debug_name (objfile),
+ block_index == GLOBAL_BLOCK
+ ? "GLOBAL_BLOCK" : "STATIC_BLOCK",
+ name, domain_name (domain));
+ }
+
result = lookup_symbol_in_objfile_symtabs (objfile, block_index,
name, domain);
- if (result == NULL)
+ if (result != NULL)
{
- result = lookup_symbol_via_quick_fns (objfile, block_index,
- name, domain);
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_objfile (...) = %s"
+ " (in symtabs)\n",
+ host_address_to_string (result));
+ }
+ return result;
}
+ result = lookup_symbol_via_quick_fns (objfile, block_index,
+ name, domain);
+ if (symbol_lookup_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "lookup_symbol_in_objfile (...) = %s%s\n",
+ result != NULL
+ ? host_address_to_string (result)
+ : "NULL",
+ result != NULL ? " (via quick fns)" : "");
+ }
return result;
}
struct symbol *
lookup_static_symbol (const char *name, const domain_enum domain)
{
+ struct symbol_cache *cache = get_symbol_cache (current_program_space);
struct objfile *objfile;
struct symbol *result;
+ struct block_symbol_cache *bsc;
+ struct symbol_cache_slot *slot;
+
+ /* Lookup in STATIC_BLOCK is not current-objfile-dependent, so just pass
+ NULL for OBJFILE_CONTEXT. */
+ result = symbol_cache_lookup (cache, NULL, STATIC_BLOCK, name, domain,
+ &bsc, &slot);
+ if (result != NULL)
+ {
+ if (result == SYMBOL_LOOKUP_FAILED)
+ return NULL;
+ return result;
+ }
ALL_OBJFILES (objfile)
{
result = lookup_symbol_in_objfile (objfile, STATIC_BLOCK, name, domain);
if (result != NULL)
- return result;
+ {
+ /* Still pass NULL for OBJFILE_CONTEXT here. */
+ symbol_cache_mark_found (bsc, slot, NULL, result);
+ return result;
+ }
}
+ /* Still pass NULL for OBJFILE_CONTEXT here. */
+ symbol_cache_mark_not_found (bsc, slot, NULL, name, domain);
return NULL;
}
const struct block *block,
const domain_enum domain)
{
- struct symbol *sym = NULL;
- struct objfile *objfile = NULL;
+ struct symbol_cache *cache = get_symbol_cache (current_program_space);
+ struct symbol *sym;
+ struct objfile *objfile;
struct global_sym_lookup_data lookup_data;
+ struct block_symbol_cache *bsc;
+ struct symbol_cache_slot *slot;
- /* Call library-specific lookup procedure. */
objfile = lookup_objfile_from_block (block);
+
+ /* First see if we can find the symbol in the cache.
+ This works because we use the current objfile to qualify the lookup. */
+ sym = symbol_cache_lookup (cache, objfile, GLOBAL_BLOCK, name, domain,
+ &bsc, &slot);
+ if (sym != NULL)
+ {
+ if (sym == SYMBOL_LOOKUP_FAILED)
+ return NULL;
+ return sym;
+ }
+
+ /* Call library-specific lookup procedure. */
if (objfile != NULL)
sym = solib_global_lookup (objfile, 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);
+ /* If that didn't work go a global search (of global blocks, heh). */
+ if (sym == NULL)
+ {
+ 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);
+ sym = lookup_data.result;
+ }
+
+ if (sym != NULL)
+ symbol_cache_mark_found (bsc, slot, objfile, sym);
+ else
+ symbol_cache_mark_not_found (bsc, slot, objfile, name, domain);
- return lookup_data.result;
+ return sym;
}
int
basic_lookup_transparent_type_quick (struct objfile *objfile, int block_index,
const char *name)
{
- struct symtab *symtab;
+ struct compunit_symtab *cust;
const struct blockvector *bv;
struct block *block;
struct symbol *sym;
if (!objfile->sf)
return NULL;
- symtab = objfile->sf->qf->lookup_symbol (objfile, block_index, name,
- STRUCT_DOMAIN);
- if (!symtab)
+ cust = objfile->sf->qf->lookup_symbol (objfile, block_index, name,
+ STRUCT_DOMAIN);
+ if (cust == NULL)
return NULL;
- bv = BLOCKVECTOR (symtab);
+ bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
if (!sym)
- error_in_psymtab_expansion (block_index, name, symtab);
+ error_in_psymtab_expansion (block_index, name, cust);
if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
return SYMBOL_TYPE (sym);
basic_lookup_transparent_type (const char *name)
{
struct symbol *sym;
- struct symtab *s = NULL;
+ struct compunit_symtab *cust;
const struct blockvector *bv;
struct objfile *objfile;
struct block *block;
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ ALL_OBJFILE_COMPUNITS (objfile, cust)
{
- bv = BLOCKVECTOR (s);
+ bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
+ ALL_OBJFILE_COMPUNITS (objfile, cust)
{
- bv = BLOCKVECTOR (s);
+ bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
}
}
-/* Find the symtab associated with PC and SECTION. Look through the
- psymtabs and read in another symtab if necessary. */
+/* Find the compunit symtab associated with PC and SECTION.
+ This will read in debug info as necessary. */
-struct symtab *
-find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
+struct compunit_symtab *
+find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
{
- struct block *b;
- const struct blockvector *bv;
- struct symtab *s = NULL;
- struct symtab *best_s = NULL;
+ struct compunit_symtab *cust;
+ struct compunit_symtab *best_cust = NULL;
struct objfile *objfile;
CORE_ADDR distance = 0;
struct bound_minimal_symbol msymbol;
It also happens for objfiles that have their functions reordered.
For these, the symtab we are looking for is not necessarily read in. */
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
- bv = BLOCKVECTOR (s);
+ struct block *b;
+ const struct blockvector *bv;
+
+ bv = COMPUNIT_BLOCKVECTOR (cust);
b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
if (BLOCK_START (b) <= pc
can't be found. */
if ((objfile->flags & OBJF_REORDERED) && objfile->sf)
{
- struct symtab *result;
+ struct compunit_symtab *result;
result
- = objfile->sf->qf->find_pc_sect_symtab (objfile,
- msymbol,
- pc, section,
- 0);
- if (result)
+ = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile,
+ msymbol,
+ pc, section,
+ 0);
+ if (result != NULL)
return result;
}
if (section != 0)
section. */
}
distance = BLOCK_END (b) - BLOCK_START (b);
- best_s = s;
+ best_cust = cust;
}
}
- if (best_s != NULL)
- return (best_s);
+ if (best_cust != NULL)
+ return best_cust;
/* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs). */
ALL_OBJFILES (objfile)
{
- struct symtab *result;
+ struct compunit_symtab *result;
if (!objfile->sf)
continue;
- result = objfile->sf->qf->find_pc_sect_symtab (objfile,
- msymbol,
- pc, section,
- 1);
- if (result)
+ result = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile,
+ msymbol,
+ pc, section,
+ 1);
+ if (result != NULL)
return result;
}
return NULL;
}
-/* Find the symtab associated with PC. Look through the psymtabs and read
- in another symtab if necessary. Backward compatibility, no section. */
+/* Find the compunit symtab associated with PC.
+ This will read in debug info as necessary.
+ Backward compatibility, no section. */
-struct symtab *
-find_pc_symtab (CORE_ADDR pc)
+struct compunit_symtab *
+find_pc_compunit_symtab (CORE_ADDR pc)
{
- return find_pc_sect_symtab (pc, find_pc_mapped_section (pc));
+ return find_pc_sect_compunit_symtab (pc, find_pc_mapped_section (pc));
}
\f
struct symtab_and_line
find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
{
- struct symtab *s;
+ struct compunit_symtab *cust;
+ struct symtab *iter_s;
struct linetable *l;
int len;
int i;
struct symtab_and_line val;
const struct blockvector *bv;
struct bound_minimal_symbol msymbol;
- struct objfile *objfile;
/* Info on best line seen so far, and where it starts, and its file. */
}
- s = find_pc_sect_symtab (pc, section);
- if (!s)
+ cust = find_pc_sect_compunit_symtab (pc, section);
+ if (cust == NULL)
{
/* If no symbol information, return previous pc. */
if (notcurrent)
return val;
}
- bv = BLOCKVECTOR (s);
- objfile = s->objfile;
+ bv = COMPUNIT_BLOCKVECTOR (cust);
/* Look at all the symtabs that share this blockvector.
They all have the same apriori range, that we found was right;
but they have different line tables. */
- ALL_OBJFILE_SYMTABS (objfile, s)
+ ALL_COMPUNIT_FILETABS (cust, iter_s)
{
- if (BLOCKVECTOR (s) != bv)
- continue;
-
/* Find the best line in this symtab. */
- l = LINETABLE (s);
+ l = SYMTAB_LINETABLE (iter_s);
if (!l)
continue;
len = l->nitems;
if (prev && prev->line && (!best || prev->pc > best->pc))
{
best = prev;
- best_symtab = s;
+ best_symtab = iter_s;
/* Discard BEST_END if it's before the PC of the current BEST. */
if (best_end <= best->pc)
pc = overlay_mapped_address (pc, section);
return find_pc_sect_line (pc, section, notcurrent);
}
+
+/* See symtab.h. */
+
+struct symtab *
+find_pc_line_symtab (CORE_ADDR pc)
+{
+ struct symtab_and_line sal;
+
+ /* This always passes zero for NOTCURRENT to find_pc_line.
+ There are currently no callers that ever pass non-zero. */
+ sal = find_pc_line (pc, 0);
+ return sal.symtab;
+}
\f
/* Find line number LINE in any symtab whose name is the same as
SYMTAB.
struct symtab *best_symtab;
/* First try looking it up in the given symtab. */
- best_linetable = LINETABLE (symtab);
+ best_linetable = SYMTAB_LINETABLE (symtab);
best_symtab = symtab;
best_index = find_line_common (best_linetable, line, &exact, 0);
if (best_index < 0 || !exact)
int best;
struct objfile *objfile;
+ struct compunit_symtab *cu;
struct symtab *s;
if (best_index >= 0)
symtab_to_fullname (symtab));
}
- ALL_SYMTABS (objfile, s)
+ ALL_FILETABS (objfile, cu, s)
{
struct linetable *l;
int ind;
if (FILENAME_CMP (symtab_to_fullname (symtab),
symtab_to_fullname (s)) != 0)
continue;
- l = LINETABLE (s);
+ l = SYMTAB_LINETABLE (s);
ind = find_line_common (l, line, &exact, 0);
if (ind >= 0)
{
int was_exact;
int idx;
- idx = find_line_common (LINETABLE (symtab), line, &was_exact, start);
+ idx = find_line_common (SYMTAB_LINETABLE (symtab), line, &was_exact,
+ start);
if (idx < 0)
break;
if (!was_exact)
{
- struct linetable_entry *item = &LINETABLE (symtab)->item[idx];
+ struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
if (*best_item == NULL || item->line < (*best_item)->line)
*best_item = item;
break;
}
- VEC_safe_push (CORE_ADDR, result, LINETABLE (symtab)->item[idx].pc);
+ VEC_safe_push (CORE_ADDR, result,
+ SYMTAB_LINETABLE (symtab)->item[idx].pc);
start = idx + 1;
}
symtab = find_line_symtab (symtab, line, &ind, NULL);
if (symtab != NULL)
{
- l = LINETABLE (symtab);
+ l = SYMTAB_LINETABLE (symtab);
*pc = l->item[ind].pc;
return 1;
}
find_function_start_sal (struct symbol *sym, int funfirstline)
{
struct symtab_and_line sal;
+ struct obj_section *section;
fixup_symbol_section (sym, NULL);
- sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)),
- SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym), 0);
+ section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
+ sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
/* We always should have a line for the function start address.
If we don't, something is odd. Create a plain SAL refering
init_sal (&sal);
sal.pspace = current_program_space;
sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- sal.section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
+ sal.section = section;
}
if (funfirstline)
int i;
/* Give up if this symbol has no lineinfo table. */
- l = LINETABLE (symtab);
+ l = SYMTAB_LINETABLE (symtab);
if (l == NULL)
return func_addr;
{
fixup_symbol_section (sym, NULL);
+ objfile = symbol_objfile (sym);
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
+ section = SYMBOL_OBJ_SECTION (objfile, sym);
name = SYMBOL_LINKAGE_NAME (sym);
- objfile = SYMBOL_SYMTAB (sym)->objfile;
}
else
{
/* Be conservative - allow direct PC (without skipping prologue) only if we
have proven the CU (Compilation Unit) supports it. sal->SYMTAB does not
have to be set by the caller so we use SYM instead. */
- if (sym && SYMBOL_SYMTAB (sym)->locations_valid)
+ if (sym != NULL
+ && COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (symbol_symtab (sym))))
force_skip = 0;
saved_pc = pc;
is aligned. */
if (!force_skip && sym && start_sal.symtab == NULL)
{
- pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym));
+ pc = skip_prologue_using_lineinfo (pc, symbol_symtab (sym));
/* Recalculate the line number. */
start_sal = find_pc_sect_line (pc, section, 0);
}
&& SYMBOL_LINE (BLOCK_FUNCTION (function_block)) != 0)
{
sal->line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
- sal->symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block));
+ sal->symtab = symbol_symtab (BLOCK_FUNCTION (function_block));
}
}
do this. */
if (prologue_sal.symtab->language != language_asm)
{
- struct linetable *linetable = LINETABLE (prologue_sal.symtab);
+ struct linetable *linetable = SYMTAB_LINETABLE (prologue_sal.symtab);
int idx = 0;
/* Skip any earlier lines, and any end-of-sequence marker
static void
sources_info (char *ignore, int from_tty)
{
+ struct compunit_symtab *cu;
struct symtab *s;
struct objfile *objfile;
struct output_source_filename_data data;
printf_filtered ("Source files for which symbols have been read in:\n\n");
data.first = 1;
- ALL_SYMTABS (objfile, s)
+ ALL_FILETABS (objfile, cu, s)
{
const char *fullname = symtab_to_fullname (s);
struct symbol_search *sym_b = *(struct symbol_search **) sb;
int c;
- c = FILENAME_CMP (sym_a->symtab->filename, sym_b->symtab->filename);
+ c = FILENAME_CMP (symbol_symtab (sym_a->symbol)->filename,
+ symbol_symtab (sym_b->symbol)->filename);
if (c != 0)
return c;
int nfiles, const char *files[],
struct symbol_search **matches)
{
- struct symtab *s;
+ struct compunit_symtab *cust;
const struct blockvector *bv;
struct block *b;
int i = 0;
{
/* 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. */
+ benefit of the next loop on ALL_COMPUNITS. */
if (kind == FUNCTIONS_DOMAIN
- ? find_pc_symtab (MSYMBOL_VALUE_ADDRESS (objfile,
- msymbol)) == NULL
+ ? (find_pc_compunit_symtab
+ (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) == NULL)
: (lookup_symbol_in_objfile_from_linkage_name
(objfile, MSYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
== NULL))
nfound = 0;
retval_chain = make_cleanup_free_search_symbols (&found);
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
- bv = BLOCKVECTOR (s);
+ bv = COMPUNIT_BLOCKVECTOR (cust);
for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
{
b = BLOCKVECTOR_BLOCK (bv, i);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- struct symtab *real_symtab = SYMBOL_SYMTAB (sym);
+ struct symtab *real_symtab = symbol_symtab (sym);
QUIT;
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))
+ && (TYPE_CODE (SYMBOL_TYPE (sym))
+ == TYPE_CODE_ENUM)))
|| (kind == FUNCTIONS_DOMAIN
&& SYMBOL_CLASS (sym) == LOC_BLOCK)
|| (kind == TYPES_DOMAIN
struct symbol_search *psr = (struct symbol_search *)
xmalloc (sizeof (struct symbol_search));
psr->block = i;
- psr->symtab = real_symtab;
psr->symbol = sym;
memset (&psr->msymbol, 0, sizeof (psr->msymbol));
psr->next = NULL;
}
/* If there are no eyes, avoid all contact. I mean, if there are
- no debug symbols, then print directly from the msymbol_vector. */
+ no debug symbols, then add matching minsyms. */
if (found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
{
/* 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 (MSYMBOL_VALUE_ADDRESS (objfile,
- msymbol)) == NULL)
+ || (find_pc_compunit_symtab
+ (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) == NULL))
{
if (lookup_symbol_in_objfile_from_linkage_name
(objfile, MSYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
psr->block = i;
psr->msymbol.minsym = msymbol;
psr->msymbol.objfile = objfile;
- psr->symtab = NULL;
psr->symbol = NULL;
psr->next = NULL;
if (tail == NULL)
static void
print_symbol_info (enum search_domain kind,
- struct symtab *s, struct symbol *sym,
+ struct symbol *sym,
int block, const char *last)
{
+ struct symtab *s = symbol_symtab (sym);
const char *s_filename = symtab_to_filename_for_display (s);
if (last == NULL || filename_cmp (last, s_filename) != 0)
else
{
print_symbol_info (kind,
- p->symtab,
p->symbol,
p->block,
last_filename);
- last_filename = symtab_to_filename_for_display (p->symtab);
+ last_filename
+ = symtab_to_filename_for_display (symbol_symtab (p->symbol));
}
}
{
if (p->msymbol.minsym == NULL)
{
- const char *fullname = symtab_to_fullname (p->symtab);
+ struct symtab *symtab = symbol_symtab (p->symbol);
+ const char *fullname = symtab_to_fullname (symtab);
int newlen = (strlen (fullname)
+ strlen (SYMBOL_LINKAGE_NAME (p->symbol))
strcat (string, "'");
break_command (string, from_tty);
print_symbol_info (FUNCTIONS_DOMAIN,
- p->symtab,
p->symbol,
p->block,
- symtab_to_filename_for_display (p->symtab));
+ symtab_to_filename_for_display (symtab));
}
else
{
won't be that many. */
struct symbol *sym;
- struct symtab *s;
+ struct compunit_symtab *cust;
struct minimal_symbol *msymbol;
struct objfile *objfile;
const struct block *b;
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
if (code == TYPE_CODE_UNDEF
}
}
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
if (code == TYPE_CODE_UNDEF
/* Go through this symtab and check the externs and statics for
symbols which match. */
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ b = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
}
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ b = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
VEC (char_ptr) *
make_source_files_completion_list (const char *text, const char *word)
{
+ struct compunit_symtab *cu;
struct symtab *s;
struct objfile *objfile;
size_t text_len = strlen (text);
cache_cleanup = make_cleanup (delete_filename_seen_cache,
filename_seen_cache);
- ALL_SYMTABS (objfile, s)
+ ALL_FILETABS (objfile, cu, s)
{
if (not_interesting_fname (s->filename))
continue;
\f
-/* Initialize the symbol SYM. */
+/* Helper function to initialize the fields of an objfile-owned symbol.
+ It assumed that *SYM is already all zeroes. */
+
+static void
+initialize_objfile_symbol_1 (struct symbol *sym)
+{
+ SYMBOL_OBJFILE_OWNED (sym) = 1;
+ SYMBOL_SECTION (sym) = -1;
+}
+
+/* Initialize the symbol SYM, and mark it as being owned by an objfile. */
void
-initialize_symbol (struct symbol *sym)
+initialize_objfile_symbol (struct symbol *sym)
{
memset (sym, 0, sizeof (*sym));
- SYMBOL_SECTION (sym) = -1;
+ initialize_objfile_symbol_1 (sym);
}
/* Allocate and initialize a new 'struct symbol' on OBJFILE's
struct symbol *result;
result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
- SYMBOL_SECTION (result) = -1;
+ initialize_objfile_symbol_1 (result);
return result;
}
struct template_symbol *result;
result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
- SYMBOL_SECTION (&result->base) = -1;
+ initialize_objfile_symbol_1 (&result->base);
return result;
}
+/* See symtab.h. */
+
+struct objfile *
+symbol_objfile (const struct symbol *symbol)
+{
+ gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
+ return SYMTAB_OBJFILE (symbol->owner.symtab);
+}
+
+/* See symtab.h. */
+
+struct gdbarch *
+symbol_arch (const struct symbol *symbol)
+{
+ if (!SYMBOL_OBJFILE_OWNED (symbol))
+ return symbol->owner.arch;
+ return get_objfile_arch (SYMTAB_OBJFILE (symbol->owner.symtab));
+}
+
+/* See symtab.h. */
+
+struct symtab *
+symbol_symtab (const struct symbol *symbol)
+{
+ gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
+ return symbol->owner.symtab;
+}
+
+/* See symtab.h. */
+
+void
+symbol_set_symtab (struct symbol *symbol, struct symtab *symtab)
+{
+ gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
+ symbol->owner.symtab = symtab;
+}
+
\f
void
main_progspace_key
= register_program_space_data_with_cleanup (NULL, main_info_cleanup);
+ symbol_cache_key
+ = register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup);
+
add_info ("variables", variables_info, _("\
All global and static variable names, or those matching REGEXP."));
if (dbx_commands)
NULL,
&setdebuglist, &showdebuglist);
+ add_setshow_zuinteger_cmd ("symbol-lookup", no_class, &symbol_lookup_debug,
+ _("\
+Set debugging of symbol lookup."), _("\
+Show debugging of symbol lookup."), _("\
+When enabled (non-zero), symbol lookups are logged."),
+ NULL, NULL,
+ &setdebuglist, &showdebuglist);
+
+ add_setshow_zuinteger_cmd ("symbol-cache-size", no_class,
+ &new_symbol_cache_size,
+ _("Set the size of the symbol cache."),
+ _("Show the size of the symbol cache."), _("\
+The size of the symbol cache.\n\
+If zero then the symbol cache is disabled."),
+ set_symbol_cache_size_handler, NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+ add_cmd ("symbol-cache", class_maintenance, maintenance_print_symbol_cache,
+ _("Dump the symbol cache for each program space."),
+ &maintenanceprintlist);
+
+ add_cmd ("symbol-cache-statistics", class_maintenance,
+ maintenance_print_symbol_cache_statistics,
+ _("Print symbol cache statistics for each program space."),
+ &maintenanceprintlist);
+
+ add_cmd ("flush-symbol-cache", class_maintenance,
+ maintenance_flush_symbol_cache,
+ _("Flush the symbol cache for each program space."),
+ &maintenancelist);
+
observer_attach_executable_changed (symtab_observer_executable_changed);
+ observer_attach_new_objfile (symtab_new_objfile_observer);
+ observer_attach_free_objfile (symtab_free_objfile_observer);
}