+2002-12-18 David Carlton <carlton@math.stanford.edu>
+
+ * symtab.c (lookup_symbol_aux_file): Call
+ cp_lookup_possible_namespace_symbol.
+ * dwarf2read.c (add_partial_symbol): Sometimes check for possible
+ namespace symbols.
+ * cp-support.c (maintenance_print_namespace): Handle
+ possible_namespace_block, too.
+ (cp_lookup_possible_namespace_symbol): New function.
+ * cp-support.h: Declare cp_check_possible_namespace_symbols,
+ cp_lookup_possible_namespace_symbol.
+ * cp-support.c (check_one_possible_namespace_symbol): New
+ function.
+ (cp_check_possible_namespace_symbols): New function.
+ (check_possible_namespace_symbols_loop): New function.
+ * symfile.h: Update declaration for add_psymbol_to_list.
+ * symfile.c (psymbol_init_demangled_name): New function.
+ (add_psymbol_to_list): Change SYMBOL_INIT_LANGUAGE_SPECIFIC to
+ psymbol_init_demangled_name.
+ (add_psymbol_to_list): Return a const struct psymbol *.
+ * Makefile.in (dwarf2read.o): Don't depend on bcache_h.
+ * dwarf2read.c: Don't #include "bcache.h"
+ * cp-support.c (get_namespace_block): Allocate blocks via
+ allocate_block.
+ (initialize_namespace_blocks): New function.
+ New variable possible_namespace_block.
+ (get_namespace_block): Call initialize_namespace_blocks.
+ (free_namespace_blocks): Rename from free_namespace_block; handle
+ possible_namespace_block, too.
+ (get_possible_namespace_block): New function.
+ * jv-lang.c (get_java_class_symtab): Ditto.
+ * block.c (allocate_block): New function.
+ * block.h: Declare allocate_block.
+
2002-12-17 David Carlton <carlton@math.stanford.edu>
* c-exp.y (yylex): Modify the #if 1 block to handle nested types
dwarf2read.o: dwarf2read.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
$(symfile_h) $(objfiles_h) $(elf_dwarf2_h) $(buildsym_h) \
$(demangle_h) $(expression_h) $(filenames_h) $(macrotab_h) \
- $(language_h) $(complaints_h) $(bcache_h) $(gdb_string_h) \
+ $(language_h) $(complaints_h) $(gdb_string_h) \
$(gdb_assert_h) $(cp_support_h)
dwarfread.o: dwarfread.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(symfile_h) \
$(objfiles_h) $(elf_dwarf_h) $(buildsym_h) $(demangle_h) \
return NULL;
}
}
+
+/* This allocates a block on OBSTACK, and initializes its elements to
+ zero/NULL. This is useful for creating "dummy" blocks that don't
+ correspond to actual source files.
+
+ Warning: it sets the block's BLOCK_DICT to NULL, which isn't a
+ valid value. If you don't want the block to have a dictiionary,
+ then you should subsequently set its BLOCK_DICT to
+ dict_create_linear (obstack, NULL). */
+
+struct block *
+allocate_block (struct obstack *obstack)
+{
+ struct block *bl = obstack_alloc (obstack, sizeof (struct block));
+
+ BLOCK_START (bl) = 0;
+ BLOCK_END (bl) = 0;
+ BLOCK_FUNCTION (bl) = NULL;
+ BLOCK_SUPERBLOCK (bl) = NULL;
+ BLOCK_DICT (bl) = NULL;
+ BLOCK_NAMESPACE (bl) = NULL;
+ BLOCK_GCC_COMPILED (bl) = 0;
+
+ return bl;
+}
+
extern struct
using_direct *block_using_iterator_next (struct block_using_iterator
*iterator);
+
+/* Allocate a dummy block. See warnings before the source code of
+ this function about using it correctly. */
+
+extern struct block *allocate_block (struct obstack *obstack);
/* This block exists only to store symbols associated to namespaces.
Normally, try to avoid accessing it directly: instead, use
get_namespace_block if you can. Similarly with
- namespace_objfile. */
+ possible_namespace_block and namespace_objfile. */
static struct block *namespace_block = NULL;
+static struct block *possible_namespace_block = NULL;
+
static struct objfile *namespace_objfile = NULL;
+static void initialize_namespace_blocks (void);
+
static struct block *get_namespace_block (void);
+static struct block *get_possible_namespace_block (void);
+
static struct objfile *get_namespace_objfile (void);
-static void free_namespace_block (struct symtab *symtab);
+static void free_namespace_blocks (struct symtab *symtab);
+
+static int check_one_possible_namespace_symbol (const char *name,
+ int len);
+
+static int check_possible_namespace_symbols_loop (const char *name,
+ int len);
static void maintenance_print_namespace (char *args, int from_tty);
}
}
-/* Locate the namespace_block, allocating it if necessary. */
+/* Allocate everything necessary for namespace_block and
+ possible_namespace_block. */
+
+static void
+initialize_namespace_blocks (void)
+{
+ struct objfile *objfile = get_namespace_objfile ();
+ struct symtab *namespace_symtab;
+ struct blockvector *bv;
+ struct block *bl;
+
+ namespace_symtab = allocate_symtab ("<C++-namespaces>", objfile);
+ namespace_symtab->language = language_cplus;
+ namespace_symtab->free_code = free_nothing;
+ namespace_symtab->dirname = NULL;
+
+ /* 2 = 3 blocks (global = namespace_block, static = NULL,
+ possible_namespace_block) - 1 block that's always part of struct
+ blockvector. */
+ bv = obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct blockvector)
+ + 2 * sizeof (struct block *));
+ BLOCKVECTOR_NBLOCKS (bv) = 3;
+ BLOCKVECTOR (namespace_symtab) = bv;
+
+ /* Allocate dummy STATIC_BLOCK. */
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
+ NULL);
+ BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
+
+ /* Allocate GLOBAL_BLOCK, which is namespace_block. */
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_linear_expandable ();
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
+ namespace_block = bl;
+
+ /* Allocate possible_namespace_block; we put it where the first
+ local block will live, though I don't think there's any need to
+ pretend that it's actually a local block (e.g. by setting
+ BLOCK_SUPERBLOCK appropriately). */
+ bl = allocate_block (&objfile->symbol_obstack);
+ BLOCK_DICT (bl) = dict_create_linear_expandable ();
+ BLOCKVECTOR_BLOCK (bv, 2) = bl;
+ possible_namespace_block = bl;
+
+ namespace_symtab->free_func = free_namespace_blocks;
+}
+
+/* Locate namespace_block, allocating it if necessary. */
static struct block *
get_namespace_block (void)
{
if (namespace_block == NULL)
- {
- struct objfile *objfile = get_namespace_objfile ();
- struct symtab *namespace_symtab;
- struct blockvector *bv;
- struct block *bl;
-
- namespace_symtab = allocate_symtab ("<C++-namespaces>", objfile);
- namespace_symtab->language = language_cplus;
- namespace_symtab->free_code = free_nothing;
- namespace_symtab->dirname = NULL;
-
- bv = obstack_alloc (&objfile->symbol_obstack,
- sizeof (struct blockvector));
- BLOCKVECTOR_NBLOCKS (bv) = 1;
- BLOCKVECTOR (namespace_symtab) = bv;
-
- /* Allocate dummy STATIC_BLOCK. */
- bl = obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- BLOCK_START (bl) = 0;
- BLOCK_END (bl) = 0;
- BLOCK_FUNCTION (bl) = NULL;
- BLOCK_SUPERBLOCK (bl) = NULL;
- BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
- NULL);
- BLOCK_NAMESPACE (bl) = NULL;
- BLOCK_GCC_COMPILED (bl) = 0;
- BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
-
- /* Allocate GLOBAL_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- BLOCK_DICT (bl) = dict_create_linear_expandable ();
- BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
- namespace_symtab->free_func = free_namespace_block;
-
- namespace_block = bl;
- }
+ initialize_namespace_blocks ();
return namespace_block;
}
+/* Locate possible_namespace_block, allocating it if necessary. */
+
+static struct block *
+get_possible_namespace_block (void)
+{
+ if (namespace_block == NULL)
+ initialize_namespace_blocks ();
+
+ return possible_namespace_block;
+}
+
/* Free the dictionary associated to the namespace block. */
static void
-free_namespace_block (struct symtab *symtab)
+free_namespace_blocks (struct symtab *symtab)
{
gdb_assert (namespace_block != NULL);
dict_free (BLOCK_DICT (namespace_block));
namespace_block = NULL;
+ dict_free (BLOCK_DICT (possible_namespace_block));
+ possible_namespace_block = NULL;
namespace_objfile = NULL;
}
return sym;
}
+/* The next few functions deal with "possible namespace symbols".
+ These are symbols that claim to be associated to namespaces,
+ whereas in fact we don't know if the object of that name is a
+ namespace or a class. So don't trust them until you've searched
+ through all the global symbols to see if there's a class of that
+ name or not. */
+
+/* FIXME: carlton/2002-12-18: This concept is a hack. But it seems to
+ be the easiest way to deal with our desire for namespace symbols,
+ given the commonness of compilers that don't generate debugging
+ info for them. Once such compilers are more common, we should
+ delete all the possible namespace stuff. */
+
+/* Check to see if there's already a possible namespace symbol whose
+ name is the initial substring of NAME of length LEN. If not,
+ create one and return 0; otherwise, return 1. */
+
+static int
+check_one_possible_namespace_symbol (const char *name, int len)
+{
+ struct objfile *objfile = get_namespace_objfile ();
+ char *name_copy = obsavestring (name, len, &objfile->symbol_obstack);
+ const struct block *block = get_possible_namespace_block ();
+ struct symbol *sym = lookup_block_symbol (block, name_copy,
+ NULL, VAR_NAMESPACE);
+
+ if (sym == NULL)
+ {
+ struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+ name_copy, objfile);
+ TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+ sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_LANGUAGE (sym) = language_cplus;
+ SYMBOL_NAME (sym) = name_copy;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+ dict_add_symbol (BLOCK_DICT (block), sym);
+ return 0;
+ }
+ else
+ {
+ obstack_free (&objfile->symbol_obstack, name_copy);
+ return 1;
+ }
+}
+
+/* This is a helper loop for cp_check_possible_namespace_symbols; it
+ ensures that there are namespace symbols for all namespaces that
+ are initial substrings of NAME of length LEN. It returns 1 if a
+ previous loop had already created the shortest such symbol and 0
+ otherwise. */
+
+static int
+check_possible_namespace_symbols_loop (const char *name, int len)
+{
+ if (name[len] == ':')
+ {
+ const char *next_name = cp_find_first_component (name + len + 2);
+ int done = check_possible_namespace_symbols_loop (name,
+ next_name - name);
+
+ if (!done)
+ {
+ done = check_one_possible_namespace_symbol (name, len);
+ }
+ return done;
+ }
+ else
+ return 0;
+}
+
+/* Ensure that there are symbols in possible_namespace_block for all
+ initial substrings of NAME that look like namespaces or
+ classes. */
+
+void
+cp_check_possible_namespace_symbols (const char *name)
+{
+ check_possible_namespace_symbols_loop (name,
+ cp_find_first_component (name)
+ - name);
+}
+
+/* Look up a symbol in possible_namespace_block named NAME. Note that
+ there's no corresponding function for regular namespace symbols:
+ those get searched via the normal search of all global blocks in
+ lookup_symbol. */
+
+struct symbol *
+cp_lookup_possible_namespace_symbol (const char *name)
+{
+ return lookup_block_symbol (get_possible_namespace_block (),
+ name, NULL, VAR_NAMESPACE);
+}
+
static void
maintenance_print_namespace (char *args, int from_tty)
{
- const struct block *block = get_namespace_block ();
+ const struct block *namespace_block = get_namespace_block ();
+ const struct block *possible_namespace_block
+ = get_possible_namespace_block ();
struct dict_iterator iter;
struct symbol *sym;
- ALL_BLOCK_SYMBOLS (block, iter, sym)
+ printf_unfiltered ("Definite namespaces:\n");
+ ALL_BLOCK_SYMBOLS (namespace_block, iter, sym)
+ {
+ printf_unfiltered ("%s\n", SYMBOL_BEST_NAME (sym));
+ }
+ printf_unfiltered ("Possible namespaces:\n");
+ ALL_BLOCK_SYMBOLS (possible_namespace_block, iter, sym)
{
printf_unfiltered ("%s\n", SYMBOL_BEST_NAME (sym));
}
extern void cp_free_usings (struct using_direct_node *using);
extern struct symbol *cp_check_namespace_symbol (const char *name, int len);
+
+extern void cp_check_possible_namespace_symbols (const char *name);
+
+extern struct symbol *cp_lookup_possible_namespace_symbol (const char *name);
#include "language.h"
#include "complaints.h"
-#include "bcache.h"
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_assert.h"
{
CORE_ADDR addr = 0;
char *actual_name = pdi->name;
+ const struct partial_symbol *psym = NULL;
/* If we're not in the global namespace and if the namespace name
isn't encoded in a mangled actual_name, add it. */
{
/*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- add_psymbol_to_list (actual_name, strlen (actual_name),
- VAR_NAMESPACE, LOC_BLOCK,
- &objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
else
{
/*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- add_psymbol_to_list (actual_name, strlen (actual_name),
- VAR_NAMESPACE, LOC_BLOCK,
- &objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
break;
case DW_TAG_variable:
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
if (pdi->locdesc || pdi->has_type)
- add_psymbol_to_list (actual_name, strlen (actual_name),
- VAR_NAMESPACE, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
else
{
default:
break;
}
+
+ /* Check to see if we should scan the name for possible namespace
+ info. Only do this if this is C++, if we don't have namespace
+ debugging info in the file, if the psym is of an appropriate type
+ (otherwise we'll have psym == NULL), and if we actually had a
+ mangled name to begin with. */
+
+ if (cu_language == language_cplus
+ && namespace == NULL
+ && psym != NULL
+ && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+ cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym));
}
static int
BLOCKVECTOR (class_symtab) = bv;
/* Allocate dummy STATIC_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- BLOCK_START (bl) = 0;
- BLOCK_END (bl) = 0;
- BLOCK_FUNCTION (bl) = NULL;
- BLOCK_SUPERBLOCK (bl) = NULL;
+ bl = allocate_block (&objfile->symbol_obstack);
BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
NULL);
- BLOCK_NAMESPACE (bl) = NULL;
- BLOCK_GCC_COMPILED (bl) = 0;
BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
/* Allocate GLOBAL_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ bl = allocate_block (&objfile->symbol_obstack);
BLOCK_DICT (bl) = dict_create_linear_expandable ();
BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
class_symtab->free_func = free_class_block;
static void decrement_reading_symtab (void *);
+static void psymbol_init_demangled_name (struct partial_symbol *psymbol,
+ struct bcache *bcache);
+
static void overlay_invalidate_all (void);
static int overlay_is_mapped (struct obj_section *);
/* Add a symbol with a long value to a psymtab.
Since one arg is a struct, we pass in a ptr and deref it (sigh). */
-void
+/* NOTE: carlton/2002-12-18: I've modified this function to return the
+ partial symbol in question. But pay heed to the 'const' qualifier
+ in front: these partial symbols are stored in a bcache, and bad
+ things will happen if you modify them. */
+
+const struct partial_symbol *
add_psymbol_to_list (char *name, int namelength, namespace_enum namespace,
enum address_class class,
struct psymbol_allocation_list *list, long val, /* Value as a long */
SYMBOL_LANGUAGE (&psymbol) = language;
PSYMBOL_NAMESPACE (&psymbol) = namespace;
PSYMBOL_CLASS (&psymbol) = class;
- SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+ psymbol_init_demangled_name (&psymbol, objfile->psymbol_cache);
/* Stash the partial symbol away in the cache */
psym = bcache (&psymbol, sizeof (struct partial_symbol), objfile->psymbol_cache);
}
*list->next++ = psym;
OBJSTAT (objfile, n_psyms++);
+
+ return psym;
+}
+
+/* Initialize the demangled name for PSYMBOL, using bcache CACHE to
+ store the demangle name if necessary. */
+
+static void
+psymbol_init_demangled_name (struct partial_symbol *psymbol,
+ struct bcache *cache)
+{
+ const char *mangled = SYMBOL_NAME (psymbol);
+ char *demangled = NULL;
+
+ SYMBOL_CPLUS_DEMANGLED_NAME (psymbol) = NULL;
+
+ if (SYMBOL_LANGUAGE (psymbol) == language_unknown)
+ SYMBOL_LANGUAGE (psymbol) = language_auto;
+
+ switch (SYMBOL_LANGUAGE (psymbol))
+ {
+ case language_cplus:
+ case language_auto:
+ demangled = cplus_demangle (SYMBOL_NAME (psymbol),
+ DMGL_PARAMS | DMGL_ANSI);
+ if (demangled != NULL)
+ {
+ SYMBOL_LANGUAGE (psymbol) = language_cplus;
+ SYMBOL_CPLUS_DEMANGLED_NAME (psymbol)
+ = bcache (demangled, strlen (demangled) + 1, cache);
+ xfree (demangled);
+ }
+ break;
+ case language_java:
+ demangled =
+ cplus_demangle (SYMBOL_NAME (psymbol),
+ DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
+ if (demangled != NULL)
+ {
+ SYMBOL_LANGUAGE (psymbol) = language_java;
+ SYMBOL_CPLUS_DEMANGLED_NAME (psymbol)
+ = bcache (demangled, strlen (demangled) + 1, cache);
+ xfree (demangled);
+ }
+ default:
+ break;
+ }
}
/* Add a symbol with a long value to a psymtab. This differs from
/* #include "demangle.h" */
-extern void
+extern const struct partial_symbol *
add_psymbol_to_list (char *, int, namespace_enum, enum address_class,
struct psymbol_allocation_list *, long, CORE_ADDR,
enum language, struct objfile *);
return sym;
}
- return lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, name, mangled_name,
- namespace, symtab);
+ sym = lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, name, mangled_name,
+ namespace, symtab);
+
+ if (sym != NULL)
+ return sym;
+
+ /* Now call "cp_lookup_possible_namespace_symbol". Symbols in here
+ claim to be associated to namespaces, whereas the names in
+ question might actually correspond to either namespaces or to
+ classes. But if they correspond to classes, then we should have
+ found a match to them above. So if we find them now, they should
+ be genuine. */
+
+ /* FIXME: carlton/2002-12-18: This is a hack and should eventually
+ be deleted: see cp-support.c. */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ sym = cp_lookup_possible_namespace_symbol (name);
+ if (sym != NULL)
+ {
+ if (symtab != NULL)
+ *symtab = NULL;
+ return sym;
+ }
+ }
+
+ return NULL;
}