| Index: gdb/buildsym.c
|
| diff --git a/gdb/buildsym.c b/gdb/buildsym.c
|
| index 38bde22e209b7aa917ef9e150bbdf18c90f55038..d547012166be99d5b0d6570d537153a81e97ee66 100644
|
| --- a/gdb/buildsym.c
|
| +++ b/gdb/buildsym.c
|
| @@ -49,7 +49,7 @@
|
| #include "buildsym.h" /* Our own declarations. */
|
| #undef EXTERN
|
|
|
| -/* For cleanup_undefined_types and finish_global_stabs (somewhat
|
| +/* For cleanup_undefined_stabs_types and finish_global_stabs (somewhat
|
| questionable--see comment where we call them). */
|
|
|
| #include "stabsread.h"
|
| @@ -85,6 +85,10 @@ static int pending_addrmap_interesting;
|
|
|
|
|
| static int compare_line_numbers (const void *ln1p, const void *ln2p);
|
| +
|
| +static void record_pending_block (struct objfile *objfile,
|
| + struct block *block,
|
| + struct pending_block *opblock);
|
|
|
|
|
| /* Initial sizes of data structures. These are realloc'd larger if
|
| @@ -97,20 +101,6 @@ static int compare_line_numbers (const void *ln1p, const void *ln2p);
|
|
|
| /* Maintain the lists of symbols and blocks. */
|
|
|
| -/* Add a pending list to free_pendings. */
|
| -void
|
| -add_free_pendings (struct pending *list)
|
| -{
|
| - struct pending *link = list;
|
| -
|
| - if (list)
|
| - {
|
| - while (link->next) link = link->next;
|
| - link->next = free_pendings;
|
| - free_pendings = list;
|
| - }
|
| -}
|
| -
|
| /* Add a symbol to one of the lists of symbols. */
|
|
|
| void
|
| @@ -151,7 +141,7 @@ struct symbol *
|
| find_symbol_in_list (struct pending *list, char *name, int length)
|
| {
|
| int j;
|
| - char *pp;
|
| + const char *pp;
|
|
|
| while (list != NULL)
|
| {
|
| @@ -224,11 +214,12 @@ free_pending_blocks (void)
|
| the order the symbols have in the list (reversed from the input
|
| file). Put the block on the list of pending blocks. */
|
|
|
| -struct block *
|
| -finish_block (struct symbol *symbol, struct pending **listhead,
|
| - struct pending_block *old_blocks,
|
| - CORE_ADDR start, CORE_ADDR end,
|
| - struct objfile *objfile)
|
| +static struct block *
|
| +finish_block_internal (struct symbol *symbol, struct pending **listhead,
|
| + struct pending_block *old_blocks,
|
| + CORE_ADDR start, CORE_ADDR end,
|
| + struct objfile *objfile,
|
| + int is_global, int expandable)
|
| {
|
| struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
| struct pending *next, *next1;
|
| @@ -236,7 +227,9 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| struct pending_block *pblock;
|
| struct pending_block *opblock;
|
|
|
| - block = allocate_block (&objfile->objfile_obstack);
|
| + block = (is_global
|
| + ? allocate_global_block (&objfile->objfile_obstack)
|
| + : allocate_block (&objfile->objfile_obstack));
|
|
|
| if (symbol)
|
| {
|
| @@ -245,15 +238,20 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| }
|
| else
|
| {
|
| - BLOCK_DICT (block) = dict_create_hashed (&objfile->objfile_obstack,
|
| - *listhead);
|
| + if (expandable)
|
| + {
|
| + BLOCK_DICT (block) = dict_create_hashed_expandable ();
|
| + dict_add_pending (BLOCK_DICT (block), *listhead);
|
| + }
|
| + else
|
| + {
|
| + BLOCK_DICT (block) =
|
| + dict_create_hashed (&objfile->objfile_obstack, *listhead);
|
| + }
|
| }
|
|
|
| BLOCK_START (block) = start;
|
| BLOCK_END (block) = end;
|
| - /* Superblock filled in when containing block is made. */
|
| - BLOCK_SUPERBLOCK (block) = NULL;
|
| - BLOCK_NAMESPACE (block) = NULL;
|
|
|
| /* Put the block in as the value of the symbol that names it. */
|
|
|
| @@ -271,7 +269,10 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| parameter symbols. */
|
| int nparams = 0, iparams;
|
| struct symbol *sym;
|
| - ALL_BLOCK_SYMBOLS (block, iter, sym)
|
| +
|
| + /* Here we want to directly access the dictionary, because
|
| + we haven't fully initialized the block yet. */
|
| + ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
| {
|
| if (SYMBOL_IS_ARGUMENT (sym))
|
| nparams++;
|
| @@ -283,7 +284,9 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| TYPE_ALLOC (ftype, nparams * sizeof (struct field));
|
|
|
| iparams = 0;
|
| - ALL_BLOCK_SYMBOLS (block, iter, sym)
|
| + /* Here we want to directly access the dictionary, because
|
| + we haven't fully initialized the block yet. */
|
| + ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
| {
|
| if (iparams == nparams)
|
| break;
|
| @@ -392,6 +395,15 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| return block;
|
| }
|
|
|
| +struct block *
|
| +finish_block (struct symbol *symbol, struct pending **listhead,
|
| + struct pending_block *old_blocks,
|
| + CORE_ADDR start, CORE_ADDR end,
|
| + struct objfile *objfile)
|
| +{
|
| + return finish_block_internal (symbol, listhead, old_blocks,
|
| + start, end, objfile, 0, 0);
|
| +}
|
|
|
| /* Record BLOCK on the list of all blocks in the file. Put it after
|
| OPBLOCK, or at the beginning if opblock is NULL. This puts the
|
| @@ -400,7 +412,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
| Allocate the pending block struct in the objfile_obstack to save
|
| time. This wastes a little space. FIXME: Is it worth it? */
|
|
|
| -void
|
| +static void
|
| record_pending_block (struct objfile *objfile, struct block *block,
|
| struct pending_block *opblock)
|
| {
|
| @@ -492,10 +504,13 @@ make_blockvector (struct objfile *objfile)
|
| = addrmap_create_fixed (pending_addrmap, &objfile->objfile_obstack);
|
| else
|
| BLOCKVECTOR_MAP (blockvector) = 0;
|
| -
|
| +
|
| /* Some compilers output blocks in the wrong order, but we depend on
|
| their being in the right order so we can binary search. Check the
|
| - order and moan about it. */
|
| + order and moan about it.
|
| + Note: Remember that the first two blocks are the global and static
|
| + blocks. We could special case that fact and begin checking at block 2.
|
| + To avoid making that assumption we do not. */
|
| if (BLOCKVECTOR_NBLOCKS (blockvector) > 1)
|
| {
|
| for (i = 1; i < BLOCKVECTOR_NBLOCKS (blockvector); i++)
|
| @@ -565,7 +580,7 @@ start_subfile (const char *name, const char *dirname)
|
| current_subfile = subfile;
|
|
|
| /* Save its name and compilation directory name. */
|
| - subfile->name = (name == NULL) ? NULL : xstrdup (name);
|
| + subfile->name = xstrdup (name);
|
| subfile->dirname = (dirname == NULL) ? NULL : xstrdup (dirname);
|
|
|
| /* Initialize line-number recording for this subfile. */
|
| @@ -798,7 +813,20 @@ compare_line_numbers (const void *ln1p, const void *ln2p)
|
| void
|
| start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
|
| {
|
| + restart_symtab (start_addr);
|
| last_source_file = name;
|
| + start_subfile (name, dirname);
|
| +}
|
| +
|
| +/* Restart compilation for a symtab.
|
| + This is used when a symtab is built from multiple sources.
|
| + The symtab is first built with start_symtab and then for each additional
|
| + piece call restart_symtab. */
|
| +
|
| +void
|
| +restart_symtab (CORE_ADDR start_addr)
|
| +{
|
| + last_source_file = NULL;
|
| last_source_start_addr = start_addr;
|
| file_symbols = NULL;
|
| global_symbols = NULL;
|
| @@ -820,10 +848,8 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
|
|
|
| /* Initialize the list of sub source files with one entry for this
|
| file (the top-level source file). */
|
| -
|
| subfiles = NULL;
|
| current_subfile = NULL;
|
| - start_subfile (name, dirname);
|
| }
|
|
|
| /* Subroutine of end_symtab to simplify it. Look for a subfile that
|
| @@ -903,7 +929,7 @@ watch_main_source_file_lossage (void)
|
| }
|
| }
|
|
|
| -/* Helper function for qsort. Parametes are `struct block *' pointers,
|
| +/* Helper function for qsort. Parameters are `struct block *' pointers,
|
| function sorts them in descending order by their BLOCK_START. */
|
|
|
| static int
|
| @@ -916,38 +942,43 @@ block_compar (const void *ap, const void *bp)
|
| - (BLOCK_START (b) < BLOCK_START (a)));
|
| }
|
|
|
| -/* Finish the symbol definitions for one main source file, close off
|
| - all the lexical contexts for that file (creating struct block's for
|
| - them), then make the struct symtab for that file and put it in the
|
| - list of all such.
|
| +/* Reset globals used to build symtabs. */
|
|
|
| - END_ADDR is the address of the end of the file's text. SECTION is
|
| - the section number (in objfile->section_offsets) of the blockvector
|
| - and linetable.
|
| +static void
|
| +reset_symtab_globals (void)
|
| +{
|
| + last_source_file = NULL;
|
| + current_subfile = NULL;
|
| + pending_macros = NULL;
|
| + if (pending_addrmap)
|
| + {
|
| + obstack_free (&pending_addrmap_obstack, NULL);
|
| + pending_addrmap = NULL;
|
| + }
|
| +}
|
|
|
| - Note that it is possible for end_symtab() to return NULL. In
|
| - particular, for the DWARF case at least, it will return NULL when
|
| - it finds a compilation unit that has exactly one DIE, a
|
| - TAG_compile_unit DIE. This can happen when we link in an object
|
| - file that was compiled from an empty source file. Returning NULL
|
| - is probably not the correct thing to do, because then gdb will
|
| - never know about this empty file (FIXME). */
|
| +/* Implementation of the first part of end_symtab. It allows modifying
|
| + STATIC_BLOCK before it gets finalized by end_symtab_from_static_block.
|
| + If the returned value is NULL there is no blockvector created for
|
| + this symtab (you still must call end_symtab_from_static_block).
|
|
|
| -struct symtab *
|
| -end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| -{
|
| - struct symtab *symtab = NULL;
|
| - struct blockvector *blockvector;
|
| - struct subfile *subfile;
|
| - struct context_stack *cstk;
|
| - struct subfile *nextsub;
|
| + END_ADDR is the same as for end_symtab: the address of the end of the
|
| + file's text.
|
|
|
| + If EXPANDABLE is non-zero the STATIC_BLOCK dictionary is made
|
| + expandable. */
|
| +
|
| +struct block *
|
| +end_symtab_get_static_block (CORE_ADDR end_addr, struct objfile *objfile,
|
| + int expandable)
|
| +{
|
| /* Finish the lexical context of the last function in the file; pop
|
| the context stack. */
|
|
|
| if (context_stack_depth > 0)
|
| {
|
| - cstk = pop_context ();
|
| + struct context_stack *cstk = pop_context ();
|
| +
|
| /* Make a block for the local symbols within. */
|
| finish_block (cstk->name, &local_symbols, cstk->old_blocks,
|
| cstk->start_addr, end_addr, objfile);
|
| @@ -967,6 +998,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|
|
| /* Reordered executables may have out of order pending blocks; if
|
| OBJF_REORDERED is true, then sort the pending blocks. */
|
| +
|
| if ((objfile->flags & OBJF_REORDERED) && pending_blocks)
|
| {
|
| unsigned count = 0;
|
| @@ -997,13 +1029,13 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| (this needs to be done before the finish_blocks so that
|
| file_symbols is still good).
|
|
|
| - Both cleanup_undefined_types and finish_global_stabs are stabs
|
| + Both cleanup_undefined_stabs_types and finish_global_stabs are stabs
|
| specific, but harmless for other symbol readers, since on gdb
|
| startup or when finished reading stabs, the state is set so these
|
| are no-ops. FIXME: Is this handled right in case of QUIT? Can
|
| we make this cleaner? */
|
|
|
| - cleanup_undefined_types (objfile);
|
| + cleanup_undefined_stabs_types (objfile);
|
| finish_global_stabs (objfile);
|
|
|
| if (pending_blocks == NULL
|
| @@ -1012,18 +1044,51 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| && have_line_numbers == 0
|
| && pending_macros == NULL)
|
| {
|
| - /* Ignore symtabs that have no functions with real debugging
|
| - info. */
|
| + /* Ignore symtabs that have no functions with real debugging info. */
|
| + return NULL;
|
| + }
|
| + else
|
| + {
|
| + /* Define the STATIC_BLOCK. */
|
| + return finish_block_internal (NULL, &file_symbols, NULL,
|
| + last_source_start_addr, end_addr, objfile,
|
| + 0, expandable);
|
| + }
|
| +}
|
| +
|
| +/* Implementation of the second part of end_symtab. Pass STATIC_BLOCK
|
| + as value returned by end_symtab_get_static_block.
|
| +
|
| + SECTION is the same as for end_symtab: the section number
|
| + (in objfile->section_offsets) of the blockvector and linetable.
|
| +
|
| + If EXPANDABLE is non-zero the GLOBAL_BLOCK dictionary is made
|
| + expandable. */
|
| +
|
| +struct symtab *
|
| +end_symtab_from_static_block (struct block *static_block,
|
| + struct objfile *objfile, int section,
|
| + int expandable)
|
| +{
|
| + struct symtab *symtab = NULL;
|
| + struct blockvector *blockvector;
|
| + struct subfile *subfile;
|
| + struct subfile *nextsub;
|
| +
|
| + if (static_block == NULL)
|
| + {
|
| + /* Ignore symtabs that have no functions with real debugging info. */
|
| blockvector = NULL;
|
| }
|
| else
|
| {
|
| - /* Define the STATIC_BLOCK & GLOBAL_BLOCK, and build the
|
| + CORE_ADDR end_addr = BLOCK_END (static_block);
|
| +
|
| + /* Define after STATIC_BLOCK also GLOBAL_BLOCK, and build the
|
| blockvector. */
|
| - finish_block (0, &file_symbols, 0, last_source_start_addr,
|
| - end_addr, objfile);
|
| - finish_block (0, &global_symbols, 0, last_source_start_addr,
|
| - end_addr, objfile);
|
| + finish_block_internal (NULL, &global_symbols, NULL,
|
| + last_source_start_addr, end_addr, objfile,
|
| + 1, expandable);
|
| blockvector = make_blockvector (objfile);
|
| }
|
|
|
| @@ -1122,7 +1187,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| {
|
| /* Since we are ignoring that subfile, we also need
|
| to unlink the associated empty symtab that we created.
|
| - Otherwise, we can into trouble because various parts
|
| + Otherwise, we can run into trouble because various parts
|
| such as the block-vector are uninitialized whereas
|
| the rest of the code assumes that they are.
|
|
|
| @@ -1163,6 +1228,14 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| if (symtab)
|
| {
|
| symtab->primary = 1;
|
| +
|
| + if (symtab->blockvector)
|
| + {
|
| + struct block *b = BLOCKVECTOR_BLOCK (symtab->blockvector,
|
| + GLOBAL_BLOCK);
|
| +
|
| + set_block_symtab (b, symtab);
|
| + }
|
| }
|
|
|
| /* Default any symbols without a specified symtab to the primary
|
| @@ -1183,24 +1256,128 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL)
|
| SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab;
|
|
|
| - for (sym = dict_iterator_first (BLOCK_DICT (block), &iter);
|
| - sym != NULL;
|
| - sym = dict_iterator_next (&iter))
|
| + /* Note that we only want to fix up symbols from the local
|
| + blocks, not blocks coming from included symtabs. That is why
|
| + we use ALL_DICT_SYMBOLS here and not ALL_BLOCK_SYMBOLS. */
|
| + ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
| if (SYMBOL_SYMTAB (sym) == NULL)
|
| SYMBOL_SYMTAB (sym) = symtab;
|
| }
|
| }
|
|
|
| - last_source_file = NULL;
|
| - current_subfile = NULL;
|
| - pending_macros = NULL;
|
| - if (pending_addrmap)
|
| + reset_symtab_globals ();
|
| +
|
| + return symtab;
|
| +}
|
| +
|
| +/* Finish the symbol definitions for one main source file, close off
|
| + all the lexical contexts for that file (creating struct block's for
|
| + them), then make the struct symtab for that file and put it in the
|
| + list of all such.
|
| +
|
| + END_ADDR is the address of the end of the file's text. SECTION is
|
| + the section number (in objfile->section_offsets) of the blockvector
|
| + and linetable.
|
| +
|
| + Note that it is possible for end_symtab() to return NULL. In
|
| + particular, for the DWARF case at least, it will return NULL when
|
| + it finds a compilation unit that has exactly one DIE, a
|
| + TAG_compile_unit DIE. This can happen when we link in an object
|
| + file that was compiled from an empty source file. Returning NULL
|
| + is probably not the correct thing to do, because then gdb will
|
| + never know about this empty file (FIXME).
|
| +
|
| + If you need to modify STATIC_BLOCK before it is finalized you should
|
| + call end_symtab_get_static_block and end_symtab_from_static_block
|
| + yourself. */
|
| +
|
| +struct symtab *
|
| +end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
| +{
|
| + struct block *static_block;
|
| +
|
| + static_block = end_symtab_get_static_block (end_addr, objfile, 0);
|
| + return end_symtab_from_static_block (static_block, objfile, section, 0);
|
| +}
|
| +
|
| +/* Same as end_symtab except create a symtab that can be later added to. */
|
| +
|
| +struct symtab *
|
| +end_expandable_symtab (CORE_ADDR end_addr, struct objfile *objfile,
|
| + int section)
|
| +{
|
| + struct block *static_block;
|
| +
|
| + static_block = end_symtab_get_static_block (end_addr, objfile, 1);
|
| + return end_symtab_from_static_block (static_block, objfile, section, 1);
|
| +}
|
| +
|
| +/* Subroutine of augment_type_symtab to simplify it.
|
| + Attach SYMTAB to all symbols in PENDING_LIST that don't have one. */
|
| +
|
| +static void
|
| +set_missing_symtab (struct pending *pending_list, struct symtab *symtab)
|
| +{
|
| + struct pending *pending;
|
| + int i;
|
| +
|
| + for (pending = pending_list; pending != NULL; pending = pending->next)
|
| {
|
| - obstack_free (&pending_addrmap_obstack, NULL);
|
| - pending_addrmap = NULL;
|
| + for (i = 0; i < pending->nsyms; ++i)
|
| + {
|
| + if (SYMBOL_SYMTAB (pending->symbol[i]) == NULL)
|
| + SYMBOL_SYMTAB (pending->symbol[i]) = symtab;
|
| + }
|
| }
|
| +}
|
|
|
| - return symtab;
|
| +/* Same as end_symtab, but for the case where we're adding more symbols
|
| + to an existing symtab that is known to contain only type information.
|
| + This is the case for DWARF4 Type Units. */
|
| +
|
| +void
|
| +augment_type_symtab (struct objfile *objfile, struct symtab *primary_symtab)
|
| +{
|
| + struct blockvector *blockvector = primary_symtab->blockvector;
|
| + int i;
|
| +
|
| + if (context_stack_depth > 0)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Context stack not empty in augment_type_symtab"));
|
| + context_stack_depth = 0;
|
| + }
|
| + if (pending_blocks != NULL)
|
| + complaint (&symfile_complaints, _("Blocks in a type symtab"));
|
| + if (pending_macros != NULL)
|
| + complaint (&symfile_complaints, _("Macro in a type symtab"));
|
| + if (have_line_numbers)
|
| + complaint (&symfile_complaints,
|
| + _("Line numbers recorded in a type symtab"));
|
| +
|
| + if (file_symbols != NULL)
|
| + {
|
| + struct block *block = BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK);
|
| +
|
| + /* First mark any symbols without a specified symtab as belonging
|
| + to the primary symtab. */
|
| + set_missing_symtab (file_symbols, primary_symtab);
|
| +
|
| + dict_add_pending (BLOCK_DICT (block), file_symbols);
|
| + }
|
| +
|
| + if (global_symbols != NULL)
|
| + {
|
| + struct block *block = BLOCKVECTOR_BLOCK (blockvector, GLOBAL_BLOCK);
|
| +
|
| + /* First mark any symbols without a specified symtab as belonging
|
| + to the primary symtab. */
|
| + set_missing_symtab (global_symbols, primary_symtab);
|
| +
|
| + dict_add_pending (BLOCK_DICT (block), global_symbols);
|
| + }
|
| +
|
| + reset_symtab_globals ();
|
| }
|
|
|
| /* Push a context block. Args are an identifying nesting level
|
| @@ -1251,7 +1428,7 @@ pop_context (void)
|
| /* Compute a small integer hash code for the given name. */
|
|
|
| int
|
| -hashname (char *name)
|
| +hashname (const char *name)
|
| {
|
| return (hash(name,strlen(name)) % HASHSIZE);
|
| }
|
|
|