2003-04-09 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / symfile.c
index d5aeba3a1f378b6161fa763219e12a437c9db09e..7d7886a29215328d522d77d4bd4b16efb141d375 100644 (file)
@@ -1,6 +1,8 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001 Free Software Foundation, Inc.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
    This file is part of GDB.
@@ -21,6 +23,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "bfdlink.h"
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "gdbcore.h"
 #include "value.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "source.h"
 #include "gdbcmd.h"
 #include "breakpoint.h"
 #include "language.h"
 #include "complaints.h"
 #include "demangle.h"
 #include "inferior.h"          /* for write_pc */
+#include "filenames.h"         /* for DOSish file names */
 #include "gdb-stabs.h"
-#include "obstack.h"
+#include "gdb_obstack.h"
 #include "completer.h"
+#include "bcache.h"
+#include "hashtab.h"
+#include <readline/readline.h>
+#include "gdb_assert.h"
+#include "block.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -78,21 +88,6 @@ static void clear_symtab_users_cleanup (void *ignore);
 /* Global variables owned by this file */
 int readnow_symbol_files;      /* Read full symbols immediately */
 
-struct complaint oldsyms_complaint =
-{
-  "Replacing old symbols for `%s'", 0, 0
-};
-
-struct complaint empty_symtab_complaint =
-{
-  "Empty symbol table found for `%s'", 0, 0
-};
-
-struct complaint unknown_option_complaint =
-{
-  "Unknown option `%s' ignored", 0, 0
-};
-
 /* External variables and functions referenced. */
 
 extern void report_transfer_performance (unsigned long, time_t, time_t);
@@ -114,10 +109,14 @@ static void add_symbol_file_command (char *, int);
 
 static void add_shared_symbol_files_command (char *, int);
 
+static void reread_separate_symbols (struct objfile *objfile);
+
 static void cashier_psymtab (struct partial_symtab *);
 
 bfd *symfile_bfd_open (char *);
 
+int get_section_index (struct objfile *, char *);
+
 static void find_sym_fns (struct objfile *);
 
 static void decrement_reading_symtab (void *);
@@ -156,6 +155,8 @@ static void set_ext_lang_command (char *args, int from_tty);
 
 static void info_ext_lang_command (char *args, int from_tty);
 
+static char *find_separate_debug_file (struct objfile *objfile);
+
 static void init_filename_language_table (void);
 
 void _initialize_symfile (void);
@@ -209,55 +210,20 @@ compare_symbols (const void *s1p, const void *s2p)
 
   s1 = (struct symbol **) s1p;
   s2 = (struct symbol **) s2p;
-  return (strcmp (SYMBOL_SOURCE_NAME (*s1), SYMBOL_SOURCE_NAME (*s2)));
+  return (strcmp (SYMBOL_NATURAL_NAME (*s1), SYMBOL_NATURAL_NAME (*s2)));
 }
 
-/*
-
-   LOCAL FUNCTION
-
-   compare_psymbols -- compare two partial symbols by name
-
-   DESCRIPTION
-
-   Given pointers to pointers to two partial symbol table entries,
-   compare them by name and return -N, 0, or +N (ala strcmp).
-   Typically used by sorting routines like qsort().
-
-   NOTES
-
-   Does direct compare of first two characters before punting
-   and passing to strcmp for longer compares.  Note that the
-   original version had a bug whereby two null strings or two
-   identically named one character strings would return the
-   comparison of memory following the null byte.
-
- */
+/* This compares two partial symbols by names, using strcmp_iw_ordered
+   for the comparison.  */
 
 static int
 compare_psymbols (const void *s1p, const void *s2p)
 {
-  register struct partial_symbol **s1, **s2;
-  register char *st1, *st2;
+  struct partial_symbol *const *s1 = s1p;
+  struct partial_symbol *const *s2 = s2p;
 
-  s1 = (struct partial_symbol **) s1p;
-  s2 = (struct partial_symbol **) s2p;
-  st1 = SYMBOL_SOURCE_NAME (*s1);
-  st2 = SYMBOL_SOURCE_NAME (*s2);
-
-
-  if ((st1[0] - st2[0]) || !st1[0])
-    {
-      return (st1[0] - st2[0]);
-    }
-  else if ((st1[1] - st2[1]) || !st1[1])
-    {
-      return (st1[1] - st2[1]);
-    }
-  else
-    {
-      return (strcmp (st1, st2));
-    }
+  return strcmp_iw_ordered (SYMBOL_NATURAL_NAME (*s1),
+                           SYMBOL_NATURAL_NAME (*s2));
 }
 
 void
@@ -308,16 +274,16 @@ sort_symtab_syms (register struct symtab *s)
    may be part of a larger string and we are only saving a substring. */
 
 char *
-obsavestring (char *ptr, int size, struct obstack *obstackp)
+obsavestring (const char *ptr, int size, struct obstack *obstackp)
 {
   register char *p = (char *) obstack_alloc (obstackp, size + 1);
   /* Open-coded memcpy--saves function call time.  These strings are usually
      short.  FIXME: Is this really still true with a compiler that can
      inline memcpy? */
   {
-    register char *p1 = ptr;
+    register const char *p1 = ptr;
     register char *p2 = p;
-    char *end = ptr + size;
+    const char *end = ptr + size;
     while (p1 != end)
       *p2++ = *p1++;
   }
@@ -419,7 +385,7 @@ entry_point_address (void)
    lowest-addressed loadable section.  */
 
 void
-find_lowest_section (bfd *abfd, asection *sect, PTR obj)
+find_lowest_section (bfd *abfd, asection *sect, void *obj)
 {
   asection **lowest = (asection **) obj;
 
@@ -452,11 +418,13 @@ build_section_addr_info_from_section_table (const struct section_table *start,
 
   for (stp = start, oidx = 0; stp != end; stp++)
     {
-      if (stp->the_bfd_section->flags & (SEC_ALLOC | SEC_LOAD)
+      if (bfd_get_section_flags (stp->bfd, 
+                                stp->the_bfd_section) & (SEC_ALLOC | SEC_LOAD)
          && oidx < MAX_SECTIONS)
        {
          sap->other[oidx].addr = stp->addr;
-         sap->other[oidx].name = xstrdup (stp->the_bfd_section->name);
+         sap->other[oidx].name 
+           = xstrdup (bfd_section_name (stp->bfd, stp->the_bfd_section));
          sap->other[oidx].sectindex = stp->the_bfd_section->index;
          oidx++;
        }
@@ -480,6 +448,60 @@ free_section_addr_info (struct section_addr_info *sap)
 }
 
 
+/* Initialize OBJFILE's sect_index_* members.  */
+static void
+init_objfile_sect_indices (struct objfile *objfile)
+{
+  asection *sect;
+  int i;
+  
+  sect = bfd_get_section_by_name (objfile->obfd, ".text");
+  if (sect) 
+    objfile->sect_index_text = sect->index;
+
+  sect = bfd_get_section_by_name (objfile->obfd, ".data");
+  if (sect) 
+    objfile->sect_index_data = sect->index;
+
+  sect = bfd_get_section_by_name (objfile->obfd, ".bss");
+  if (sect) 
+    objfile->sect_index_bss = sect->index;
+
+  sect = bfd_get_section_by_name (objfile->obfd, ".rodata");
+  if (sect) 
+    objfile->sect_index_rodata = sect->index;
+
+  /* This is where things get really weird...  We MUST have valid
+     indices for the various sect_index_* members or gdb will abort.
+     So if for example, there is no ".text" section, we have to
+     accomodate that.  Except when explicitly adding symbol files at
+     some address, section_offsets contains nothing but zeros, so it
+     doesn't matter which slot in section_offsets the individual
+     sect_index_* members index into.  So if they are all zero, it is
+     safe to just point all the currently uninitialized indices to the
+     first slot. */
+
+  for (i = 0; i < objfile->num_sections; i++)
+    {
+      if (ANOFFSET (objfile->section_offsets, i) != 0)
+       {
+         break;
+       }
+    }
+  if (i == objfile->num_sections)
+    {
+      if (objfile->sect_index_text == -1)
+       objfile->sect_index_text = 0;
+      if (objfile->sect_index_data == -1)
+       objfile->sect_index_data = 0;
+      if (objfile->sect_index_bss == -1)
+       objfile->sect_index_bss = 0;
+      if (objfile->sect_index_rodata == -1)
+       objfile->sect_index_rodata = 0;
+    }
+}
+
+
 /* Parse the user's idea of an offset for dynamic linking, into our idea
    of how to represent it for fast symbol reading.  This is the default 
    version of the sym_fns.sym_offsets function for symbol readers that
@@ -491,7 +513,6 @@ default_symfile_offsets (struct objfile *objfile,
                         struct section_addr_info *addrs)
 {
   int i;
-  asection *sect = NULL;
 
   objfile->num_sections = SECT_OFF_MAX;
   objfile->section_offsets = (struct section_offsets *)
@@ -516,32 +537,35 @@ default_symfile_offsets (struct objfile *objfile,
 
   /* Remember the bfd indexes for the .text, .data, .bss and
      .rodata sections. */
-
-  sect = bfd_get_section_by_name (objfile->obfd, ".text");
-  if (sect) 
-    objfile->sect_index_text = sect->index;
-
-  sect = bfd_get_section_by_name (objfile->obfd, ".data");
-  if (sect) 
-    objfile->sect_index_data = sect->index;
-
-  sect = bfd_get_section_by_name (objfile->obfd, ".bss");
-  if (sect) 
-    objfile->sect_index_bss = sect->index;
-
-  sect = bfd_get_section_by_name (objfile->obfd, ".rodata");
-  if (sect) 
-    objfile->sect_index_rodata = sect->index;
-
+  init_objfile_sect_indices (objfile);
 }
 
+
 /* Process a symbol file, as either the main file or as a dynamically
    loaded file.
 
    OBJFILE is where the symbols are to be read from.
 
-   ADDR is the address where the text segment was loaded, unless the
-   objfile is the main symbol file, in which case it is zero.
+   ADDRS is the list of section load addresses.  If the user has given
+   an 'add-symbol-file' command, then this is the list of offsets and
+   addresses he or she provided as arguments to the command; or, if
+   we're handling a shared library, these are the actual addresses the
+   sections are loaded at, according to the inferior's dynamic linker
+   (as gleaned by GDB's shared library code).  We convert each address
+   into an offset from the section VMA's as it appears in the object
+   file, and then call the file's sym_offsets function to convert this
+   into a format-specific offset table --- a `struct section_offsets'.
+   If ADDRS is non-zero, OFFSETS must be zero.
+
+   OFFSETS is a table of section offsets already in the right
+   format-specific representation.  NUM_OFFSETS is the number of
+   elements present in OFFSETS->offsets.  If OFFSETS is non-zero, we
+   assume this is the proper table the call to sym_offsets described
+   above would produce.  Instead of calling sym_offsets, we just dump
+   it right into objfile->section_offsets.  (When we're re-reading
+   symbols from an objfile, we don't have the original load address
+   list any more; all we have is the section offset table.)  If
+   OFFSETS is non-zero, ADDRS must be zero.
 
    MAINLINE is nonzero if this is the main symbol file, or zero if
    it's an extra symbol file such as dynamically loaded code.
@@ -550,8 +574,12 @@ default_symfile_offsets (struct objfile *objfile,
    the symbol reading (and complaints can be more terse about it).  */
 
 void
-syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
-                  int mainline, int verbo)
+syms_from_objfile (struct objfile *objfile,
+                   struct section_addr_info *addrs,
+                   struct section_offsets *offsets,
+                   int num_offsets,
+                  int mainline,
+                   int verbo)
 {
   asection *lower_sect;
   asection *sect;
@@ -560,19 +588,25 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
   struct cleanup *old_chain;
   int i;
 
-  /* If ADDRS is NULL, initialize the local section_addr_info struct and
-     point ADDRS to it.  We now establish the convention that an addr of
-     zero means no load address was specified. */
+  gdb_assert (! (addrs && offsets));
 
-  if (addrs == NULL)
+  /* If ADDRS and OFFSETS are both NULL, put together a dummy address
+     list.  We now establish the convention that an addr of zero means
+     no load address was specified. */
+  if (! addrs && ! offsets)
     {
       memset (&local_addr, 0, sizeof (local_addr));
       addrs = &local_addr;
     }
 
+  /* Now either addrs or offsets is non-zero.  */
+
   init_entry_point_info (objfile);
   find_sym_fns (objfile);
 
+  if (objfile->sf == NULL)
+    return;    /* No symbols. */
+
   /* Make sure that partially constructed symbol tables will be cleaned up
      if an error occurs during symbol reading.  */
   old_chain = make_cleanup_free_objfile (objfile);
@@ -613,7 +647,7 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
       lower_sect = bfd_get_section_by_name (objfile->obfd, ".text");
       if (lower_sect == NULL)
        bfd_map_over_sections (objfile->obfd, find_lowest_section,
-                              (PTR) &lower_sect);
+                              &lower_sect);
       if (lower_sect == NULL)
        warning ("no loadable sections found in added symbol-file %s",
                 objfile->name);
@@ -628,39 +662,43 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
       else
        lower_offset = 0;
  
-       /* Calculate offsets for the loadable sections.
+      /* Calculate offsets for the loadable sections.
         FIXME! Sections must be in order of increasing loadable section
         so that contiguous sections can use the lower-offset!!!
  
-          Adjust offsets if the segments are not contiguous.
-          If the section is contiguous, its offset should be set to
+         Adjust offsets if the segments are not contiguous.
+         If the section is contiguous, its offset should be set to
         the offset of the highest loadable section lower than it
         (the loadable section directly below it in memory).
         this_offset = lower_offset = lower_addr - lower_orig_addr */
 
-       /* Calculate offsets for sections. */
-      for (i=0 ; i < MAX_SECTIONS && addrs->other[i].name; i++)
-       {
-         if (addrs->other[i].addr != 0)
-           {
-             sect = bfd_get_section_by_name (objfile->obfd, addrs->other[i].name);
-             if (sect)
-               {
-                 addrs->other[i].addr -= bfd_section_vma (objfile->obfd, sect);
-                 lower_offset = addrs->other[i].addr;
-                 /* This is the index used by BFD. */
-                 addrs->other[i].sectindex = sect->index ;
-               }
-             else
-               {
-                 warning ("section %s not found in %s", addrs->other[i].name, 
-                          objfile->name);
-                 addrs->other[i].addr = 0;
-               }
-           }
-         else
-           addrs->other[i].addr = lower_offset;
-       }
+      /* Calculate offsets for sections. */
+      if (addrs)
+        for (i=0 ; i < MAX_SECTIONS && addrs->other[i].name; i++)
+          {
+            if (addrs->other[i].addr != 0)
+              {
+                sect = bfd_get_section_by_name (objfile->obfd,
+                                                addrs->other[i].name);
+                if (sect)
+                  {
+                    addrs->other[i].addr
+                      -= bfd_section_vma (objfile->obfd, sect);
+                    lower_offset = addrs->other[i].addr;
+                    /* This is the index used by BFD. */
+                    addrs->other[i].sectindex = sect->index ;
+                  }
+                else
+                  {
+                    warning ("section %s not found in %s",
+                             addrs->other[i].name, 
+                             objfile->name);
+                    addrs->other[i].addr = 0;
+                  }
+              }
+            else
+              addrs->other[i].addr = lower_offset;
+          }
     }
 
   /* Initialize symbol reading routines for this objfile, allow complaints to
@@ -668,9 +706,23 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
      initial symbol reading for this file. */
 
   (*objfile->sf->sym_init) (objfile);
-  clear_complaints (1, verbo);
+  clear_complaints (&symfile_complaints, 1, verbo);
 
-  (*objfile->sf->sym_offsets) (objfile, addrs);
+  if (addrs)
+    (*objfile->sf->sym_offsets) (objfile, addrs);
+  else
+    {
+      size_t size = SIZEOF_N_SECTION_OFFSETS (num_offsets);
+
+      /* Just copy in the offset table directly as given to us.  */
+      objfile->num_sections = num_offsets;
+      objfile->section_offsets
+        = ((struct section_offsets *)
+           obstack_alloc (&objfile->psymbol_obstack, size));
+      memcpy (objfile->section_offsets, offsets, size);
+
+      init_objfile_sect_indices (objfile);
+    }
 
 #ifndef IBM6000_TARGET
   /* This is a SVR4/SunOS specific hack, I think.  In any event, it
@@ -708,7 +760,9 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
            for (i = 0; 
                 !s_addr && i < MAX_SECTIONS && addrs->other[i].name;
                 i++)
-             if (strcmp (s->the_bfd_section->name, addrs->other[i].name) == 0)
+             if (strcmp (bfd_section_name (s->objfile->obfd, 
+                                           s->the_bfd_section), 
+                         addrs->other[i].name) == 0)
                s_addr = addrs->other[i].addr; /* end added for gdb/13815 */
  
          s->addr -= s->offset;
@@ -722,13 +776,6 @@ syms_from_objfile (struct objfile *objfile, struct section_addr_info *addrs,
 
   (*objfile->sf->sym_read) (objfile, mainline);
 
-  if (!have_partial_symbols () && !have_full_symbols ())
-    {
-      wrap_here ("");
-      printf_filtered ("(no debugging symbols found)...");
-      wrap_here ("");
-    }
-
   /* Don't allow char * to have a typename (else would get caddr_t).
      Ditto void *.  FIXME: Check whether this is now done by all the
      symbol readers themselves (many of them now do), and if so remove
@@ -778,7 +825,7 @@ new_symfile_objfile (struct objfile *objfile, int mainline, int verbo)
     }
 
   /* We're done reading the symbol file; finish off complaints.  */
-  clear_complaints (0, verbo);
+  clear_complaints (&symfile_complaints, 0, verbo);
 }
 
 /* Process a symbol file, as either the main file or as a dynamically
@@ -786,21 +833,33 @@ new_symfile_objfile (struct objfile *objfile, int mainline, int verbo)
 
    NAME is the file name (which will be tilde-expanded and made
    absolute herein) (but we don't free or modify NAME itself).
-   FROM_TTY says how verbose to be.  MAINLINE specifies whether this
-   is the main symbol file, or whether it's an extra symbol file such
-   as dynamically loaded code.  If !mainline, ADDR is the address
-   where the text segment was loaded.
+
+   FROM_TTY says how verbose to be.
+
+   MAINLINE specifies whether this is the main symbol file, or whether
+   it's an extra symbol file such as dynamically loaded code.
+
+   ADDRS, OFFSETS, and NUM_OFFSETS are as described for
+   syms_from_objfile, above.  ADDRS is ignored when MAINLINE is
+   non-zero.
 
    Upon success, returns a pointer to the objfile that was added.
    Upon failure, jumps back to command level (never returns). */
-
-struct objfile *
-symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
-                int mainline, int flags)
+static struct objfile *
+symbol_file_add_with_addrs_or_offsets (char *name, int from_tty,
+                                       struct section_addr_info *addrs,
+                                       struct section_offsets *offsets,
+                                       int num_offsets,
+                                       int mainline, int flags)
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
+  char *debugfile;
   bfd *abfd;
+  struct section_addr_info orig_addrs;
+  
+  if (addrs)
+    orig_addrs = *addrs;
 
   /* Open a bfd for the file, and give user a chance to burp if we'd be
      interactively wiping out any existing symbols.  */
@@ -849,7 +908,8 @@ symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
              gdb_flush (gdb_stdout);
            }
        }
-      syms_from_objfile (objfile, addrs, mainline, from_tty);
+      syms_from_objfile (objfile, addrs, offsets, num_offsets,
+                         mainline, from_tty);
     }
 
   /* We now have at least a partial symbol table.  Check to see if the
@@ -874,6 +934,36 @@ symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
        }
     }
 
+  debugfile = find_separate_debug_file (objfile);
+  if (debugfile)
+    {
+      if (addrs != NULL)
+       {
+         objfile->separate_debug_objfile
+            = symbol_file_add (debugfile, from_tty, &orig_addrs, 0, flags);
+       }
+      else
+       {
+         objfile->separate_debug_objfile
+            = symbol_file_add (debugfile, from_tty, NULL, 0, flags);
+       }
+      objfile->separate_debug_objfile->separate_debug_objfile_backlink
+        = objfile;
+      
+      /* Put the separate debug object before the normal one, this is so that
+         usage of the ALL_OBJFILES_SAFE macro will stay safe. */
+      put_objfile_before (objfile->separate_debug_objfile, objfile);
+      
+      xfree (debugfile);
+    }
+  
+  if (!have_partial_symbols () && !have_full_symbols ())
+    {
+      wrap_here ("");
+      printf_filtered ("(no debugging symbols found)...");
+      wrap_here ("");
+    }
+
   if (from_tty || info_verbose)
     {
       if (post_add_symbol_hook)
@@ -881,10 +971,17 @@ symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
       else
        {
          printf_filtered ("done.\n");
-         gdb_flush (gdb_stdout);
        }
     }
 
+  /* We print some messages regardless of whether 'from_tty ||
+     info_verbose' is true, so make sure they go out at the right
+     time.  */
+  gdb_flush (gdb_stdout);
+
+  if (objfile->sf == NULL)
+    return objfile;    /* No symbols. */
+
   new_symfile_objfile (objfile, mainline, from_tty);
 
   if (target_new_objfile_hook)
@@ -893,6 +990,19 @@ symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
   return (objfile);
 }
 
+
+/* Process a symbol file, as either the main file or as a dynamically
+   loaded file.  See symbol_file_add_with_addrs_or_offsets's comments
+   for details.  */
+struct objfile *
+symbol_file_add (char *name, int from_tty, struct section_addr_info *addrs,
+                int mainline, int flags)
+{
+  return symbol_file_add_with_addrs_or_offsets (name, from_tty, addrs, 0, 0, 
+                                                mainline, flags);
+}
+
+
 /* Call symbol_file_add() with default values and update whatever is
    affected by the loading of a new main().
    Used when the file is supplied in the gdb command line
@@ -949,6 +1059,144 @@ symbol_file_clear (int from_tty)
 #endif
 }
 
+static char *
+get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
+{
+  asection *sect;
+  bfd_size_type debuglink_size;
+  unsigned long crc32;
+  char *contents;
+  int crc_offset;
+  unsigned char *p;
+  
+  sect = bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink");
+
+  if (sect == NULL)
+    return NULL;
+
+  debuglink_size = bfd_section_size (objfile->obfd, sect);
+  
+  contents = xmalloc (debuglink_size);
+  bfd_get_section_contents (objfile->obfd, sect, contents,
+                           (file_ptr)0, (bfd_size_type)debuglink_size);
+
+  /* Crc value is stored after the filename, aligned up to 4 bytes. */
+  crc_offset = strlen (contents) + 1;
+  crc_offset = (crc_offset + 3) & ~3;
+
+  crc32 = bfd_get_32 (objfile->obfd, (bfd_byte *) (contents + crc_offset));
+  
+  *crc32_out = crc32;
+  return contents;
+}
+
+static int
+separate_debug_file_exists (const char *name, unsigned long crc)
+{
+  unsigned long file_crc = 0;
+  int fd;
+  char buffer[8*1024];
+  int count;
+
+  fd = open (name, O_RDONLY | O_BINARY);
+  if (fd < 0)
+    return 0;
+
+  while ((count = read (fd, buffer, sizeof (buffer))) > 0)
+    file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
+
+  close (fd);
+
+  return crc == file_crc;
+}
+
+static char *debug_file_directory = NULL;
+
+#if ! defined (DEBUG_SUBDIRECTORY)
+#define DEBUG_SUBDIRECTORY ".debug"
+#endif
+
+static char *
+find_separate_debug_file (struct objfile *objfile)
+{
+  asection *sect;
+  char *basename;
+  char *dir;
+  char *debugfile;
+  char *name_copy;
+  bfd_size_type debuglink_size;
+  unsigned long crc32;
+  int i;
+
+  basename = get_debug_link_info (objfile, &crc32);
+
+  if (basename == NULL)
+    return NULL;
+  
+  dir = xstrdup (objfile->name);
+
+  /* Strip off the final filename part, leaving the directory name,
+     followed by a slash.  Objfile names should always be absolute and
+     tilde-expanded, so there should always be a slash in there
+     somewhere.  */
+  for (i = strlen(dir) - 1; i >= 0; i--)
+    {
+      if (IS_DIR_SEPARATOR (dir[i]))
+       break;
+    }
+  gdb_assert (i >= 0 && IS_DIR_SEPARATOR (dir[i]));
+  dir[i+1] = '\0';
+  
+  debugfile = alloca (strlen (debug_file_directory) + 1
+                      + strlen (dir)
+                      + strlen (DEBUG_SUBDIRECTORY)
+                      + strlen ("/")
+                      + strlen (basename) 
+                      + 1);
+
+  /* First try in the same directory as the original file.  */
+  strcpy (debugfile, dir);
+  strcat (debugfile, basename);
+
+  if (separate_debug_file_exists (debugfile, crc32))
+    {
+      xfree (basename);
+      xfree (dir);
+      return xstrdup (debugfile);
+    }
+  
+  /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
+  strcpy (debugfile, dir);
+  strcat (debugfile, DEBUG_SUBDIRECTORY);
+  strcat (debugfile, "/");
+  strcat (debugfile, basename);
+
+  if (separate_debug_file_exists (debugfile, crc32))
+    {
+      xfree (basename);
+      xfree (dir);
+      return xstrdup (debugfile);
+    }
+  
+  /* Then try in the global debugfile directory.  */
+  strcpy (debugfile, debug_file_directory);
+  strcat (debugfile, "/");
+  strcat (debugfile, dir);
+  strcat (debugfile, basename);
+
+  if (separate_debug_file_exists (debugfile, crc32))
+    {
+      xfree (basename);
+      xfree (dir);
+      return xstrdup (debugfile);
+    }
+  
+  xfree (basename);
+  xfree (dir);
+  return NULL;
+}
+
+
 /* This is the symbol-file command.  Read the file, analyze its
    symbols, and add a struct symtab to a symtab list.  The syntax of
    the command is rather bizarre--(1) buildargv implements various
@@ -1088,7 +1336,7 @@ symfile_bfd_open (char *name)
       error ("\"%s\": can't open to read symbols: %s.", name,
             bfd_errmsg (bfd_get_error ()));
     }
-  sym_bfd->cacheable = true;
+  sym_bfd->cacheable = 1;
 
   if (!bfd_check_format (sym_bfd, bfd_object))
     {
@@ -1103,6 +1351,18 @@ symfile_bfd_open (char *name)
   return (sym_bfd);
 }
 
+/* Return the section index for the given section name. Return -1 if
+   the section was not found. */
+int
+get_section_index (struct objfile *objfile, char *section_name)
+{
+  asection *sect = bfd_get_section_by_name (objfile->obfd, section_name);
+  if (sect)
+    return sect->index;
+  else
+    return -1;
+}
+
 /* Link a new symtab_fns into the global symtab_fns list.  Called on gdb
    startup by the _initialize routine in each object file format reader,
    to register information about each format the the reader is prepared
@@ -1128,6 +1388,11 @@ find_sym_fns (struct objfile *objfile)
   enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd);
   char *our_target = bfd_get_target (objfile->obfd);
 
+  if (our_flavour == bfd_target_srec_flavour
+      || our_flavour == bfd_target_ihex_flavour
+      || our_flavour == bfd_target_tekhex_flavour)
+    return;    /* No symbols. */
+
   /* Special kludge for apollo.  See dstread.c.  */
   if (STREQN (our_target, "apollo", 6))
     our_flavour = (enum bfd_flavour) -2;
@@ -1170,20 +1435,133 @@ load_command (char *arg, int from_tty)
 static int download_write_size = 512;
 static int validate_download = 0;
 
+/* Callback service function for generic_load (bfd_map_over_sections).  */
+
+static void
+add_section_size_callback (bfd *abfd, asection *asec, void *data)
+{
+  bfd_size_type *sum = data;
+
+  *sum += bfd_get_section_size_before_reloc (asec);
+}
+
+/* Opaque data for load_section_callback.  */
+struct load_section_data {
+  unsigned long load_offset;
+  unsigned long write_count;
+  unsigned long data_count;
+  bfd_size_type total_size;
+};
+
+/* Callback service function for generic_load (bfd_map_over_sections).  */
+
+static void
+load_section_callback (bfd *abfd, asection *asec, void *data)
+{
+  struct load_section_data *args = data;
+
+  if (bfd_get_section_flags (abfd, asec) & SEC_LOAD)
+    {
+      bfd_size_type size = bfd_get_section_size_before_reloc (asec);
+      if (size > 0)
+       {
+         char *buffer;
+         struct cleanup *old_chain;
+         CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset;
+         bfd_size_type block_size;
+         int err;
+         const char *sect_name = bfd_get_section_name (abfd, asec);
+         bfd_size_type sent;
+
+         if (download_write_size > 0 && size > download_write_size)
+           block_size = download_write_size;
+         else
+           block_size = size;
+
+         buffer = xmalloc (size);
+         old_chain = make_cleanup (xfree, buffer);
+
+         /* Is this really necessary?  I guess it gives the user something
+            to look at during a long download.  */
+         ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
+                         sect_name, paddr_nz (size), paddr_nz (lma));
+
+         bfd_get_section_contents (abfd, asec, buffer, 0, size);
+
+         sent = 0;
+         do
+           {
+             int len;
+             bfd_size_type this_transfer = size - sent;
+
+             if (this_transfer >= block_size)
+               this_transfer = block_size;
+             len = target_write_memory_partial (lma, buffer,
+                                                this_transfer, &err);
+             if (err)
+               break;
+             if (validate_download)
+               {
+                 /* Broken memories and broken monitors manifest
+                    themselves here when bring new computers to
+                    life.  This doubles already slow downloads.  */
+                 /* NOTE: cagney/1999-10-18: A more efficient
+                    implementation might add a verify_memory()
+                    method to the target vector and then use
+                    that.  remote.c could implement that method
+                    using the ``qCRC'' packet.  */
+                 char *check = xmalloc (len);
+                 struct cleanup *verify_cleanups = 
+                   make_cleanup (xfree, check);
+
+                 if (target_read_memory (lma, check, len) != 0)
+                   error ("Download verify read failed at 0x%s",
+                          paddr (lma));
+                 if (memcmp (buffer, check, len) != 0)
+                   error ("Download verify compare failed at 0x%s",
+                          paddr (lma));
+                 do_cleanups (verify_cleanups);
+               }
+             args->data_count += len;
+             lma += len;
+             buffer += len;
+             args->write_count += 1;
+             sent += len;
+             if (quit_flag
+                 || (ui_load_progress_hook != NULL
+                     && ui_load_progress_hook (sect_name, sent)))
+               error ("Canceled the download");
+
+             if (show_load_progress != NULL)
+               show_load_progress (sect_name, sent, size, 
+                                   args->data_count, args->total_size);
+           }
+         while (sent < size);
+
+         if (err != 0)
+           error ("Memory access error while loading section %s.", sect_name);
+
+         do_cleanups (old_chain);
+       }
+    }
+}
+
 void
 generic_load (char *args, int from_tty)
 {
   asection *s;
   bfd *loadfile_bfd;
   time_t start_time, end_time; /* Start and end times of download */
-  unsigned long data_count = 0;        /* Number of bytes transferred to memory */
-  unsigned long write_count = 0;       /* Number of writes needed. */
-  unsigned long load_offset;   /* offset to add to vma for each section */
   char *filename;
   struct cleanup *old_cleanups;
   char *offptr;
-  CORE_ADDR total_size = 0;
-  CORE_ADDR total_sent = 0;
+  struct load_section_data cbdata;
+  CORE_ADDR entry;
+
+  cbdata.load_offset = 0;      /* Offset to add to vma for each section. */
+  cbdata.write_count = 0;      /* Number of writes needed. */
+  cbdata.data_count = 0;       /* Number of bytes written to target memory. */
+  cbdata.total_size = 0;       /* Total size of all bfd sectors. */
 
   /* Parse the input argument - the user can specify a load offset as
      a second argument. */
@@ -1194,13 +1572,14 @@ generic_load (char *args, int from_tty)
   if (offptr != NULL)
     {
       char *endptr;
-      load_offset = strtoul (offptr, &endptr, 0);
+
+      cbdata.load_offset = strtoul (offptr, &endptr, 0);
       if (offptr == endptr)
        error ("Invalid download offset:%s\n", offptr);
       *offptr = '\0';
     }
   else
-    load_offset = 0;
+    cbdata.load_offset = 0;
 
   /* Open the file for loading. */
   loadfile_bfd = bfd_openr (filename, gnutarget);
@@ -1221,132 +1600,33 @@ generic_load (char *args, int from_tty)
             bfd_errmsg (bfd_get_error ()));
     }
 
-  for (s = loadfile_bfd->sections; s; s = s->next)
-    if (s->flags & SEC_LOAD)
-      total_size += bfd_get_section_size_before_reloc (s);
+  bfd_map_over_sections (loadfile_bfd, add_section_size_callback, 
+                        (void *) &cbdata.total_size);
 
   start_time = time (NULL);
 
-  for (s = loadfile_bfd->sections; s; s = s->next)
-    {
-      if (s->flags & SEC_LOAD)
-       {
-         CORE_ADDR size = bfd_get_section_size_before_reloc (s);
-         if (size > 0)
-           {
-             char *buffer;
-             struct cleanup *old_chain;
-             CORE_ADDR lma = s->lma + load_offset;
-             CORE_ADDR block_size;
-             int err;
-             const char *sect_name = bfd_get_section_name (loadfile_bfd, s);
-             CORE_ADDR sent;
-
-             if (download_write_size > 0 && size > download_write_size)
-               block_size = download_write_size;
-             else
-               block_size = size;
-
-             buffer = xmalloc (size);
-             old_chain = make_cleanup (xfree, buffer);
-
-             /* Is this really necessary?  I guess it gives the user something
-                to look at during a long download.  */
-#ifdef UI_OUT
-             ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
-                          sect_name, paddr_nz (size), paddr_nz (lma));
-#else
-             fprintf_unfiltered (gdb_stdout,
-                                 "Loading section %s, size 0x%s lma 0x%s\n",
-                                 sect_name, paddr_nz (size), paddr_nz (lma));
-#endif
-
-             bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
-
-             sent = 0;
-             do
-               {
-                 CORE_ADDR len;
-                 CORE_ADDR this_transfer = size - sent;
-                 if (this_transfer >= block_size)
-                   this_transfer = block_size;
-                 len = target_write_memory_partial (lma, buffer,
-                                                    this_transfer, &err);
-                 if (err)
-                   break;
-                 if (validate_download)
-                   {
-                     /* Broken memories and broken monitors manifest
-                        themselves here when bring new computers to
-                        life.  This doubles already slow downloads.  */
-                     /* NOTE: cagney/1999-10-18: A more efficient
-                         implementation might add a verify_memory()
-                         method to the target vector and then use
-                         that.  remote.c could implement that method
-                         using the ``qCRC'' packet.  */
-                     char *check = xmalloc (len);
-                     struct cleanup *verify_cleanups = make_cleanup (xfree, check);
-                     if (target_read_memory (lma, check, len) != 0)
-                       error ("Download verify read failed at 0x%s",
-                              paddr (lma));
-                     if (memcmp (buffer, check, len) != 0)
-                       error ("Download verify compare failed at 0x%s",
-                              paddr (lma));
-                     do_cleanups (verify_cleanups);
-                   }
-                 data_count += len;
-                 lma += len;
-                 buffer += len;
-                 write_count += 1;
-                 sent += len;
-                 total_sent += len;
-                 if (quit_flag
-                     || (ui_load_progress_hook != NULL
-                         && ui_load_progress_hook (sect_name, sent)))
-                   error ("Canceled the download");
-
-                 if (show_load_progress != NULL)
-                   show_load_progress (sect_name, sent, size, total_sent, total_size);
-               }
-             while (sent < size);
-
-             if (err != 0)
-               error ("Memory access error while loading section %s.", sect_name);
-
-             do_cleanups (old_chain);
-           }
-       }
-    }
+  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
 
   end_time = time (NULL);
-  {
-    CORE_ADDR entry;
-    entry = bfd_get_start_address (loadfile_bfd);
-#ifdef UI_OUT
-   ui_out_text (uiout, "Start address ");
-   ui_out_field_fmt (uiout, "address", "0x%s" , paddr_nz (entry));
-   ui_out_text (uiout, ", load size ");
-   ui_out_field_fmt (uiout, "load-size", "%ld" , data_count);
-   ui_out_text (uiout, "\n");
 
-#else
-    fprintf_unfiltered (gdb_stdout,
-                       "Start address 0x%s , load size %ld\n",
-                       paddr_nz (entry), data_count);
-#endif
-    /* We were doing this in remote-mips.c, I suspect it is right
-       for other targets too.  */
-    write_pc (entry);
-  }
-
-  /* FIXME: are we supposed to call symbol_file_add or not?  According to
-     a comment from remote-mips.c (where a call to symbol_file_add was
-     commented out), making the call confuses GDB if more than one file is
-     loaded in.  remote-nindy.c had no call to symbol_file_add, but remote-vx.c
-     does.  */
-
-  print_transfer_performance (gdb_stdout, data_count, write_count,
-                             end_time - start_time);
+  entry = bfd_get_start_address (loadfile_bfd);
+  ui_out_text (uiout, "Start address ");
+  ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
+  ui_out_text (uiout, ", load size ");
+  ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
+  ui_out_text (uiout, "\n");
+  /* We were doing this in remote-mips.c, I suspect it is right
+     for other targets too.  */
+  write_pc (entry);
+
+  /* FIXME: are we supposed to call symbol_file_add or not?  According
+     to a comment from remote-mips.c (where a call to symbol_file_add
+     was commented out), making the call confuses GDB if more than one
+     file is loaded in.  Some targets do (e.g., remote-vx.c) but
+     others don't (or didn't - perhaphs they have all been deleted).  */
+
+  print_transfer_performance (gdb_stdout, cbdata.data_count, 
+                             cbdata.write_count, end_time - start_time);
 
   do_cleanups (old_cleanups);
 }
@@ -1361,7 +1641,8 @@ void
 report_transfer_performance (unsigned long data_count, time_t start_time,
                             time_t end_time)
 {
-  print_transfer_performance (gdb_stdout, data_count, end_time - start_time, 0);
+  print_transfer_performance (gdb_stdout, data_count, 
+                             end_time - start_time, 0);
 }
 
 void
@@ -1370,36 +1651,25 @@ print_transfer_performance (struct ui_file *stream,
                            unsigned long write_count,
                            unsigned long time_count)
 {
-#ifdef UI_OUT
   ui_out_text (uiout, "Transfer rate: ");
   if (time_count > 0)
     {
-      ui_out_field_fmt (uiout, "transfer-rate", "%ld", 
+      ui_out_field_fmt (uiout, "transfer-rate", "%lu", 
                        (data_count * 8) / time_count);
       ui_out_text (uiout, " bits/sec");
     }
   else
     {
-      ui_out_field_fmt (uiout, "transferred-bits", "%ld", (data_count * 8));
+      ui_out_field_fmt (uiout, "transferred-bits", "%lu", (data_count * 8));
       ui_out_text (uiout, " bits in <1 sec");    
     }
   if (write_count > 0)
     {
       ui_out_text (uiout, ", ");
-      ui_out_field_fmt (uiout, "write-rate", "%ld", data_count / write_count);
+      ui_out_field_fmt (uiout, "write-rate", "%lu", data_count / write_count);
       ui_out_text (uiout, " bytes/write");
     }
   ui_out_text (uiout, ".\n");
-#else
-  fprintf_unfiltered (stream, "Transfer rate: ");
-  if (time_count > 0)
-    fprintf_unfiltered (stream, "%ld bits/sec", (data_count * 8) / time_count);
-  else
-    fprintf_unfiltered (stream, "%ld bits in <1 sec", (data_count * 8));
-  if (write_count > 0)
-    fprintf_unfiltered (stream, ", %ld bytes/write", data_count / write_count);
-  fprintf_unfiltered (stream, ".\n");
-#endif
 }
 
 /* This function allows the addition of incrementally linked object files.
@@ -1667,16 +1937,24 @@ reread_symbols (void)
              /* FIXME: Do we have to free a whole linked list, or is this
                 enough?  */
              if (objfile->global_psymbols.list)
-               mfree (objfile->md, objfile->global_psymbols.list);
+               xmfree (objfile->md, objfile->global_psymbols.list);
              memset (&objfile->global_psymbols, 0,
                      sizeof (objfile->global_psymbols));
              if (objfile->static_psymbols.list)
-               mfree (objfile->md, objfile->static_psymbols.list);
+               xmfree (objfile->md, objfile->static_psymbols.list);
              memset (&objfile->static_psymbols, 0,
                      sizeof (objfile->static_psymbols));
 
              /* Free the obstacks for non-reusable objfiles */
-             free_bcache (&objfile->psymbol_cache);
+             bcache_xfree (objfile->psymbol_cache);
+             objfile->psymbol_cache = bcache_xmalloc ();
+             bcache_xfree (objfile->macro_cache);
+             objfile->macro_cache = bcache_xmalloc ();
+             if (objfile->demangled_names_hash != NULL)
+               {
+                 htab_delete (objfile->demangled_names_hash);
+                 objfile->demangled_names_hash = NULL;
+               }
              obstack_free (&objfile->psymbol_obstack, 0);
              obstack_free (&objfile->symbol_obstack, 0);
              obstack_free (&objfile->type_obstack, 0);
@@ -1700,8 +1978,8 @@ reread_symbols (void)
              objfile->md = NULL;
              /* obstack_specify_allocation also initializes the obstack so
                 it is empty.  */
-             obstack_specify_allocation (&objfile->psymbol_cache.cache, 0, 0,
-                                         xmalloc, xfree);
+             objfile->psymbol_cache = bcache_xmalloc ();
+             objfile->macro_cache = bcache_xmalloc ();
              obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0,
                                          xmalloc, xfree);
              obstack_specify_allocation (&objfile->symbol_obstack, 0, 0,
@@ -1713,6 +1991,7 @@ reread_symbols (void)
                  error ("Can't find the file sections in `%s': %s",
                         objfile->name, bfd_errmsg (bfd_get_error ()));
                }
+              terminate_minimal_symbol_table (objfile);
 
              /* We use the same section offsets as from last time.  I'm not
                 sure whether that is always correct for shared libraries.  */
@@ -1733,7 +2012,7 @@ reread_symbols (void)
                }
 
              (*objfile->sf->sym_init) (objfile);
-             clear_complaints (1, 1);
+             clear_complaints (&symfile_complaints, 1, 1);
              /* The "mainline" parameter is a hideous hack; I think leaving it
                 zero is OK since dbxread.c also does what it needs to do if
                 objfile->global_psymbols.size is 0.  */
@@ -1747,7 +2026,7 @@ reread_symbols (void)
              objfile->flags |= OBJF_SYMS;
 
              /* We're done reading the symbol file; finish off complaints.  */
-             clear_complaints (0, 1);
+             clear_complaints (&symfile_complaints, 0, 1);
 
              /* Getting new symbols may change our opinion about what is
                 frameless.  */
@@ -1769,6 +2048,8 @@ reread_symbols (void)
                 needs to keep track of (such as _sigtramp, or whatever).  */
 
              TARGET_SYMFILE_POSTREAD (objfile);
+
+              reread_separate_symbols (objfile);
            }
        }
     }
@@ -1776,6 +2057,73 @@ reread_symbols (void)
   if (reread_one)
     clear_symtab_users ();
 }
+
+
+/* Handle separate debug info for OBJFILE, which has just been
+   re-read:
+   - If we had separate debug info before, but now we don't, get rid
+     of the separated objfile.
+   - If we didn't have separated debug info before, but now we do,
+     read in the new separated debug info file.
+   - If the debug link points to a different file, toss the old one
+     and read the new one.
+   This function does *not* handle the case where objfile is still
+   using the same separate debug info file, but that file's timestamp
+   has changed.  That case should be handled by the loop in
+   reread_symbols already.  */
+static void
+reread_separate_symbols (struct objfile *objfile)
+{
+  char *debug_file;
+  unsigned long crc32;
+
+  /* Does the updated objfile's debug info live in a
+     separate file?  */
+  debug_file = find_separate_debug_file (objfile);
+
+  if (objfile->separate_debug_objfile)
+    {
+      /* There are two cases where we need to get rid of
+         the old separated debug info objfile:
+         - if the new primary objfile doesn't have
+         separated debug info, or
+         - if the new primary objfile has separate debug
+         info, but it's under a different filename.
+         If the old and new objfiles both have separate
+         debug info, under the same filename, then we're
+         okay --- if the separated file's contents have
+         changed, we will have caught that when we
+         visited it in this function's outermost
+         loop.  */
+      if (! debug_file
+          || strcmp (debug_file, objfile->separate_debug_objfile->name) != 0)
+        free_objfile (objfile->separate_debug_objfile);
+    }
+
+  /* If the new objfile has separate debug info, and we
+     haven't loaded it already, do so now.  */
+  if (debug_file
+      && ! objfile->separate_debug_objfile)
+    {
+      /* Use the same section offset table as objfile itself.
+         Preserve the flags from objfile that make sense.  */
+      objfile->separate_debug_objfile
+        = (symbol_file_add_with_addrs_or_offsets
+           (debug_file,
+            info_verbose, /* from_tty: Don't override the default. */
+            0, /* No addr table.  */
+            objfile->section_offsets, objfile->num_sections,
+            0, /* Not mainline.  See comments about this above.  */
+            objfile->flags & (OBJF_MAPPED | OBJF_REORDERED
+                              | OBJF_SHARED | OBJF_READNOW
+                              | OBJF_USERLOADED)));
+      objfile->separate_debug_objfile->separate_debug_objfile_backlink
+        = objfile;
+    }
+}
+
+
 \f
 
 
@@ -1795,8 +2143,9 @@ add_filename_language (char *ext, enum language lang)
   if (fl_table_next >= fl_table_size)
     {
       fl_table_size += 10;
-      filename_language_table = xrealloc (filename_language_table,
-                                         fl_table_size);
+      filename_language_table = 
+       xrealloc (filename_language_table,
+                 fl_table_size * sizeof (*filename_language_table));
     }
 
   filename_language_table[fl_table_next].ext = xstrdup (ext);
@@ -1894,9 +2243,7 @@ init_filename_language_table (void)
       add_filename_language (".c++", language_cplus);
       add_filename_language (".java", language_java);
       add_filename_language (".class", language_java);
-      add_filename_language (".ch", language_chill);
-      add_filename_language (".c186", language_chill);
-      add_filename_language (".c286", language_chill);
+      add_filename_language (".m", language_objc);
       add_filename_language (".f", language_fortran);
       add_filename_language (".F", language_fortran);
       add_filename_language (".s", language_asm);
@@ -2049,8 +2396,7 @@ clear_symtab_users (void)
   clear_internalvars ();
   breakpoint_re_set ();
   set_default_breakpoint (0, 0, 0, 0);
-  current_source_symtab = 0;
-  current_source_line = 0;
+  clear_current_source_symtab_and_line ();
   clear_pc_function_cache ();
   if (target_new_objfile_hook)
     target_new_objfile_hook (NULL);
@@ -2236,15 +2582,16 @@ again2:
          || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
          || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)))
        {
-         complain (&oldsyms_complaint, name);
-
+         complaint (&symfile_complaints, "Replacing old symbols for `%s'",
+                    name);
          clear_symtab_users_queued++;
          make_cleanup (clear_symtab_users_once, 0);
          blewit = 1;
        }
       else
        {
-         complain (&empty_symtab_complaint, name);
+         complaint (&symfile_complaints, "Empty symbol table found for `%s'",
+                    name);
        }
 
       free_symtab (s);
@@ -2309,7 +2656,6 @@ add_psymbol_to_list (char *name, int namelength, namespace_enum namespace,
   /* Create local copy of the partial symbol */
   memcpy (buf, name, namelength);
   buf[namelength] = '\0';
-  SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
   /* val and coreaddr are mutually exclusive, one of them *will* be zero */
   if (val != 0)
     {
@@ -2323,10 +2669,11 @@ add_psymbol_to_list (char *name, int namelength, namespace_enum namespace,
   SYMBOL_LANGUAGE (&psymbol) = language;
   PSYMBOL_NAMESPACE (&psymbol) = namespace;
   PSYMBOL_CLASS (&psymbol) = class;
-  SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+  SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
 
   /* Stash the partial symbol away in the cache */
-  psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+  psym = bcache (&psymbol, sizeof (struct partial_symbol), objfile->psymbol_cache);
 
   /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
   if (list->next >= list->list + list->size)
@@ -2361,7 +2708,7 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name,
 
   memcpy (buf, name, namelength);
   buf[namelength] = '\0';
-  SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+  DEPRECATED_SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, objfile->psymbol_cache);
 
   buf = alloca (dem_namelength + 1);
   memcpy (buf, dem_name, dem_namelength);
@@ -2372,12 +2719,8 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name,
     case language_c:
     case language_cplus:
       SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) =
-       bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
+       bcache (buf, dem_namelength + 1, objfile->psymbol_cache);
       break;
-    case language_chill:
-      SYMBOL_CHILL_DEMANGLED_NAME (&psymbol) =
-       bcache (buf, dem_namelength + 1, &objfile->psymbol_cache);
-
       /* FIXME What should be done for the default case? Ignoring for now. */
     }
 
@@ -2397,7 +2740,7 @@ add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name,
   SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
 
   /* Stash the partial symbol away in the cache */
-  psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+  psym = bcache (&psymbol, sizeof (struct partial_symbol), objfile->psymbol_cache);
 
   /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
   if (list->next >= list->list + list->size)
@@ -2417,11 +2760,11 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
 
   if (objfile->global_psymbols.list)
     {
-      mfree (objfile->md, (PTR) objfile->global_psymbols.list);
+      xmfree (objfile->md, objfile->global_psymbols.list);
     }
   if (objfile->static_psymbols.list)
     {
-      mfree (objfile->md, (PTR) objfile->static_psymbols.list);
+      xmfree (objfile->md, objfile->static_psymbols.list);
     }
 
   /* Current best guess is that approximately a twentieth
@@ -2498,7 +2841,7 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
 
 /* Overlay debugging state: */
 
-int overlay_debugging = 0;     /* 0 == off, 1 == manual, -1 == auto */
+enum overlay_debugging_state overlay_debugging = ovly_off;
 int overlay_cache_invalid = 0; /* True if need to refresh mapped state */
 
 /* Target vector for refreshing overlay mapped state */
@@ -2512,6 +2855,8 @@ void (*target_overlay_update) (struct obj_section *) = simple_overlay_update;
 int
 section_is_overlay (asection *section)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
+
   if (overlay_debugging)
     if (section && section->lma != 0 &&
        section->vma != section->lma)
@@ -2553,9 +2898,9 @@ overlay_is_mapped (struct obj_section *osect)
   switch (overlay_debugging)
     {
     default:
-    case 0:
+    case ovly_off:
       return 0;                        /* overlay debugging off */
-    case -1:                   /* overlay debugging automatic */
+    case ovly_auto:            /* overlay debugging automatic */
       /* Unles there is a target_overlay_update function, 
          there's really nothing useful to do here (can't really go auto)  */
       if (target_overlay_update)
@@ -2569,7 +2914,7 @@ overlay_is_mapped (struct obj_section *osect)
            (*target_overlay_update) (osect);
        }
       /* fall thru to manual case */
-    case 1:                    /* overlay debugging manual */
+    case ovly_on:              /* overlay debugging manual */
       return osect->ovly_mapped == 1;
     }
 }
@@ -2598,6 +2943,8 @@ section_is_mapped (asection *section)
 CORE_ADDR
 pc_in_unmapped_range (CORE_ADDR pc, asection *section)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
+
   int size;
 
   if (overlay_debugging)
@@ -2616,6 +2963,8 @@ pc_in_unmapped_range (CORE_ADDR pc, asection *section)
 CORE_ADDR
 pc_in_mapped_range (CORE_ADDR pc, asection *section)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
+
   int size;
 
   if (overlay_debugging)
@@ -2634,6 +2983,8 @@ pc_in_mapped_range (CORE_ADDR pc, asection *section)
 int
 sections_overlap (asection *a, asection *b)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
+
   CORE_ADDR a_start = a->vma;
   CORE_ADDR a_end = a->vma + bfd_get_section_size_before_reloc (a);
   CORE_ADDR b_start = b->vma;
@@ -2649,6 +3000,8 @@ sections_overlap (asection *a, asection *b)
 CORE_ADDR
 overlay_unmapped_address (CORE_ADDR pc, asection *section)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
+
   if (overlay_debugging)
     if (section && section_is_overlay (section) &&
        pc_in_mapped_range (pc, section))
@@ -2664,6 +3017,8 @@ overlay_unmapped_address (CORE_ADDR pc, asection *section)
 CORE_ADDR
 overlay_mapped_address (CORE_ADDR pc, asection *section)
 {
+  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
+
   if (overlay_debugging)
     if (section && section_is_overlay (section) &&
        pc_in_unmapped_range (pc, section))
@@ -2874,7 +3229,8 @@ the 'overlay manual' command.");
 static void
 overlay_auto_command (char *args, int from_tty)
 {
-  overlay_debugging = -1;
+  overlay_debugging = ovly_auto;
+  enable_overlay_breakpoints ();
   if (info_verbose)
     printf_filtered ("Automatic overlay debugging enabled.");
 }
@@ -2886,7 +3242,8 @@ overlay_auto_command (char *args, int from_tty)
 static void
 overlay_manual_command (char *args, int from_tty)
 {
-  overlay_debugging = 1;
+  overlay_debugging = ovly_on;
+  disable_overlay_breakpoints ();
   if (info_verbose)
     printf_filtered ("Overlay debugging enabled.");
 }
@@ -2898,7 +3255,8 @@ overlay_manual_command (char *args, int from_tty)
 static void
 overlay_off_command (char *args, int from_tty)
 {
-  overlay_debugging = 0;
+  overlay_debugging = ovly_off;
+  disable_overlay_breakpoints ();
   if (info_verbose)
     printf_filtered ("Overlay debugging disabled.");
 }
@@ -3009,6 +3367,7 @@ simple_free_overlay_region_table (void)
 static void
 read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len)
 {
+  /* FIXME (alloca): Not safe if array is very large. */
   char *buf = alloca (len * TARGET_LONG_BYTES);
   int i;
 
@@ -3026,7 +3385,7 @@ simple_read_overlay_table (void)
   struct minimal_symbol *novlys_msym, *ovly_table_msym;
 
   simple_free_overlay_table ();
-  novlys_msym = lookup_minimal_symbol ("_novlys", 0, 0);
+  novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL);
   if (! novlys_msym)
     {
       error ("Error reading inferior's overlay table: "
@@ -3035,7 +3394,7 @@ simple_read_overlay_table (void)
       return 0;
     }
 
-  ovly_table_msym = lookup_minimal_symbol ("_ovly_table", 0, 0);
+  ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, NULL);
   if (! ovly_table_msym)
     {
       error ("Error reading inferior's overlay table: couldn't find "
@@ -3064,7 +3423,7 @@ simple_read_overlay_region_table (void)
   struct minimal_symbol *msym;
 
   simple_free_overlay_region_table ();
-  msym = lookup_minimal_symbol ("_novly_regions", 0, 0);
+  msym = lookup_minimal_symbol ("_novly_regions", NULL, NULL);
   if (msym != NULL)
     cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), 4);
   else
@@ -3072,7 +3431,7 @@ simple_read_overlay_region_table (void)
   cache_ovly_region_table = (void *) xmalloc (cache_novly_regions * 12);
   if (cache_ovly_region_table != NULL)
     {
-      msym = lookup_minimal_symbol ("_ovly_region_table", 0, 0);
+      msym = lookup_minimal_symbol ("_ovly_region_table", NULL, NULL);
       if (msym != NULL)
        {
          cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym);
@@ -3101,23 +3460,25 @@ static int
 simple_overlay_update_1 (struct obj_section *osect)
 {
   int i, size;
+  bfd *obfd = osect->objfile->obfd;
+  asection *bsect = osect->the_bfd_section;
 
   size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
   for (i = 0; i < cache_novlys; i++)
-    if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
-       cache_ovly_table[i][LMA] == osect->the_bfd_section->lma         /* &&
-                                                                          cache_ovly_table[i][SIZE] == size */ )
+    if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
+       && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
+       /* && cache_ovly_table[i][SIZE] == size */ )
       {
        read_target_long_array (cache_ovly_table_base + i * TARGET_LONG_BYTES,
                                (int *) cache_ovly_table[i], 4);
-       if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
-           cache_ovly_table[i][LMA] == osect->the_bfd_section->lma     /* &&
-                                                                          cache_ovly_table[i][SIZE] == size */ )
+       if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
+           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
+           /* && cache_ovly_table[i][SIZE] == size */ )
          {
            osect->ovly_mapped = cache_ovly_table[i][MAPPED];
            return 1;
          }
-       else                    /* Warning!  Warning!  Target's ovly table has changed! */
+       else    /* Warning!  Warning!  Target's ovly table has changed! */
          return 0;
       }
   return 0;
@@ -3142,7 +3503,7 @@ simple_overlay_update (struct obj_section *osect)
     if (cache_ovly_table != NULL)
       /* Does its cached location match what's currently in the symtab? */
       if (cache_ovly_table_base ==
-         SYMBOL_VALUE_ADDRESS (lookup_minimal_symbol ("_ovly_table", 0, 0)))
+         SYMBOL_VALUE_ADDRESS (lookup_minimal_symbol ("_ovly_table", NULL, NULL)))
        /* Then go ahead and try to look up this single section in the cache */
        if (simple_overlay_update_1 (osect))
          /* Found it!  We're done. */
@@ -3160,19 +3521,60 @@ simple_overlay_update (struct obj_section *osect)
     if (section_is_overlay (osect->the_bfd_section))
     {
       int i, size;
+      bfd *obfd = osect->objfile->obfd;
+      asection *bsect = osect->the_bfd_section;
 
       size = bfd_get_section_size_before_reloc (osect->the_bfd_section);
       for (i = 0; i < cache_novlys; i++)
-       if (cache_ovly_table[i][VMA] == osect->the_bfd_section->vma &&
-           cache_ovly_table[i][LMA] == osect->the_bfd_section->lma     /* &&
-                                                                          cache_ovly_table[i][SIZE] == size */ )
-         {                     /* obj_section matches i'th entry in ovly_table */
+       if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
+           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
+           /* && cache_ovly_table[i][SIZE] == size */ )
+         { /* obj_section matches i'th entry in ovly_table */
            osect->ovly_mapped = cache_ovly_table[i][MAPPED];
            break;              /* finished with inner for loop: break out */
          }
     }
 }
 
+/* Set the output sections and output offsets for section SECTP in
+   ABFD.  The relocation code in BFD will read these offsets, so we
+   need to be sure they're initialized.  We map each section to itself,
+   with no offset; this means that SECTP->vma will be honored.  */
+
+static void
+symfile_dummy_outputs (bfd *abfd, asection *sectp, void *dummy)
+{
+  sectp->output_section = sectp;
+  sectp->output_offset = 0;
+}
+
+/* Relocate the contents of a debug section SECTP in ABFD.  The
+   contents are stored in BUF if it is non-NULL, or returned in a
+   malloc'd buffer otherwise.
+
+   For some platforms and debug info formats, shared libraries contain
+   relocations against the debug sections (particularly for DWARF-2;
+   one affected platform is PowerPC GNU/Linux, although it depends on
+   the version of the linker in use).  Also, ELF object files naturally
+   have unresolved relocations for their debug sections.  We need to apply
+   the relocations in order to get the locations of symbols correct.  */
+
+bfd_byte *
+symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
+{
+  /* We're only interested in debugging sections with relocation
+     information.  */
+  if ((sectp->flags & SEC_RELOC) == 0)
+    return NULL;
+  if ((sectp->flags & SEC_DEBUGGING) == 0)
+    return NULL;
+
+  /* We will handle section offsets properly elsewhere, so relocate as if
+     all sections begin at 0.  */
+  bfd_map_over_sections (abfd, symfile_dummy_outputs, NULL);
+
+  return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL);
+}
 
 void
 _initialize_symfile (void)
@@ -3183,7 +3585,7 @@ _initialize_symfile (void)
               "Load symbol table from executable file FILE.\n\
 The `file' command can also load symbol tables, as well as setting the file\n\
 to execute.", &cmdlist);
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
 
   c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command,
               "Usage: add-symbol-file FILE ADDR [-s <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR> ...]\n\
@@ -3191,9 +3593,9 @@ Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\
 ADDR is the starting address of the file's text.\n\
 The optional arguments are section-name section-address pairs and\n\
 should be specified if the data and bss segments are not contiguous\n\
-with the text. SECT is a section name to be loaded at SECT_ADDR.",
+with the text.  SECT is a section name to be loaded at SECT_ADDR.",
               &cmdlist);
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
 
   c = add_cmd ("add-shared-symbol-files", class_files,
               add_shared_symbol_files_command,
@@ -3205,7 +3607,7 @@ with the text. SECT is a section name to be loaded at SECT_ADDR.",
   c = add_cmd ("load", class_files, load_command,
               "Dynamically load FILE into the running program, and record its symbols\n\
 for access from GDB.", &cmdlist);
-  c->completer = filename_completer;
+  set_cmd_completer (c, filename_completer);
 
   add_show_from_set
     (add_set_cmd ("symbol-reloading", class_support, var_boolean,
@@ -3246,7 +3648,7 @@ for access from GDB.", &cmdlist);
                   "Set mapping between filename extension and source language.\n\
 Usage: set extension-language .foo bar",
                   &setlist);
-  c->function.cfunc = set_ext_lang_command;
+  set_cmd_cfunc (c, set_ext_lang_command);
 
   add_info ("extensions", info_ext_lang_command,
            "All filename extensions associated with a source language.");
@@ -3262,4 +3664,18 @@ Usage: set extension-language .foo bar",
                  "cache.\n",
                  &setlist),
      &showlist);
+
+  debug_file_directory = xstrdup (DEBUGDIR);
+  c = (add_set_cmd
+       ("debug-file-directory", class_support, var_string,
+        (char *) &debug_file_directory,
+        "Set the directory where separate debug symbols are searched for.\n"
+        "Separate debug symbols are first searched for in the same\n"
+        "directory as the binary, then in the `" DEBUG_SUBDIRECTORY 
+        "' subdirectory,\n"
+        "and lastly at the path of the directory of the binary with\n"
+        "the global debug-file directory prepended\n",
+        &setlist));
+  add_show_from_set (c, &showlist);
+  set_cmd_completer (c, filename_completer);
 }
This page took 0.043563 seconds and 4 git commands to generate.