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); |
} |