OSDN Git Service

Merge branch 'master' of git://github.com/monaka/binutils
[pf3gnuchains/pf3gnuchains3x.git] / gdb / symfile.c
index 5151966..cee84db 100644 (file)
@@ -1,7 +1,7 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
@@ -97,8 +97,6 @@ static void symbol_file_add_main_1 (char *args, int from_tty, int flags);
 
 static void add_symbol_file_command (char *, int);
 
-static void reread_separate_symbols (struct objfile *objfile);
-
 static void cashier_psymtab (struct partial_symtab *);
 
 bfd *symfile_bfd_open (char *);
@@ -140,8 +138,6 @@ static void add_filename_language (char *ext, enum language lang);
 
 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);
 
 static void symfile_find_segment_sections (struct objfile *objfile);
@@ -171,13 +167,6 @@ Dynamic symbol table reloading multiple times in one run is %s.\n"),
                    value);
 }
 
-/* If non-zero, gdb will notify the user when it is loading symbols
-   from a file.  This is almost always what users will want to have happen;
-   but for programs with lots of dynamically linked libraries, the output
-   can be more noise than signal.  */
-
-int print_symbol_loading = 1;
-
 /* If non-zero, shared library symbols will be added automatically
    when the inferior is created, new libraries are loaded, or when
    attaching to the inferior.  This is almost always what users will
@@ -395,6 +384,29 @@ build_section_addr_info_from_section_table (const struct target_section *start,
   return sap;
 }
 
+/* Create a section_addr_info from section offsets in OBJFILE.  */
+
+static struct section_addr_info *
+build_section_addr_info_from_objfile (const struct objfile *objfile)
+{
+  struct section_addr_info *sap;
+  int i;
+  struct bfd_section *sec;
+
+  sap = alloc_section_addr_info (objfile->num_sections);
+  for (i = 0, sec = objfile->obfd->sections;
+       i < objfile->num_sections;
+       i++, sec = sec->next)
+    {
+      gdb_assert (sec != NULL);
+      sap->other[i].addr = (bfd_get_section_vma (objfile->obfd, sec)
+                            + objfile->section_offsets->offsets[i]);
+      sap->other[i].name = xstrdup (bfd_get_section_name (objfile->obfd, sec));
+      sap->other[i].sectindex = sec->index;
+    }
+  return sap;
+}
+
 
 /* Free all memory allocated by build_section_addr_info_from_section_table. */
 
@@ -793,7 +805,7 @@ syms_from_objfile (struct objfile *objfile,
       if (symfile_objfile != NULL)
        {
          free_objfile (symfile_objfile);
-         symfile_objfile = NULL;
+         gdb_assert (symfile_objfile == NULL);
        }
 
       /* Currently we keep symbols from the add-symbol-file command.
@@ -810,7 +822,7 @@ syms_from_objfile (struct objfile *objfile,
 
      We no longer warn if the lowest section is not a text segment (as
      happens for the PA64 port.  */
-  if (!mainline && addrs && addrs->other[0].name)
+  if (addrs && addrs->other[0].name)
     {
       asection *lower_sect;
       asection *sect;
@@ -893,7 +905,7 @@ syms_from_objfile (struct objfile *objfile,
       init_objfile_sect_indices (objfile);
     }
 
-  (*objfile->sf->sym_read) (objfile, mainline);
+  (*objfile->sf->sym_read) (objfile, add_flags);
 
   /* Discard cleanups as symbol reading was successful.  */
 
@@ -954,8 +966,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
-  char *debugfile = NULL;
-  struct section_addr_info *orig_addrs = NULL;
   struct cleanup *my_cleanups;
   const char *name = bfd_get_filename (abfd);
   const int from_tty = add_flags & SYMFILE_VERBOSE;
@@ -974,12 +984,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
   objfile = allocate_objfile (abfd, flags);
   discard_cleanups (my_cleanups);
 
-  if (addrs)
-    {
-      orig_addrs = copy_section_addr_info (addrs);
-      make_cleanup_free_section_addr_info (orig_addrs);
-    }
-
   /* We either created a new mapped symbol table, mapped an existing
      symbol table file which has not had initial symbol reading
      performed, or need to read an unmapped symbol table. */
@@ -989,12 +993,9 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
        deprecated_pre_add_symbol_hook (name);
       else
        {
-          if (print_symbol_loading)
-           {
-             printf_unfiltered (_("Reading symbols from %s..."), name);
-             wrap_here ("");
-             gdb_flush (gdb_stdout);
-           }
+         printf_unfiltered (_("Reading symbols from %s..."), name);
+         wrap_here ("");
+         gdb_flush (gdb_stdout);
        }
     }
   syms_from_objfile (objfile, addrs, offsets, num_offsets,
@@ -1007,7 +1008,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 
   if ((flags & OBJF_READNOW) || readnow_symbol_files)
     {
-      if ((from_tty || info_verbose) && print_symbol_loading)
+      if (from_tty || info_verbose)
        {
          printf_unfiltered (_("expanding to full symbols..."));
          wrap_here ("");
@@ -1022,42 +1023,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
        }
     }
 
-  /* If the file has its own symbol tables it has no separate debug info.
-     `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
-     `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'.  */
-  if (objfile->psymtabs == NULL)
-    debugfile = find_separate_debug_file (objfile);
-  if (debugfile)
-    {
-      if (addrs != NULL)
-       {
-         objfile->separate_debug_objfile
-            = symbol_file_add (debugfile, add_flags, orig_addrs, flags);
-       }
-      else
-       {
-         objfile->separate_debug_objfile
-            = symbol_file_add (debugfile, add_flags, NULL, 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 ()
-      && print_symbol_loading)
+  if ((from_tty || info_verbose)
+      && !objfile_has_symbols (objfile))
     {
       wrap_here ("");
-      printf_unfiltered (_("(no debugging symbols found)"));
-      if (from_tty || info_verbose)
-        printf_unfiltered ("...");
-      else
-        printf_unfiltered ("\n");
+      printf_unfiltered (_("(no debugging symbols found)..."));
       wrap_here ("");
     }
 
@@ -1066,10 +1036,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
       if (deprecated_post_add_symbol_hook)
        deprecated_post_add_symbol_hook ();
       else
-       {
-         if (print_symbol_loading)
-           printf_unfiltered (_("done.\n"));
-       }
+       printf_unfiltered (_("done.\n"));
     }
 
   /* We print some messages regardless of whether 'from_tty ||
@@ -1093,6 +1060,31 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
   return (objfile);
 }
 
+/* Add BFD as a separate debug file for OBJFILE.  */
+
+void
+symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile)
+{
+  struct objfile *new_objfile;
+  struct section_addr_info *sap;
+  struct cleanup *my_cleanup;
+
+  /* Create section_addr_info.  We can't directly use offsets from OBJFILE
+     because sections of BFD may not match sections of OBJFILE and because
+     vma may have been modified by tools such as prelink.  */
+  sap = build_section_addr_info_from_objfile (objfile);
+  my_cleanup = make_cleanup_free_section_addr_info (sap);
+
+  new_objfile = symbol_file_add_with_addrs_or_offsets
+    (bfd, symfile_flags,
+     sap, NULL, 0,
+     objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
+                      | OBJF_USERLOADED));
+
+  do_cleanups (my_cleanup);
+
+  add_separate_debug_objfile (new_objfile, objfile);
+}
 
 /* Process the symbol file ABFD, as either the main file or as a
    dynamically loaded file.
@@ -1166,108 +1158,11 @@ symbol_file_clear (int from_tty)
      descriptors as well.  */
   no_shared_libraries (NULL, from_tty);
 
-  symfile_objfile = NULL;
+  gdb_assert (symfile_objfile == NULL);
   if (from_tty)
     printf_unfiltered (_("No symbol file now.\n"));
 }
 
-struct build_id
-  {
-    size_t size;
-    gdb_byte data[1];
-  };
-
-/* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
-
-static struct build_id *
-build_id_bfd_get (bfd *abfd)
-{
-  struct build_id *retval;
-
-  if (!bfd_check_format (abfd, bfd_object)
-      || bfd_get_flavour (abfd) != bfd_target_elf_flavour
-      || elf_tdata (abfd)->build_id == NULL)
-    return NULL;
-
-  retval = xmalloc (sizeof *retval - 1 + elf_tdata (abfd)->build_id_size);
-  retval->size = elf_tdata (abfd)->build_id_size;
-  memcpy (retval->data, elf_tdata (abfd)->build_id, retval->size);
-
-  return retval;
-}
-
-/* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value.  */
-
-static int
-build_id_verify (const char *filename, struct build_id *check)
-{
-  bfd *abfd;
-  struct build_id *found = NULL;
-  int retval = 0;
-
-  /* We expect to be silent on the non-existing files.  */
-  if (remote_filename_p (filename))
-    abfd = remote_bfd_open (filename, gnutarget);
-  else
-    abfd = bfd_openr (filename, gnutarget);
-  if (abfd == NULL)
-    return 0;
-
-  found = build_id_bfd_get (abfd);
-
-  if (found == NULL)
-    warning (_("File \"%s\" has no build-id, file skipped"), filename);
-  else if (found->size != check->size
-           || memcmp (found->data, check->data, found->size) != 0)
-    warning (_("File \"%s\" has a different build-id, file skipped"), filename);
-  else
-    retval = 1;
-
-  if (!bfd_close (abfd))
-    warning (_("cannot close \"%s\": %s"), filename,
-            bfd_errmsg (bfd_get_error ()));
-
-  xfree (found);
-
-  return retval;
-}
-
-static char *
-build_id_to_debug_filename (struct build_id *build_id)
-{
-  char *link, *s, *retval = NULL;
-  gdb_byte *data = build_id->data;
-  size_t size = build_id->size;
-
-  /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
-  link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
-                 + 2 * size + (sizeof ".debug" - 1) + 1);
-  s = link + sprintf (link, "%s/.build-id/", debug_file_directory);
-  if (size > 0)
-    {
-      size--;
-      s += sprintf (s, "%02x", (unsigned) *data++);
-    }
-  if (size > 0)
-    *s++ = '/';
-  while (size-- > 0)
-    s += sprintf (s, "%02x", (unsigned) *data++);
-  strcpy (s, ".debug");
-
-  /* lrealpath() is expensive even for the usually non-existent files.  */
-  if (access (link, F_OK) == 0)
-    retval = lrealpath (link);
-  xfree (link);
-
-  if (retval != NULL && !build_id_verify (retval, build_id))
-    {
-      xfree (retval);
-      retval = NULL;
-    }
-
-  return retval;
-}
-
 static char *
 get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
 {
@@ -1300,27 +1195,63 @@ get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
 }
 
 static int
-separate_debug_file_exists (const char *name, unsigned long crc)
+separate_debug_file_exists (const char *name, unsigned long crc,
+                           struct objfile *parent_objfile)
 {
   unsigned long file_crc = 0;
   bfd *abfd;
   gdb_byte buffer[8*1024];
   int count;
+  struct stat parent_stat, abfd_stat;
 
-  if (remote_filename_p (name))
-    abfd = remote_bfd_open (name, gnutarget);
-  else
-    abfd = bfd_openr (name, gnutarget);
+  /* Find a separate debug info file as if symbols would be present in
+     PARENT_OBJFILE itself this function would not be called.  .gnu_debuglink
+     section can contain just the basename of PARENT_OBJFILE without any
+     ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where
+     the separate debug infos with the same basename can exist. */
+
+  if (strcmp (name, parent_objfile->name) == 0)
+    return 0;
+
+  abfd = bfd_open_maybe_remote (name);
 
   if (!abfd)
     return 0;
 
+  /* Verify symlinks were not the cause of strcmp name difference above.
+
+     Some operating systems, e.g. Windows, do not provide a meaningful
+     st_ino; they always set it to zero.  (Windows does provide a
+     meaningful st_dev.)  Do not indicate a duplicate library in that
+     case.  While there is no guarantee that a system that provides
+     meaningful inode numbers will never set st_ino to zero, this is
+     merely an optimization, so we do not need to worry about false
+     negatives.  */
+
+  if (bfd_stat (abfd, &abfd_stat) == 0
+      && bfd_stat (parent_objfile->obfd, &parent_stat) == 0
+      && abfd_stat.st_dev == parent_stat.st_dev
+      && abfd_stat.st_ino == parent_stat.st_ino
+      && abfd_stat.st_ino != 0)
+    {
+      bfd_close (abfd);
+      return 0;
+    }
+
   while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0)
     file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
 
   bfd_close (abfd);
 
-  return crc == file_crc;
+  if (crc != file_crc)
+    {
+      warning (_("the debug information found in \"%s\""
+                " does not match \"%s\" (CRC mismatch).\n"),
+              name, parent_objfile->name);
+      return 0;
+    }
+
+  return 1;
 }
 
 char *debug_file_directory = NULL;
@@ -1337,42 +1268,24 @@ The directory where separate debug symbols are searched for is \"%s\".\n"),
 #define DEBUG_SUBDIRECTORY ".debug"
 #endif
 
-static char *
-find_separate_debug_file (struct objfile *objfile)
+char *
+find_separate_debug_file_by_debuglink (struct objfile *objfile)
 {
   asection *sect;
-  char *basename;
-  char *dir;
-  char *debugfile;
-  char *name_copy;
-  char *canon_name;
+  char *basename, *name_copy, *debugdir;
+  char *dir = NULL;
+  char *debugfile = NULL;
+  char *canon_name = NULL;
   bfd_size_type debuglink_size;
   unsigned long crc32;
   int i;
-  struct build_id *build_id;
-
-  build_id = build_id_bfd_get (objfile->obfd);
-  if (build_id != NULL)
-    {
-      char *build_id_name;
-
-      build_id_name = build_id_to_debug_filename (build_id);
-      xfree (build_id);
-      /* Prevent looping on a stripped .debug file.  */
-      if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0)
-        {
-         warning (_("\"%s\": separate debug info file has no debug info"),
-                  build_id_name);
-         xfree (build_id_name);
-       }
-      else if (build_id_name != NULL)
-        return build_id_name;
-    }
 
   basename = get_debug_link_info (objfile, &crc32);
 
   if (basename == NULL)
-    return NULL;
+    /* There's no separate debug info, hence there's no way we could
+       load it => no warning.  */
+    goto cleanup_return_debugfile;
 
   dir = xstrdup (objfile->name);
 
@@ -1394,24 +1307,19 @@ find_separate_debug_file (struct objfile *objfile)
   if (canon_name && strlen (canon_name) > i)
     i = strlen (canon_name);
 
-  debugfile = alloca (strlen (debug_file_directory) + 1
-                      + i
-                      + strlen (DEBUG_SUBDIRECTORY)
-                      + strlen ("/")
-                      + strlen (basename)
-                      + 1);
+  debugfile = xmalloc (strlen (debug_file_directory) + 1
+                      + i
+                      + 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);
-      xfree (canon_name);
-      return xstrdup (debugfile);
-    }
+  if (separate_debug_file_exists (debugfile, crc32, objfile))
+    goto cleanup_return_debugfile;
 
   /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
   strcpy (debugfile, dir);
@@ -1419,54 +1327,63 @@ find_separate_debug_file (struct objfile *objfile)
   strcat (debugfile, "/");
   strcat (debugfile, basename);
 
-  if (separate_debug_file_exists (debugfile, crc32))
-    {
-      xfree (basename);
-      xfree (dir);
-      xfree (canon_name);
-      return xstrdup (debugfile);
-    }
+  if (separate_debug_file_exists (debugfile, crc32, objfile))
+    goto cleanup_return_debugfile;
 
-  /* Then try in the global debugfile directory.  */
-  strcpy (debugfile, debug_file_directory);
-  strcat (debugfile, "/");
-  strcat (debugfile, dir);
-  strcat (debugfile, basename);
+  /* Then try in the global debugfile directories.
+     Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
+     cause "/..." lookups.  */
 
-  if (separate_debug_file_exists (debugfile, crc32))
+  debugdir = debug_file_directory;
+  do
     {
-      xfree (basename);
-      xfree (dir);
-      xfree (canon_name);
-      return xstrdup (debugfile);
-    }
+      char *debugdir_end;
 
-  /* If the file is in the sysroot, try using its base path in the
-     global debugfile directory.  */
-  if (canon_name
-      && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
-      && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
-    {
-      strcpy (debugfile, debug_file_directory);
-      strcat (debugfile, canon_name + strlen (gdb_sysroot));
+      while (*debugdir == DIRNAME_SEPARATOR)
+       debugdir++;
+
+      debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
+      if (debugdir_end == NULL)
+       debugdir_end = &debugdir[strlen (debugdir)];
+
+      memcpy (debugfile, debugdir, debugdir_end - debugdir);
+      debugfile[debugdir_end - debugdir] = 0;
       strcat (debugfile, "/");
+      strcat (debugfile, dir);
       strcat (debugfile, basename);
 
-      if (separate_debug_file_exists (debugfile, crc32))
+      if (separate_debug_file_exists (debugfile, crc32, objfile))
+       goto cleanup_return_debugfile;
+
+      /* If the file is in the sysroot, try using its base path in the
+        global debugfile directory.  */
+      if (canon_name
+         && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
+         && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
        {
-         xfree (canon_name);
-         xfree (basename);
-         xfree (dir);
-         return xstrdup (debugfile);
+         memcpy (debugfile, debugdir, debugdir_end - debugdir);
+         debugfile[debugdir_end - debugdir] = 0;
+         strcat (debugfile, canon_name + strlen (gdb_sysroot));
+         strcat (debugfile, "/");
+         strcat (debugfile, basename);
+
+         if (separate_debug_file_exists (debugfile, crc32, objfile))
+           goto cleanup_return_debugfile;
        }
+
+      debugdir = debugdir_end;
     }
+  while (*debugdir != 0);
   
-  if (canon_name)
-    xfree (canon_name);
+  xfree (debugfile);
+  debugfile = NULL;
 
+cleanup_return_debugfile:
+  xfree (canon_name);
   xfree (basename);
   xfree (dir);
-  return NULL;
+  return debugfile;
 }
 
 
@@ -1557,6 +1474,19 @@ set_initial_language (void)
     }
 }
 
+/* If NAME is a remote name open the file using remote protocol, otherwise
+   open it normally.  */
+
+bfd *
+bfd_open_maybe_remote (const char *name)
+{
+  if (remote_filename_p (name))
+    return remote_bfd_open (name, gnutarget);
+  else
+    return bfd_openr (name, gnutarget);
+}
+
+
 /* Open the file specified by NAME and hand it off to BFD for
    preliminary analysis.  Return a newly initialized bfd *, which
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
@@ -2269,199 +2199,208 @@ reread_symbols (void)
 
   for (objfile = object_files; objfile; objfile = objfile->next)
     {
-      if (objfile->obfd)
-       {
+      /* solib-sunos.c creates one objfile with obfd.  */
+      if (objfile->obfd == NULL)
+       continue;
+
+      /* Separate debug objfiles are handled in the main objfile.  */
+      if (objfile->separate_debug_objfile_backlink)
+       continue;
+
 #ifdef DEPRECATED_IBM6000_TARGET
-         /* If this object is from a shared library, then you should
-            stat on the library name, not member name. */
+      /* If this object is from a shared library, then you should
+        stat on the library name, not member name. */
 
-         if (objfile->obfd->my_archive)
-           res = stat (objfile->obfd->my_archive->filename, &new_statbuf);
-         else
+      if (objfile->obfd->my_archive)
+       res = stat (objfile->obfd->my_archive->filename, &new_statbuf);
+      else
 #endif
-           res = stat (objfile->name, &new_statbuf);
-         if (res != 0)
-           {
-             /* FIXME, should use print_sys_errmsg but it's not filtered. */
-             printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"),
-                              objfile->name);
-             continue;
-           }
-         new_modtime = new_statbuf.st_mtime;
-         if (new_modtime != objfile->mtime)
+       res = stat (objfile->name, &new_statbuf);
+      if (res != 0)
+       {
+         /* FIXME, should use print_sys_errmsg but it's not filtered. */
+         printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"),
+                            objfile->name);
+         continue;
+       }
+      new_modtime = new_statbuf.st_mtime;
+      if (new_modtime != objfile->mtime)
+       {
+         struct cleanup *old_cleanups;
+         struct section_offsets *offsets;
+         int num_offsets;
+         char *obfd_filename;
+
+         printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"),
+                            objfile->name);
+
+         /* There are various functions like symbol_file_add,
+            symfile_bfd_open, syms_from_objfile, etc., which might
+            appear to do what we want.  But they have various other
+            effects which we *don't* want.  So we just do stuff
+            ourselves.  We don't worry about mapped files (for one thing,
+            any mapped file will be out of date).  */
+
+         /* If we get an error, blow away this objfile (not sure if
+            that is the correct response for things like shared
+            libraries).  */
+         old_cleanups = make_cleanup_free_objfile (objfile);
+         /* We need to do this whenever any symbols go away.  */
+         make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
+
+         if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd),
+                                         bfd_get_filename (exec_bfd)) == 0)
            {
-             struct cleanup *old_cleanups;
-             struct section_offsets *offsets;
-             int num_offsets;
-             char *obfd_filename;
-
-             printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"),
-                              objfile->name);
-
-             /* There are various functions like symbol_file_add,
-                symfile_bfd_open, syms_from_objfile, etc., which might
-                appear to do what we want.  But they have various other
-                effects which we *don't* want.  So we just do stuff
-                ourselves.  We don't worry about mapped files (for one thing,
-                any mapped file will be out of date).  */
-
-             /* If we get an error, blow away this objfile (not sure if
-                that is the correct response for things like shared
-                libraries).  */
-             old_cleanups = make_cleanup_free_objfile (objfile);
-             /* We need to do this whenever any symbols go away.  */
-             make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
-
-             if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd),
-                                             bfd_get_filename (exec_bfd)) == 0)
-               {
-                 /* Reload EXEC_BFD without asking anything.  */
+             /* Reload EXEC_BFD without asking anything.  */
 
-                 exec_file_attach (bfd_get_filename (objfile->obfd), 0);
-               }
+             exec_file_attach (bfd_get_filename (objfile->obfd), 0);
+           }
 
-             /* Clean up any state BFD has sitting around.  We don't need
-                to close the descriptor but BFD lacks a way of closing the
-                BFD without closing the descriptor.  */
-             obfd_filename = bfd_get_filename (objfile->obfd);
-             if (!bfd_close (objfile->obfd))
-               error (_("Can't close BFD for %s: %s"), objfile->name,
-                      bfd_errmsg (bfd_get_error ()));
-             if (remote_filename_p (obfd_filename))
-               objfile->obfd = remote_bfd_open (obfd_filename, gnutarget);
-             else
-               objfile->obfd = bfd_openr (obfd_filename, gnutarget);
-             if (objfile->obfd == NULL)
-               error (_("Can't open %s to read symbols."), objfile->name);
-             /* bfd_openr sets cacheable to true, which is what we want.  */
-             if (!bfd_check_format (objfile->obfd, bfd_object))
-               error (_("Can't read symbols from %s: %s."), objfile->name,
-                      bfd_errmsg (bfd_get_error ()));
-
-             /* Save the offsets, we will nuke them with the rest of the
-                objfile_obstack.  */
-             num_offsets = objfile->num_sections;
-             offsets = ((struct section_offsets *)
-                        alloca (SIZEOF_N_SECTION_OFFSETS (num_offsets)));
-             memcpy (offsets, objfile->section_offsets,
-                     SIZEOF_N_SECTION_OFFSETS (num_offsets));
-
-             /* Remove any references to this objfile in the global
-                value lists.  */
-             preserve_values (objfile);
-
-             /* Nuke all the state that we will re-read.  Much of the following
-                code which sets things to NULL really is necessary to tell
-                other parts of GDB that there is nothing currently there.
-                
-                Try to keep the freeing order compatible with free_objfile.  */
-
-             if (objfile->sf != NULL)
-               {
-                 (*objfile->sf->sym_finish) (objfile);
-               }
+         /* Clean up any state BFD has sitting around.  We don't need
+            to close the descriptor but BFD lacks a way of closing the
+            BFD without closing the descriptor.  */
+         obfd_filename = bfd_get_filename (objfile->obfd);
+         if (!bfd_close (objfile->obfd))
+           error (_("Can't close BFD for %s: %s"), objfile->name,
+                  bfd_errmsg (bfd_get_error ()));
+         objfile->obfd = bfd_open_maybe_remote (obfd_filename);
+         if (objfile->obfd == NULL)
+           error (_("Can't open %s to read symbols."), objfile->name);
+         else
+           objfile->obfd = gdb_bfd_ref (objfile->obfd);
+         /* bfd_openr sets cacheable to true, which is what we want.  */
+         if (!bfd_check_format (objfile->obfd, bfd_object))
+           error (_("Can't read symbols from %s: %s."), objfile->name,
+                  bfd_errmsg (bfd_get_error ()));
+
+         /* Save the offsets, we will nuke them with the rest of the
+            objfile_obstack.  */
+         num_offsets = objfile->num_sections;
+         offsets = ((struct section_offsets *)
+                    alloca (SIZEOF_N_SECTION_OFFSETS (num_offsets)));
+         memcpy (offsets, objfile->section_offsets,
+                 SIZEOF_N_SECTION_OFFSETS (num_offsets));
+
+         /* Remove any references to this objfile in the global
+            value lists.  */
+         preserve_values (objfile);
+
+         /* Nuke all the state that we will re-read.  Much of the following
+            code which sets things to NULL really is necessary to tell
+            other parts of GDB that there is nothing currently there.
+
+            Try to keep the freeing order compatible with free_objfile.  */
+
+         if (objfile->sf != NULL)
+           {
+             (*objfile->sf->sym_finish) (objfile);
+           }
 
-             clear_objfile_data (objfile);
-
-             /* FIXME: Do we have to free a whole linked list, or is this
-                enough?  */
-             if (objfile->global_psymbols.list)
-               xfree (objfile->global_psymbols.list);
-             memset (&objfile->global_psymbols, 0,
-                     sizeof (objfile->global_psymbols));
-             if (objfile->static_psymbols.list)
-               xfree (objfile->static_psymbols.list);
-             memset (&objfile->static_psymbols, 0,
-                     sizeof (objfile->static_psymbols));
-
-             /* Free the obstacks for non-reusable objfiles */
-             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->objfile_obstack, 0);
-             objfile->sections = NULL;
-             objfile->symtabs = NULL;
-             objfile->psymtabs = NULL;
-             objfile->psymtabs_addrmap = NULL;
-             objfile->free_psymtabs = NULL;
-             objfile->cp_namespace_symtab = NULL;
-             objfile->msymbols = NULL;
-             objfile->deprecated_sym_private = NULL;
-             objfile->minimal_symbol_count = 0;
-             memset (&objfile->msymbol_hash, 0,
-                     sizeof (objfile->msymbol_hash));
-             memset (&objfile->msymbol_demangled_hash, 0,
-                     sizeof (objfile->msymbol_demangled_hash));
-
-             objfile->psymbol_cache = bcache_xmalloc ();
-             objfile->macro_cache = bcache_xmalloc ();
-             /* obstack_init also initializes the obstack so it is
-                empty.  We could use obstack_specify_allocation but
-                gdb_obstack.h specifies the alloc/dealloc
-                functions.  */
-             obstack_init (&objfile->objfile_obstack);
-             if (build_objfile_section_table (objfile))
-               {
-                 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.  */
-             objfile->section_offsets = (struct section_offsets *)
-               obstack_alloc (&objfile->objfile_obstack,
-                              SIZEOF_N_SECTION_OFFSETS (num_offsets));
-             memcpy (objfile->section_offsets, offsets,
-                     SIZEOF_N_SECTION_OFFSETS (num_offsets));
-             objfile->num_sections = num_offsets;
-
-             /* What the hell is sym_new_init for, anyway?  The concept of
-                distinguishing between the main file and additional files
-                in this way seems rather dubious.  */
-             if (objfile == symfile_objfile)
-               {
-                 (*objfile->sf->sym_new_init) (objfile);
-               }
+         clear_objfile_data (objfile);
+
+         /* Free the separate debug objfiles.  It will be
+            automatically recreated by sym_read.  */
+          free_objfile_separate_debug (objfile);
+
+         /* FIXME: Do we have to free a whole linked list, or is this
+            enough?  */
+         if (objfile->global_psymbols.list)
+           xfree (objfile->global_psymbols.list);
+         memset (&objfile->global_psymbols, 0,
+                 sizeof (objfile->global_psymbols));
+         if (objfile->static_psymbols.list)
+           xfree (objfile->static_psymbols.list);
+         memset (&objfile->static_psymbols, 0,
+                 sizeof (objfile->static_psymbols));
+
+         /* Free the obstacks for non-reusable objfiles */
+         bcache_xfree (objfile->psymbol_cache);
+         objfile->psymbol_cache = bcache_xmalloc ();
+         bcache_xfree (objfile->macro_cache);
+         objfile->macro_cache = bcache_xmalloc ();
+         bcache_xfree (objfile->filename_cache);
+         objfile->filename_cache = bcache_xmalloc ();
+         if (objfile->demangled_names_hash != NULL)
+           {
+             htab_delete (objfile->demangled_names_hash);
+             objfile->demangled_names_hash = NULL;
+           }
+         obstack_free (&objfile->objfile_obstack, 0);
+         objfile->sections = NULL;
+         objfile->symtabs = NULL;
+         objfile->psymtabs = NULL;
+         objfile->psymtabs_addrmap = NULL;
+         objfile->free_psymtabs = NULL;
+         objfile->cp_namespace_symtab = NULL;
+         objfile->msymbols = NULL;
+         objfile->deprecated_sym_private = NULL;
+         objfile->minimal_symbol_count = 0;
+         memset (&objfile->msymbol_hash, 0,
+                 sizeof (objfile->msymbol_hash));
+         memset (&objfile->msymbol_demangled_hash, 0,
+                 sizeof (objfile->msymbol_demangled_hash));
+
+         objfile->psymbol_cache = bcache_xmalloc ();
+         objfile->macro_cache = bcache_xmalloc ();
+         objfile->filename_cache = bcache_xmalloc ();
+         /* obstack_init also initializes the obstack so it is
+            empty.  We could use obstack_specify_allocation but
+            gdb_obstack.h specifies the alloc/dealloc
+            functions.  */
+         obstack_init (&objfile->objfile_obstack);
+         if (build_objfile_section_table (objfile))
+           {
+             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.  */
+         objfile->section_offsets = (struct section_offsets *)
+           obstack_alloc (&objfile->objfile_obstack,
+                          SIZEOF_N_SECTION_OFFSETS (num_offsets));
+         memcpy (objfile->section_offsets, offsets,
+                 SIZEOF_N_SECTION_OFFSETS (num_offsets));
+         objfile->num_sections = num_offsets;
+
+         /* What the hell is sym_new_init for, anyway?  The concept of
+            distinguishing between the main file and additional files
+            in this way seems rather dubious.  */
+         if (objfile == symfile_objfile)
+           {
+             (*objfile->sf->sym_new_init) (objfile);
+           }
 
-             (*objfile->sf->sym_init) (objfile);
-             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.  */
-             (*objfile->sf->sym_read) (objfile, 0);
-             if (!have_partial_symbols () && !have_full_symbols ())
-               {
-                 wrap_here ("");
-                 printf_unfiltered (_("(no debugging symbols found)\n"));
-                 wrap_here ("");
-               }
+         (*objfile->sf->sym_init) (objfile);
+         clear_complaints (&symfile_complaints, 1, 1);
+         /* Do not set flags as this is safe and we don't want to be
+             verbose.  */
+         (*objfile->sf->sym_read) (objfile, 0);
+         if (!objfile_has_symbols (objfile))
+           {
+             wrap_here ("");
+             printf_unfiltered (_("(no debugging symbols found)\n"));
+             wrap_here ("");
+           }
 
-             /* We're done reading the symbol file; finish off complaints.  */
-             clear_complaints (&symfile_complaints, 0, 1);
+         /* We're done reading the symbol file; finish off complaints.  */
+         clear_complaints (&symfile_complaints, 0, 1);
 
-             /* Getting new symbols may change our opinion about what is
-                frameless.  */
+         /* Getting new symbols may change our opinion about what is
+            frameless.  */
 
-             reinit_frame_cache ();
+         reinit_frame_cache ();
 
-             /* Discard cleanups as symbol reading was successful.  */
-             discard_cleanups (old_cleanups);
+         /* Discard cleanups as symbol reading was successful.  */
+         discard_cleanups (old_cleanups);
 
-             /* If the mtime has changed between the time we set new_modtime
-                and now, we *want* this to be out of date, so don't call stat
-                again now.  */
-             objfile->mtime = new_modtime;
-             reread_one = 1;
-              reread_separate_symbols (objfile);
-             init_entry_point_info (objfile);
-           }
+         /* If the mtime has changed between the time we set new_modtime
+            and now, we *want* this to be out of date, so don't call stat
+            again now.  */
+         objfile->mtime = new_modtime;
+         reread_one = 1;
+         init_entry_point_info (objfile);
        }
     }
 
@@ -2476,73 +2415,6 @@ reread_symbols (void)
       observer_notify_executable_changed ();
     }
 }
-
-
-/* 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
-           (symfile_bfd_open (debug_file),
-            info_verbose ? SYMFILE_VERBOSE : 0,
-            0, /* No addr table.  */
-            objfile->section_offsets, objfile->num_sections,
-            objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
-                              | OBJF_USERLOADED)));
-      objfile->separate_debug_objfile->separate_debug_objfile_backlink
-        = objfile;
-    }
-  if (debug_file)
-    xfree (debug_file);
-}
-
-
 \f
 
 
@@ -2723,12 +2595,11 @@ allocate_symtab (char *filename, struct objfile *objfile)
   symtab = (struct symtab *)
     obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab));
   memset (symtab, 0, sizeof (*symtab));
-  symtab->filename = obsavestring (filename, strlen (filename),
-                                  &objfile->objfile_obstack);
+  symtab->filename = (char *) bcache (filename, strlen (filename) + 1,
+                                     objfile->filename_cache);
   symtab->fullname = NULL;
   symtab->language = deduce_language_from_filename (filename);
-  symtab->debugformat = obsavestring ("unknown", 7,
-                                     &objfile->objfile_obstack);
+  symtab->debugformat = "unknown";
 
   /* Hook it to the objfile it comes from */
 
@@ -2740,7 +2611,7 @@ allocate_symtab (char *filename, struct objfile *objfile)
 }
 
 struct partial_symtab *
-allocate_psymtab (char *filename, struct objfile *objfile)
+allocate_psymtab (const char *filename, struct objfile *objfile)
 {
   struct partial_symtab *psymtab;
 
@@ -2755,8 +2626,8 @@ allocate_psymtab (char *filename, struct objfile *objfile)
                     sizeof (struct partial_symtab));
 
   memset (psymtab, 0, sizeof (struct partial_symtab));
-  psymtab->filename = obsavestring (filename, strlen (filename),
-                                   &objfile->objfile_obstack);
+  psymtab->filename = (char *) bcache (filename, strlen (filename) + 1,
+                                      objfile->filename_cache);
   psymtab->symtab = NULL;
 
   /* Prepend it to the psymtab list for the objfile it belongs to.
@@ -2822,7 +2693,7 @@ clear_symtab_users (void)
 
   clear_displays ();
   breakpoint_re_set ();
-  set_default_breakpoint (0, 0, 0, 0);
+  set_default_breakpoint (0, NULL, 0, 0, 0);
   clear_pc_function_cache ();
   observer_notify_new_objfile (NULL);
 
@@ -3054,7 +2925,8 @@ again2:
 
 struct partial_symtab *
 start_psymtab_common (struct objfile *objfile,
-                     struct section_offsets *section_offsets, char *filename,
+                     struct section_offsets *section_offsets,
+                     const char *filename,
                      CORE_ADDR textlow, struct partial_symbol **global_syms,
                      struct partial_symbol **static_syms)
 {
@@ -3076,26 +2948,23 @@ start_psymtab_common (struct objfile *objfile,
    different domain (or address) is possible and correct.  */
 
 static const struct partial_symbol *
-add_psymbol_to_bcache (char *name, int namelength, domain_enum domain,
+add_psymbol_to_bcache (char *name, int namelength, int copy_name,
+                      domain_enum domain,
                       enum address_class class,
                       long val,        /* Value as a long */
                       CORE_ADDR coreaddr,      /* Value as a CORE_ADDR */
                       enum language language, struct objfile *objfile,
                       int *added)
 {
-  char *buf = name;  
   /* psymbol is static so that there will be no uninitialized gaps in the
      structure which might contain random data, causing cache misses in
      bcache. */
   static struct partial_symbol psymbol;
-  
-  if (name[namelength] != '\0')
-    {
-      buf = alloca (namelength + 1);
-      /* Create local copy of the partial symbol */
-      memcpy (buf, name, namelength);
-      buf[namelength] = '\0';
-    }
+
+  /* However, we must ensure that the entire 'value' field has been
+     zeroed before assigning to it, because an assignment may not
+     write the entire field.  */
+  memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
   /* val and coreaddr are mutually exclusive, one of them *will* be zero */
   if (val != 0)
     {
@@ -3110,7 +2979,7 @@ add_psymbol_to_bcache (char *name, int namelength, domain_enum domain,
   PSYMBOL_DOMAIN (&psymbol) = domain;
   PSYMBOL_CLASS (&psymbol) = class;
 
-  SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
+  SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
 
   /* Stash the partial symbol away in the cache */
   return bcache_full (&psymbol, sizeof (struct partial_symbol),
@@ -3147,7 +3016,8 @@ append_psymbol_to_list (struct psymbol_allocation_list *list,
    cache.  */
 
 const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, domain_enum domain,
+add_psymbol_to_list (char *name, int namelength, int copy_name,
+                    domain_enum domain,
                     enum address_class class,
                     struct psymbol_allocation_list *list, 
                     long val,  /* Value as a long */
@@ -3159,7 +3029,7 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain,
   int added;
 
   /* Stash the partial symbol away in the cache */
-  psym = add_psymbol_to_bcache (name, namelength, domain, class,
+  psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
                                val, coreaddr, language, objfile, &added);
 
   /* Do not duplicate global partial symbols.  */
@@ -4196,21 +4066,13 @@ Usage: set extension-language .foo bar"),
 
   add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
                                     &debug_file_directory, _("\
-Set the directory where separate debug symbols are searched for."), _("\
-Show the directory where separate debug symbols are searched for."), _("\
+Set the directories where separate debug symbols are searched for."), _("\
+Show the directories where separate debug symbols are searched for."), _("\
 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."),
+each global debug-file-directory component prepended."),
                                     NULL,
                                     show_debug_file_directory,
                                     &setlist, &showlist);
-
-  add_setshow_boolean_cmd ("symbol-loading", no_class,
-                           &print_symbol_loading, _("\
-Set printing of symbol loading messages."), _("\
-Show printing of symbol loading messages."), NULL,
-                           NULL,
-                           NULL,
-                           &setprintlist, &showprintlist);
 }