/* Support routines for building symbol tables in GDB's internal format.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This module provides subroutines used for creating and adding to
the symbol table. These routines are called from various symbol-
#include "block.h"
#include "cp-support.h"
#include "dictionary.h"
+#include "addrmap.h"
/* Ask buildsym.h to define the vars it normally declares `extern'. */
#define EXTERN
#include "stabsread.h"
+/* List of subfiles. */
+
+static struct subfile *subfiles;
+
/* List of free `struct pending' structures for reuse. */
static struct pending *free_pendings;
otherwise empty symtab from being tossed. */
static int have_line_numbers;
+
+/* The mutable address map for the compilation unit whose symbols
+ we're currently reading. The symtabs' shared blockvector will
+ point to a fixed copy of this. */
+static struct addrmap *pending_addrmap;
+
+/* The obstack on which we allocate pending_addrmap.
+ If pending_addrmap is NULL, this is uninitialized; otherwise, it is
+ initialized (and holds pending_addrmap). */
+static struct obstack pending_addrmap_obstack;
+
+/* Non-zero if we recorded any ranges in the addrmap that are
+ different from those in the blockvector already. We set this to
+ zero when we start processing a symfile, and if it's still zero at
+ the end, then we just toss the addrmap. */
+static int pending_addrmap_interesting;
+
\f
static int compare_line_numbers (const void *ln1p, const void *ln2p);
\f
}
(*listhead)->symbol[(*listhead)->nsyms++] = symbol;
-
- /* Check to see if we might need to look for a mention of anonymous
- namespaces. */
-
- if (SYMBOL_LANGUAGE (symbol) == language_cplus)
- cp_scan_for_anonymous_namespaces (symbol);
}
/* Find a symbol named NAME on a LIST. NAME need not be
{
for (j = list->nsyms; --j >= 0;)
{
- pp = DEPRECATED_SYMBOL_NAME (list->symbol[j]);
+ pp = SYMBOL_LINKAGE_NAME (list->symbol[j]);
if (*pp == *name && strncmp (pp, name, length) == 0 &&
pp[length] == '\0')
{
if (pending_macros)
free_macro_table (pending_macros);
+
+ if (pending_addrmap)
+ {
+ obstack_free (&pending_addrmap_obstack, NULL);
+ pending_addrmap = NULL;
+ }
}
/* This function is called to discard any pending blocks. */
void
free_pending_blocks (void)
{
-#if 0 /* Now we make the links in the
- objfile_obstack, so don't free
- them. */
- struct pending_block *bnext, *bnext1;
-
- for (bnext = pending_blocks; bnext; bnext = bnext1)
- {
- bnext1 = bnext->next;
- xfree ((void *) bnext);
- }
-#endif
+ /* The links are made in the objfile_obstack, so we only need to
+ reset PENDING_BLOCKS. */
pending_blocks = NULL;
}
the order the symbols have in the list (reversed from the input
file). Put the block on the list of pending blocks. */
-void
+struct block *
finish_block (struct symbol *symbol, struct pending **listhead,
struct pending_block *old_blocks,
CORE_ADDR start, CORE_ADDR end,
BLOCK_SUPERBLOCK (block) = NULL;
BLOCK_NAMESPACE (block) = NULL;
- BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
-
/* Put the block in as the value of the symbol that names it. */
if (symbol)
struct symbol *sym;
ALL_BLOCK_SYMBOLS (block, iter, sym)
{
- switch (SYMBOL_CLASS (sym))
- {
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM:
- case LOC_REGPARM_ADDR:
- case LOC_BASEREG_ARG:
- case LOC_LOCAL_ARG:
- case LOC_COMPUTED_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_BASEREG:
- case LOC_UNRESOLVED:
- case LOC_OPTIMIZED_OUT:
- case LOC_COMPUTED:
- default:
- break;
- }
+ if (SYMBOL_IS_ARGUMENT (sym))
+ nparams++;
}
if (nparams > 0)
{
if (iparams == nparams)
break;
- switch (SYMBOL_CLASS (sym))
+ if (SYMBOL_IS_ARGUMENT (sym))
{
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM:
- case LOC_REGPARM_ADDR:
- case LOC_BASEREG_ARG:
- case LOC_LOCAL_ARG:
- case LOC_COMPUTED_ARG:
TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
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_BASEREG:
- case LOC_UNRESOLVED:
- case LOC_OPTIMIZED_OUT:
- case LOC_COMPUTED:
- default:
- break;
}
}
}
}
-
- /* If we're in the C++ case, set the block's scope. */
- if (SYMBOL_LANGUAGE (symbol) == language_cplus)
- {
- cp_set_block_scope (symbol, block, &objfile->objfile_obstack);
- }
}
else
{
}
*listhead = NULL;
-#if 1
/* Check to be sure that the blocks have an end address that is
greater than starting address */
/* 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. */
{
if (BLOCK_SUPERBLOCK (pblock->block) == NULL)
{
-#if 1
/* Check to be sure the blocks are nested as we receive
them. If the compiler/assembler/linker work, this just
- burns a small amount of time. */
- if (BLOCK_START (pblock->block) < BLOCK_START (block) ||
- BLOCK_END (pblock->block) > BLOCK_END (block))
+ burns a small amount of time.
+
+ Skip blocks which correspond to a function; they're not
+ physically nested inside this other blocks, only
+ lexically nested. */
+ if (BLOCK_FUNCTION (pblock->block) == NULL
+ && (BLOCK_START (pblock->block) < BLOCK_START (block)
+ || BLOCK_END (pblock->block) > BLOCK_END (block)))
{
if (symbol)
{
if (BLOCK_END (pblock->block) > BLOCK_END (block))
BLOCK_END (pblock->block) = BLOCK_END (block);
}
-#endif
BLOCK_SUPERBLOCK (pblock->block) = block;
}
opblock = pblock;
}
record_pending_block (objfile, block, opblock);
+
+ return block;
}
}
}
+
+/* Record that the range of addresses from START to END_INCLUSIVE
+ (inclusive, like it says) belongs to BLOCK. BLOCK's start and end
+ addresses must be set already. You must apply this function to all
+ BLOCK's children before applying it to BLOCK.
+
+ If a call to this function complicates the picture beyond that
+ already provided by BLOCK_START and BLOCK_END, then we create an
+ address map for the block. */
+void
+record_block_range (struct block *block,
+ CORE_ADDR start, CORE_ADDR end_inclusive)
+{
+ /* If this is any different from the range recorded in the block's
+ own BLOCK_START and BLOCK_END, then note that the address map has
+ become interesting. Note that even if this block doesn't have
+ any "interesting" ranges, some later block might, so we still
+ need to record this block in the addrmap. */
+ if (start != BLOCK_START (block)
+ || end_inclusive + 1 != BLOCK_END (block))
+ pending_addrmap_interesting = 1;
+
+ if (! pending_addrmap)
+ {
+ obstack_init (&pending_addrmap_obstack);
+ pending_addrmap = addrmap_create_mutable (&pending_addrmap_obstack);
+ }
+
+ addrmap_set_empty (pending_addrmap, start, end_inclusive, block);
+}
+
+
static struct blockvector *
make_blockvector (struct objfile *objfile)
{
BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
}
-#if 0 /* Now we make the links in the
- obstack, so don't free them. */
- /* Now free the links of the list, and empty the list. */
-
- for (next = pending_blocks; next; next = next1)
- {
- next1 = next->next;
- xfree (next);
- }
-#endif
- pending_blocks = NULL;
+ free_pending_blocks ();
-#if 1 /* FIXME, shut this off after a while
- to speed up symbol reading. */
+ /* If we needed an address map for this symtab, record it in the
+ blockvector. */
+ if (pending_addrmap && pending_addrmap_interesting)
+ BLOCKVECTOR_MAP (blockvector)
+ = 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. FIXME. */
+ order and moan about it. */
if (BLOCKVECTOR_NBLOCKS (blockvector) > 1)
{
for (i = 1; i < BLOCKVECTOR_NBLOCKS (blockvector); i++)
}
}
}
-#endif
return (blockvector);
}
/* Start recording information about source code that came from an
included (or otherwise merged-in) source file with a different
name. NAME is the name of the file (cannot be NULL), DIRNAME is
- the directory in which it resides (or NULL if not known). */
+ the directory in which the file was compiled (or NULL if not known). */
void
start_subfile (char *name, char *dirname)
for (subfile = subfiles; subfile; subfile = subfile->next)
{
- if (FILENAME_CMP (subfile->name, name) == 0)
+ char *subfile_name;
+
+ /* If NAME is an absolute path, and this subfile is not, then
+ attempt to create an absolute path to compare. */
+ if (IS_ABSOLUTE_PATH (name)
+ && !IS_ABSOLUTE_PATH (subfile->name)
+ && subfile->dirname != NULL)
+ subfile_name = concat (subfile->dirname, SLASH_STRING,
+ subfile->name, (char *) NULL);
+ else
+ subfile_name = subfile->name;
+
+ if (FILENAME_CMP (subfile_name, name) == 0)
{
current_subfile = subfile;
+ if (subfile_name != subfile->name)
+ xfree (subfile_name);
return;
}
+ if (subfile_name != subfile->name)
+ xfree (subfile_name);
}
/* This subfile is not known. Add an entry for it. Make an entry
current_subfile = subfile;
/* Save its name and compilation directory name */
- subfile->name = (name == NULL) ? NULL : savestring (name, strlen (name));
- subfile->dirname =
- (dirname == NULL) ? NULL : savestring (dirname, strlen (dirname));
+ subfile->name = (name == NULL) ? NULL : xstrdup (name);
+ subfile->dirname = (dirname == NULL) ? NULL : xstrdup (dirname);
/* Initialize line-number recording for this subfile. */
subfile->line_vector = NULL;
later via a call to record_debugformat. */
subfile->debugformat = NULL;
+ /* Similarly for the producer. */
+ subfile->producer = NULL;
+
/* If the filename of this subfile ends in .C, then change the
language of any pending subfiles from C to C++. We also accept
any other C++ suffixes accepted by deduce_language_from_filename. */
&& subfile->name[strlen (subfile->name) - 1] == '/')
{
subfile->dirname = subfile->name;
- subfile->name = savestring (name, strlen (name));
+ subfile->name = xstrdup (name);
last_source_file = name;
/* Default the source language to whatever can be deduced from
* sizeof (struct linetable_entry))));
}
+ pc = gdbarch_addr_bits_remove (current_gdbarch, pc);
+
+ /* Normally, we treat lines as unsorted. But the end of sequence
+ marker is special. We sort line markers at the same PC by line
+ number, so end of sequence markers (which have line == 0) appear
+ first. This is right if the marker ends the previous function,
+ and there is no padding before the next function. But it is
+ wrong if the previous line was empty and we are now marking a
+ switch to a different subfile. We must leave the end of sequence
+ marker at the end of this group of lines, not sort the empty line
+ to after the marker. The easiest way to accomplish this is to
+ delete any empty lines from our table, if they are followed by
+ end of sequence markers. All we lose is the ability to set
+ breakpoints at some lines which contain no instructions
+ anyway. */
+ if (line == 0 && subfile->line_vector->nitems > 0)
+ {
+ e = subfile->line_vector->item + subfile->line_vector->nitems - 1;
+ while (subfile->line_vector->nitems > 0 && e->pc == pc)
+ {
+ e--;
+ subfile->line_vector->nitems--;
+ }
+ }
+
e = subfile->line_vector->item + subfile->line_vector->nitems++;
e->line = line;
- e->pc = ADDR_BITS_REMOVE(pc);
+ e->pc = pc;
}
/* Needed in order to sort line tables from IBM xcoff files. Sigh! */
/* Start a new symtab for a new source file. Called, for example,
when a stabs symbol of type N_SO is seen, or when a DWARF
TAG_compile_unit DIE is seen. It indicates the start of data for
- one original source file. */
+ one original source file.
+
+ NAME is the name of the file (cannot be NULL). DIRNAME is the directory in
+ which the file was compiled (or NULL if not known). START_ADDR is the
+ lowest address of objects in the file (or 0 if not known). */
void
start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
{
-
last_source_file = name;
last_source_start_addr = start_addr;
file_symbols = NULL;
}
context_stack_depth = 0;
+ /* We shouldn't have any address map at this point. */
+ gdb_assert (! pending_addrmap);
+
/* Set up support for C++ namespace support, in case we need it. */
cp_initialize_namespace ();
start_subfile (name, dirname);
}
+/* Subroutine of end_symtab to simplify it.
+ Look for a subfile that matches the main source file's basename.
+ If there is only one, and if the main source file doesn't have any
+ symbol or line number information, then copy this file's symtab and
+ line_vector to the main source file's subfile and discard the other subfile.
+ This can happen because of a compiler bug or from the user playing games
+ with #line or from things like a distributed build system that manipulates
+ the debug info. */
+
+static void
+watch_main_source_file_lossage (void)
+{
+ struct subfile *mainsub, *subfile;
+
+ /* Find the main source file.
+ This loop could be eliminated if start_symtab saved it for us. */
+ mainsub = NULL;
+ for (subfile = subfiles; subfile; subfile = subfile->next)
+ {
+ /* The main subfile is guaranteed to be the last one. */
+ if (subfile->next == NULL)
+ mainsub = subfile;
+ }
+
+ /* If the main source file doesn't have any line number or symbol info,
+ look for an alias in another subfile.
+ We have to watch for mainsub == NULL here. It's a quirk of end_symtab,
+ it can return NULL so there may not be a main subfile. */
+
+ if (mainsub
+ && mainsub->line_vector == NULL
+ && mainsub->symtab == NULL)
+ {
+ const char *mainbase = lbasename (mainsub->name);
+ int nr_matches = 0;
+ struct subfile *prevsub;
+ struct subfile *mainsub_alias = NULL;
+ struct subfile *prev_mainsub_alias = NULL;
+
+ prevsub = NULL;
+ for (subfile = subfiles;
+ /* Stop before we get to the last one. */
+ subfile->next;
+ subfile = subfile->next)
+ {
+ if (strcmp (lbasename (subfile->name), mainbase) == 0)
+ {
+ ++nr_matches;
+ mainsub_alias = subfile;
+ prev_mainsub_alias = prevsub;
+ }
+ prevsub = subfile;
+ }
+
+ if (nr_matches == 1)
+ {
+ gdb_assert (mainsub_alias != NULL && mainsub_alias != mainsub);
+
+ /* Found a match for the main source file.
+ Copy its line_vector and symtab to the main subfile
+ and then discard it. */
+
+ mainsub->line_vector = mainsub_alias->line_vector;
+ mainsub->line_vector_length = mainsub_alias->line_vector_length;
+ mainsub->symtab = mainsub_alias->symtab;
+
+ if (prev_mainsub_alias == NULL)
+ subfiles = mainsub_alias->next;
+ else
+ prev_mainsub_alias->next = mainsub_alias->next;
+ xfree (mainsub_alias);
+ }
+ }
+}
+
/* 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
&objfile->objfile_obstack);
}
-#ifndef PROCESS_LINENUMBER_HOOK
-#define PROCESS_LINENUMBER_HOOK()
-#endif
- PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
+ /* Read the line table if it has to be read separately. */
+ if (objfile->sf->sym_read_linetable != NULL)
+ objfile->sf->sym_read_linetable ();
+
+ /* Handle the case where the debug info specifies a different path
+ for the main source file. It can cause us to lose track of its
+ line number information. */
+ watch_main_source_file_lossage ();
/* Now create the symtab objects proper, one for each subfile. */
/* (The main file is the last one on the chain.) */
{
linetablesize = sizeof (struct linetable) +
subfile->line_vector->nitems * sizeof (struct linetable_entry);
-#if 0
- /* I think this is artifact from before it went on the
- obstack. I doubt we'll need the memory between now
- and when we free it later in this function. */
- /* First, shrink the linetable to make more memory. */
- subfile->line_vector = (struct linetable *)
- xrealloc ((char *) subfile->line_vector, linetablesize);
-#endif
/* Like the pending blocks, the line table may be
scrambled in reordered executables. Sort it if
}
/* Now, allocate a symbol table. */
- symtab = allocate_symtab (subfile->name, objfile);
+ if (subfile->symtab == NULL)
+ symtab = allocate_symtab (subfile->name, objfile);
+ else
+ symtab = subfile->symtab;
/* Fill in its components. */
symtab->blockvector = blockvector;
&objfile->objfile_obstack);
}
+ /* Similarly for the producer. */
+ if (subfile->producer != NULL)
+ symtab->producer = obsavestring (subfile->producer,
+ strlen (subfile->producer),
+ &objfile->objfile_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. */
symtab->primary = 0;
}
+ else
+ {
+ if (subfile->symtab)
+ {
+ /* 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
+ such as the block-vector are uninitialized whereas
+ the rest of the code assumes that they are.
+
+ We can only unlink the symtab because it was allocated
+ on the objfile obstack. */
+ struct symtab *s;
+
+ if (objfile->symtabs == subfile->symtab)
+ objfile->symtabs = objfile->symtabs->next;
+ else
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ if (s->next == subfile->symtab)
+ {
+ s->next = s->next->next;
+ break;
+ }
+ subfile->symtab = NULL;
+ }
+ }
if (subfile->name != NULL)
{
xfree ((void *) subfile->name);
{
xfree ((void *) subfile->debugformat);
}
+ if (subfile->producer != NULL)
+ xfree (subfile->producer);
nextsub = subfile->next;
xfree ((void *) subfile);
symtab->primary = 1;
}
+ /* Default any symbols without a specified symtab to the primary
+ symtab. */
+ if (blockvector)
+ {
+ int block_i;
+
+ for (block_i = 0; block_i < BLOCKVECTOR_NBLOCKS (blockvector); block_i++)
+ {
+ struct block *block = BLOCKVECTOR_BLOCK (blockvector, block_i);
+ struct symbol *sym;
+ struct dict_iterator iter;
+
+ for (sym = dict_iterator_first (BLOCK_DICT (block), &iter);
+ sym != NULL;
+ sym = dict_iterator_next (&iter))
+ if (SYMBOL_SYMTAB (sym) == NULL)
+ SYMBOL_SYMTAB (sym) = symtab;
+ }
+ }
+
last_source_file = NULL;
current_subfile = NULL;
pending_macros = NULL;
+ if (pending_addrmap)
+ {
+ obstack_free (&pending_addrmap_obstack, NULL);
+ pending_addrmap = NULL;
+ }
return symtab;
}
void
record_debugformat (char *format)
{
- current_subfile->debugformat = savestring (format, strlen (format));
+ current_subfile->debugformat = xstrdup (format);
+}
+
+void
+record_producer (const char *producer)
+{
+ /* The producer is not always provided in the debugging info.
+ Do nothing if PRODUCER is NULL. */
+ if (producer == NULL)
+ return;
+
+ current_subfile->producer = xstrdup (producer);
}
/* Merge the first symbol list SRCLIST into the second symbol list
global_symbols = NULL;
pending_blocks = NULL;
pending_macros = NULL;
+
+ /* We shouldn't have any address map at this point. */
+ gdb_assert (! pending_addrmap);
+ pending_addrmap_interesting = 0;
}
/* Initialize anything that needs initializing when a completely new