questionable--see comment where we call them). */
#include "stabsread.h"
+/* List of free `struct pending' structures for reuse. */
+
+static struct pending *free_pendings;
+
+/* Non-zero if symtab has line number info. This prevents an otherwise empty
+ symtab from being tossed. */
+
+static int have_line_numbers;
+\f
static int
compare_line_numbers PARAMS ((const void *, const void *));
-static struct blockvector *
-make_blockvector PARAMS ((struct objfile *));
-
\f
/* Initial sizes of data structures. These are realloc'd larger if needed,
and realloc'd down to the size actually used, when completed. */
\f
/* Complaints about the symbols we have encountered. */
+struct complaint block_end_complaint =
+ {"block end address less than block start address in %s (patched it)", 0, 0};
+
+struct complaint anon_block_end_complaint =
+ {"block end address 0x%lx less than block start address 0x%lx (patched it)", 0, 0};
+
struct complaint innerblock_complaint =
{"inner block not inside outer block in %s", 0, 0};
struct complaint innerblock_anon_complaint =
- {"inner block not inside outer block", 0, 0};
+ {"inner block (0x%lx-0x%lx) not inside outer block (0x%lx-0x%lx)", 0, 0};
struct complaint blockvector_complaint =
{"block at 0x%lx out of order", 0, 0};
struct pending **listhead;
{
register struct pending *link;
+
+ /* If this is an alias for another symbol, don't add it. */
+ if (symbol->ginfo.name && symbol->ginfo.name[0] == '#')
+ return;
/* We keep PENDINGSIZE symbols in each link of the list.
If we don't have a link with room in it, add a new link. */
int foo;
{
struct pending *next, *next1;
-#if 0
- struct pending_block *bnext, *bnext1;
-#endif
for (next = free_pendings; next; next = next1)
{
}
free_pendings = NULL;
-#if 0 /* Now we make the links in the symbol_obstack, so don't free them. */
- for (bnext = pending_blocks; bnext; bnext = bnext1)
- {
- bnext1 = bnext->next;
- free ((PTR)bnext);
- }
-#endif
- pending_blocks = NULL;
+ free_pending_blocks ();
for (next = file_symbols; next != NULL; next = next1)
{
global_symbols = NULL;
}
+/* This function is called to discard any pending blocks. */
+
+void
+free_pending_blocks ()
+{
+#if 0 /* Now we make the links in the symbol_obstack, so don't free them. */
+ struct pending_block *bnext, *bnext1;
+
+ for (bnext = pending_blocks; bnext; bnext = bnext1)
+ {
+ bnext1 = bnext->next;
+ free ((PTR)bnext);
+ }
+#endif
+ pending_blocks = NULL;
+}
+
/* Take one of the lists of symbols and make a block from it.
Keep the order the symbols have in the list (reversed from the input file).
Put the block on the list of pending blocks. */
BLOCK_END (block) = end;
/* Superblock filled in when containing block is made */
BLOCK_SUPERBLOCK (block) = NULL;
+
BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
/* Put the block in as the value of the symbol that names it. */
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ case LOC_LOCAL_ARG:
nparams++;
break;
case LOC_UNDEF:
case LOC_CONST:
case LOC_STATIC:
+ case LOC_INDIRECT:
case LOC_REGISTER:
case LOC_LOCAL:
case LOC_TYPEDEF:
case LOC_LABEL:
case LOC_BLOCK:
case LOC_CONST_BYTES:
- case LOC_LOCAL_ARG:
case LOC_BASEREG:
- case LOC_BASEREG_ARG:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
default:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ case LOC_LOCAL_ARG:
TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
iparams++;
break;
case LOC_UNDEF:
case LOC_CONST:
case LOC_STATIC:
+ case LOC_INDIRECT:
case LOC_REGISTER:
case LOC_LOCAL:
case LOC_TYPEDEF:
case LOC_LABEL:
case LOC_BLOCK:
case LOC_CONST_BYTES:
- case LOC_LOCAL_ARG:
case LOC_BASEREG:
- case LOC_BASEREG_ARG:
case LOC_UNRESOLVED:
case LOC_OPTIMIZED_OUT:
default:
}
*listhead = NULL;
+#if 1
+ /* Check to be sure that the blocks have an end address that is
+ greater than starting address */
+
+ if (BLOCK_END (block) < BLOCK_START (block))
+ {
+ if (symbol)
+ {
+ complain (&block_end_complaint, SYMBOL_SOURCE_NAME (symbol));
+ }
+ else
+ {
+ complain (&anon_block_end_complaint, BLOCK_END (block), BLOCK_START (block));
+ }
+ /* Better than nothing */
+ BLOCK_END (block) = BLOCK_START (block);
+ }
+#endif
+
/* Install this block as the superblock
of all blocks made since the start of this scope
that don't have superblocks yet. */
}
else
{
- complain (&innerblock_anon_complaint);
+ complain (&innerblock_anon_complaint, BLOCK_START (pblock->block),
+ BLOCK_END (pblock->block), BLOCK_START (block),
+ BLOCK_END (block));
}
- BLOCK_START (pblock->block) = BLOCK_START (block);
- BLOCK_END (pblock->block) = BLOCK_END (block);
+ if (BLOCK_START (pblock->block) < BLOCK_START (block))
+ BLOCK_START (pblock->block) = BLOCK_START (block);
+ if (BLOCK_END (pblock->block) > BLOCK_END (block))
+ BLOCK_END (pblock->block) = BLOCK_END (block);
}
#endif
BLOCK_SUPERBLOCK (pblock->block) = block;
opblock = pblock;
}
- /* Record this block on the list of all blocks in the file.
- Put it after opblock, or at the beginning if opblock is 0.
- This puts the block in the list after all its subblocks. */
+ record_pending_block (objfile, block, opblock);
+}
+
+/* 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 block
+ in the list after all its subblocks.
+
+ Allocate the pending block struct in the symbol_obstack to save
+ time. This wastes a little space. FIXME: Is it worth it? */
+
+void
+record_pending_block (objfile, block, opblock)
+ struct objfile* objfile;
+ struct block *block;
+ struct pending_block *opblock;
+{
+ register struct pending_block *pblock;
- /* Allocate in the symbol_obstack to save time.
- It wastes a little space. */
pblock = (struct pending_block *)
- obstack_alloc (&objfile -> symbol_obstack,
- sizeof (struct pending_block));
- pblock->block = block;
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct pending_block));
+ pblock -> block = block;
if (opblock)
{
- pblock->next = opblock->next;
- opblock->next = pblock;
+ pblock -> next = opblock -> next;
+ opblock -> next = pblock;
}
else
{
- pblock->next = pending_blocks;
+ pblock -> next = pending_blocks;
pending_blocks = pblock;
}
}
-static struct blockvector *
+/* Note that this is only used in this file and in dstread.c, which should be
+ fixed to not need direct access to this function. When that is done, it can
+ be made static again. */
+
+struct blockvector *
make_blockvector (objfile)
struct objfile *objfile;
{
subfile->language = subfile->next->language;
}
+ /* Initialize the debug format string to NULL. We may supply it
+ later via a call to record_debugformat. */
+ subfile->debugformat = NULL;
+
/* cfront output is a C program, so in most ways it looks like a C
program. But to demangle we need to set the language to C++. We
can distinguish cfront code by the fact that it has #line
xmalloc (sizeof (struct linetable)
+ subfile->line_vector_length * sizeof (struct linetable_entry));
subfile->line_vector->nitems = 0;
+ have_line_numbers = 1;
}
if (subfile->line_vector->nitems + 1 >= subfile->line_vector_length)
static int
compare_line_numbers (ln1p, ln2p)
- const PTR ln1p;
- const PTR ln2p;
+ const void *ln1p;
+ const void *ln2p;
{
struct linetable_entry *ln1 = (struct linetable_entry *) ln1p;
struct linetable_entry *ln2 = (struct linetable_entry *) ln2p;
file_symbols = NULL;
global_symbols = NULL;
within_function = 0;
+ have_line_numbers = 0;
/* Context stack is initially empty. Allocate first one with room for
10 levels; reuse it forever afterward. */
if (context_stack_depth > 0)
{
- context_stack_depth--;
- cstk = &context_stack[context_stack_depth];
+ 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);
OBJF_REORDERED is true, then sort the pending blocks. */
if ((objfile->flags & OBJF_REORDERED) && pending_blocks)
{
- /* FIXME! Remove this horrid bubble sort and use qsort!!!
- It'd be a whole lot easier if they weren't in a linked list!!! */
+ /* FIXME! Remove this horrid bubble sort and use merge sort!!! */
int swapped;
do
{
if (pending_blocks == NULL
&& file_symbols == NULL
- && global_symbols == NULL)
+ && global_symbols == NULL
+ && have_line_numbers == 0)
{
/* Ignore symtabs that have no functions with real debugging info */
blockvector = NULL;
blockvector = make_blockvector (objfile);
}
-#ifdef PROCESS_LINENUMBER_HOOK
- PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
+#ifndef PROCESS_LINENUMBER_HOOK
+#define PROCESS_LINENUMBER_HOOK()
#endif
+ PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
/* Now create the symtab objects proper, one for each subfile. */
/* (The main file is the last one on the chain.) */
language it is from things we found in the symbols. */
symtab->language = subfile->language;
+ /* Save the debug format string (if any) in the symtab */
+ if (subfile -> debugformat != NULL)
+ {
+ symtab->debugformat = obsavestring (subfile->debugformat,
+ strlen (subfile->debugformat),
+ &objfile -> symbol_obstack);
+ }
+
/* All symtabs for the main file and the subfiles share a
blockvector, so we need to clear primary for everything but
the main file. */
{
free ((PTR) subfile->line_vector);
}
+ if (subfile->debugformat != NULL)
+ {
+ free ((PTR) subfile->debugformat);
+ }
nextsub = subfile->next;
free ((PTR)subfile);
new = &context_stack[context_stack_depth++];
new->depth = desc;
new->locals = local_symbols;
+ new->params = param_symbols;
new->old_blocks = pending_blocks;
new->start_addr = valu;
new->name = NULL;
local_symbols = NULL;
+ param_symbols = NULL;
return (new);
}
return (total % HASHSIZE);
}
+\f
+void
+record_debugformat (format)
+ char *format;
+{
+ current_subfile -> debugformat = savestring (format, strlen (format));
+}
+
+
+/* Merge the first symbol list SRCLIST into the second symbol list
+ TARGETLIST by repeated calls to add_symbol_to_list(). This
+ procedure "frees" each link of SRCLIST by adding it to the
+ free_pendings list. Caller must set SRCLIST to a null list after
+ calling this function.
+
+ Void return. */
+
+void
+merge_symbol_lists (srclist, targetlist)
+ struct pending ** srclist;
+ struct pending ** targetlist;
+{
+ register int i;
+ register struct pending * link;
+
+ if (!srclist || !*srclist)
+ return;
+
+ /* Merge in elements from current link */
+ for (i=0; i < (*srclist)->nsyms; i++)
+ add_symbol_to_list ((*srclist)->symbol[i], targetlist);
+
+ /* Recurse on next */
+ merge_symbol_lists (&(*srclist)->next, targetlist);
+
+ /* "Free" the current link */
+ (*srclist)->next = free_pendings;
+ free_pendings = (*srclist);
+}
+
+
+
\f
/* Initialize anything that needs initializing when starting to read
a fresh piece of a symbol file, e.g. reading in the stuff corresponding