fix typo in previous entry
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 7e6ea2c8b500bda1a64dfc8f549c9945600fc9b9..eda26cc0436bb8dbbed04dc758a29868cd8ff428 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.
@@ -22,6 +22,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "bfdlink.h"
 #include "symtab.h"
 #include "gdbtypes.h"
@@ -64,6 +65,7 @@
 #include <time.h>
 #include <sys/time.h>
 
+#include "psymtab.h"
 
 int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num);
 void (*deprecated_show_load_progress) (const char *section,
@@ -96,10 +98,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 *);
 
 int get_section_index (struct objfile *, char *);
@@ -128,7 +126,8 @@ static void overlay_command (char *, int);
 
 static void simple_free_overlay_table (void);
 
-static void read_target_long_array (CORE_ADDR, unsigned int *, int);
+static void read_target_long_array (CORE_ADDR, unsigned int *, int, int,
+                                   enum bfd_endian);
 
 static int simple_read_overlay_table (void);
 
@@ -138,8 +137,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);
@@ -169,13 +166,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
@@ -199,29 +189,6 @@ int auto_solib_add = 1;
 int auto_solib_limit;
 \f
 
-/* This compares two partial symbols by names, using strcmp_iw_ordered
-   for the comparison.  */
-
-static int
-compare_psymbols (const void *s1p, const void *s2p)
-{
-  struct partial_symbol *const *s1 = s1p;
-  struct partial_symbol *const *s2 = s2p;
-
-  return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
-                           SYMBOL_SEARCH_NAME (*s2));
-}
-
-void
-sort_pst_symbols (struct partial_symtab *pst)
-{
-  /* Sort the global list; don't sort the static list */
-
-  qsort (pst->objfile->global_psymbols.list + pst->globals_offset,
-        pst->n_global_syms, sizeof (struct partial_symbol *),
-        compare_psymbols);
-}
-
 /* Make a null terminated copy of the string at PTR with SIZE characters in
    the obstack pointed to by OBSTACKP .  Returns the address of the copy.
    Note that the string at PTR does not have to be null terminated, I.E. it
@@ -260,7 +227,7 @@ obconcat (struct obstack *obstackp, const char *s1, const char *s2,
   return val;
 }
 
-/* True if we are nested inside psymtab_to_symtab. */
+/* True if we are reading a symbol table. */
 
 int currently_reading_symtab = 0;
 
@@ -270,28 +237,13 @@ decrement_reading_symtab (void *dummy)
   currently_reading_symtab--;
 }
 
-/* Get the symbol table that corresponds to a partial_symtab.
-   This is fast after the first time you do it.  In fact, there
-   is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
-   case inline.  */
-
-struct symtab *
-psymtab_to_symtab (struct partial_symtab *pst)
+/* Increment currently_reading_symtab and return a cleanup that can be
+   used to decrement it.  */
+struct cleanup *
+increment_reading_symtab (void)
 {
-  /* If it's been looked up before, return it. */
-  if (pst->symtab)
-    return pst->symtab;
-
-  /* If it has not yet been read in, read it.  */
-  if (!pst->readin)
-    {
-      struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL);
-      currently_reading_symtab++;
-      (*pst->read_symtab) (pst);
-      do_cleanups (back_to);
-    }
-
-  return pst->symtab;
+  ++currently_reading_symtab;
+  return make_cleanup (decrement_reading_symtab, NULL);
 }
 
 /* Remember the lowest-addressed loadable section we've seen.
@@ -308,7 +260,7 @@ find_lowest_section (bfd *abfd, asection *sect, void *obj)
 {
   asection **lowest = (asection **) obj;
 
-  if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD))
+  if (0 == (bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD)))
     return;
   if (!*lowest)
     *lowest = sect;            /* First loadable section */
@@ -337,32 +289,6 @@ alloc_section_addr_info (size_t num_sections)
   return sap;
 }
 
-
-/* Return a freshly allocated copy of ADDRS.  The section names, if
-   any, are also freshly allocated copies of those in ADDRS.  */
-struct section_addr_info *
-copy_section_addr_info (struct section_addr_info *addrs)
-{
-  struct section_addr_info *copy
-    = alloc_section_addr_info (addrs->num_sections);
-  int i;
-
-  copy->num_sections = addrs->num_sections;
-  for (i = 0; i < addrs->num_sections; i++)
-    {
-      copy->other[i].addr = addrs->other[i].addr;
-      if (addrs->other[i].name)
-        copy->other[i].name = xstrdup (addrs->other[i].name);
-      else
-        copy->other[i].name = NULL;
-      copy->other[i].sectindex = addrs->other[i].sectindex;
-    }
-
-  return copy;
-}
-
-
-
 /* Build (allocate and populate) a section_addr_info struct from
    an existing section table. */
 
@@ -393,6 +319,47 @@ build_section_addr_info_from_section_table (const struct target_section *start,
   return sap;
 }
 
+/* Create a section_addr_info from section offsets in ABFD.  */
+
+static struct section_addr_info *
+build_section_addr_info_from_bfd (bfd *abfd)
+{
+  struct section_addr_info *sap;
+  int i;
+  struct bfd_section *sec;
+
+  sap = alloc_section_addr_info (bfd_count_sections (abfd));
+  for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next)
+    if (bfd_get_section_flags (abfd, sec) & (SEC_ALLOC | SEC_LOAD))
+      {
+       sap->other[i].addr = bfd_get_section_vma (abfd, sec);
+       sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec));
+       sap->other[i].sectindex = sec->index;
+       i++;
+      }
+  return sap;
+}
+
+/* Create a section_addr_info from section offsets in OBJFILE.  */
+
+struct section_addr_info *
+build_section_addr_info_from_objfile (const struct objfile *objfile)
+{
+  struct section_addr_info *sap;
+  int i;
+
+  /* Before reread_symbols gets rewritten it is not safe to call:
+     gdb_assert (objfile->num_sections == bfd_count_sections (objfile->obfd));
+     */
+  sap = build_section_addr_info_from_bfd (objfile->obfd);
+  for (i = 0; i < sap->num_sections && sap->other[i].name; i++)
+    {
+      int sectindex = sap->other[i].sectindex;
+
+      sap->other[i].addr += objfile->section_offsets->offsets[sectindex];
+    }
+  return sap;
+}
 
 /* Free all memory allocated by build_section_addr_info_from_section_table. */
 
@@ -541,41 +508,227 @@ place_section (bfd *abfd, asection *sect, void *obj)
   arg->lowest = start_addr + bfd_get_section_size (sect);
 }
 
-/* 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
-   don't need to do anything special.  It allocates a section_offsets table
-   for the objectfile OBJFILE and stuffs ADDR into all of the offsets.  */
+/* Store struct section_addr_info as prepared (made relative and with SECTINDEX
+   filled-in) by addr_info_make_relative into SECTION_OFFSETS of NUM_SECTIONS
+   entries.  */
 
 void
-default_symfile_offsets (struct objfile *objfile,
-                        struct section_addr_info *addrs)
+relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
+                                      int num_sections,
+                                      struct section_addr_info *addrs)
 {
   int i;
 
-  objfile->num_sections = bfd_count_sections (objfile->obfd);
-  objfile->section_offsets = (struct section_offsets *)
-    obstack_alloc (&objfile->objfile_obstack,
-                  SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
-  memset (objfile->section_offsets, 0,
-         SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
+  memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections));
 
-  /* Now calculate offsets for section that were specified by the
-     caller. */
+  /* Now calculate offsets for section that were specified by the caller. */
   for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++)
     {
-      struct other_sections *osp ;
+      struct other_sections *osp;
 
-      osp = &addrs->other[i] ;
+      osp = &addrs->other[i];
       if (osp->addr == 0)
        continue;
 
       /* Record all sections in offsets */
       /* The section_offsets in the objfile are here filled in using
          the BFD index. */
-      (objfile->section_offsets)->offsets[osp->sectindex] = osp->addr;
+      section_offsets->offsets[osp->sectindex] = osp->addr;
+    }
+}
+
+/* qsort comparator for addrs_section_sort.  Sort entries in ascending order by
+   their (name, sectindex) pair.  sectindex makes the sort by name stable.  */
+
+static int
+addrs_section_compar (const void *ap, const void *bp)
+{
+  const struct other_sections *a = *((struct other_sections **) ap);
+  const struct other_sections *b = *((struct other_sections **) bp);
+  int retval, a_idx, b_idx;
+
+  retval = strcmp (a->name, b->name);
+  if (retval)
+    return retval;
+
+  /* SECTINDEX is undefined iff ADDR is zero.  */
+  a_idx = a->addr == 0 ? 0 : a->sectindex;
+  b_idx = b->addr == 0 ? 0 : b->sectindex;
+  return a_idx - b_idx;
+}
+
+/* Provide sorted array of pointers to sections of ADDRS.  The array is
+   terminated by NULL.  Caller is responsible to call xfree for it.  */
+
+static struct other_sections **
+addrs_section_sort (struct section_addr_info *addrs)
+{
+  struct other_sections **array;
+  int i;
+
+  /* `+ 1' for the NULL terminator.  */
+  array = xmalloc (sizeof (*array) * (addrs->num_sections + 1));
+  for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++)
+    array[i] = &addrs->other[i];
+  array[i] = NULL;
+
+  qsort (array, i, sizeof (*array), addrs_section_compar);
+
+  return array;
+}
+
+/* Relativize absolute addresses in ADDRS into offsets based on ABFD.  Fill-in
+   also SECTINDEXes specific to ABFD there.  This function can be used to
+   rebase ADDRS to start referencing different BFD than before.  */
+
+void
+addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
+{
+  asection *lower_sect;
+  CORE_ADDR lower_offset;
+  int i;
+  struct cleanup *my_cleanup;
+  struct section_addr_info *abfd_addrs;
+  struct other_sections **addrs_sorted, **abfd_addrs_sorted;
+  struct other_sections **addrs_to_abfd_addrs;
+
+  /* Find lowest loadable section to be used as starting point for
+     continguous sections.  */
+  lower_sect = NULL;
+  bfd_map_over_sections (abfd, find_lowest_section, &lower_sect);
+  if (lower_sect == NULL)
+    {
+      warning (_("no loadable sections found in added symbol-file %s"),
+              bfd_get_filename (abfd));
+      lower_offset = 0;
+    }
+  else
+    lower_offset = bfd_section_vma (bfd_get_filename (abfd), lower_sect);
+
+  /* Create ADDRS_TO_ABFD_ADDRS array to map the sections in ADDRS to sections
+     in ABFD.  Section names are not unique - there can be multiple sections of
+     the same name.  Also the sections of the same name do not have to be
+     adjacent to each other.  Some sections may be present only in one of the
+     files.  Even sections present in both files do not have to be in the same
+     order.
+
+     Use stable sort by name for the sections in both files.  Then linearly
+     scan both lists matching as most of the entries as possible.  */
+
+  addrs_sorted = addrs_section_sort (addrs);
+  my_cleanup = make_cleanup (xfree, addrs_sorted);
+
+  abfd_addrs = build_section_addr_info_from_bfd (abfd);
+  make_cleanup_free_section_addr_info (abfd_addrs);
+  abfd_addrs_sorted = addrs_section_sort (abfd_addrs);
+  make_cleanup (xfree, abfd_addrs_sorted);
+
+  /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and ABFD_ADDRS_SORTED.  */
+
+  addrs_to_abfd_addrs = xzalloc (sizeof (*addrs_to_abfd_addrs)
+                                * addrs->num_sections);
+  make_cleanup (xfree, addrs_to_abfd_addrs);
+
+  while (*addrs_sorted)
+    {
+      const char *sect_name = (*addrs_sorted)->name;
+
+      while (*abfd_addrs_sorted
+            && strcmp ((*abfd_addrs_sorted)->name, sect_name) < 0)
+       abfd_addrs_sorted++;
+
+      if (*abfd_addrs_sorted
+         && strcmp ((*abfd_addrs_sorted)->name, sect_name) == 0)
+       {
+         int index_in_addrs;
+
+         /* Make the found item directly addressable from ADDRS.  */
+         index_in_addrs = *addrs_sorted - addrs->other;
+         gdb_assert (addrs_to_abfd_addrs[index_in_addrs] == NULL);
+         addrs_to_abfd_addrs[index_in_addrs] = *abfd_addrs_sorted;
+
+         /* Never use the same ABFD entry twice.  */
+         abfd_addrs_sorted++;
+       }
+
+      addrs_sorted++;
+    }
+
+  /* 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
+     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 */
+
+  for (i = 0; i < addrs->num_sections && addrs->other[i].name; i++)
+    {
+      const char *sect_name = addrs->other[i].name;
+      struct other_sections *sect = addrs_to_abfd_addrs[i];
+
+      if (sect)
+       {
+         /* This is the index used by BFD. */
+         addrs->other[i].sectindex = sect->sectindex;
+
+         if (addrs->other[i].addr != 0)
+           {
+             addrs->other[i].addr -= sect->addr;
+             lower_offset = addrs->other[i].addr;
+           }
+         else
+           addrs->other[i].addr = lower_offset;
+       }
+      else
+       {
+         /* This section does not exist in ABFD, which is normally
+            unexpected and we want to issue a warning.
+
+            However, the ELF prelinker does create a few sections which are
+            marked in the main executable as loadable (they are loaded in
+            memory from the DYNAMIC segment) and yet are not present in
+            separate debug info files.  This is fine, and should not cause
+            a warning.  Shared libraries contain just the section
+            ".gnu.liblist" but it is not marked as loadable there.  There is
+            no other way to identify them than by their name as the sections
+            created by prelink have no special flags.  */
+
+         if (!(strcmp (sect_name, ".gnu.liblist") == 0
+               || strcmp (sect_name, ".gnu.conflict") == 0
+               || strcmp (sect_name, ".dynbss") == 0
+               || strcmp (sect_name, ".sdynbss") == 0))
+           warning (_("section %s not found in %s"), sect_name,
+                    bfd_get_filename (abfd));
+
+         addrs->other[i].addr = 0;
+
+         /* SECTINDEX is invalid if ADDR is zero.  */
+       }
     }
 
+  do_cleanups (my_cleanup);
+}
+
+/* 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
+   don't need to do anything special.  It allocates a section_offsets table
+   for the objectfile OBJFILE and stuffs ADDR into all of the offsets.  */
+
+void
+default_symfile_offsets (struct objfile *objfile,
+                        struct section_addr_info *addrs)
+{
+  objfile->num_sections = bfd_count_sections (objfile->obfd);
+  objfile->section_offsets = (struct section_offsets *)
+    obstack_alloc (&objfile->objfile_obstack,
+                  SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
+  relative_addr_info_to_section_offsets (objfile->section_offsets,
+                                        objfile->num_sections, addrs);
+
   /* For relocatable files, all loadable sections will start at zero.
      The zero is meaningless, so try to pick arbitrary addresses such
      that no loadable sections overlap.  This algorithm is quadratic,
@@ -791,7 +944,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.
@@ -808,65 +961,8 @@ 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)
-    {
-      asection *lower_sect;
-      asection *sect;
-      CORE_ADDR lower_offset;
-      int i;
-
-      /* Find lowest loadable section to be used as starting point for
-         continguous sections. FIXME!! won't work without call to find
-        .text first, but this assumes text is lowest section. */
-      lower_sect = bfd_get_section_by_name (objfile->obfd, ".text");
-      if (lower_sect == NULL)
-       bfd_map_over_sections (objfile->obfd, find_lowest_section,
-                              &lower_sect);
-      if (lower_sect == NULL)
-       {
-         warning (_("no loadable sections found in added symbol-file %s"),
-                  objfile->name);
-         lower_offset = 0;
-       }
-      else
-       lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
-
-      /* 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
-        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 */
-
-        for (i = 0; i < addrs->num_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;
-          }
-    }
+  if (addrs && addrs->other[0].name)
+    addr_info_make_relative (addrs, objfile->obfd);
 
   /* Initialize symbol reading routines for this objfile, allow complaints to
      appear for this new file, and record how verbose to be, then do the
@@ -891,7 +987,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.  */
 
@@ -919,7 +1015,7 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
     }
   else if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
     {
-      breakpoint_re_set_objfile (objfile);
+      breakpoint_re_set ();
     }
 
   /* We're done reading the symbol file; finish off complaints.  */
@@ -951,9 +1047,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
                                        int flags)
 {
   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;
@@ -972,12 +1065,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. */
@@ -987,12 +1074,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,
@@ -1005,57 +1089,22 @@ 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 ("");
          gdb_flush (gdb_stdout);
        }
 
-      for (psymtab = objfile->psymtabs;
-          psymtab != NULL;
-          psymtab = psymtab->next)
-       {
-         psymtab_to_symtab (psymtab);
-       }
-    }
-
-  /* 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 (objfile->sf)
+       objfile->sf->qf->expand_all_symtabs (objfile);
     }
 
-  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 ("");
     }
 
@@ -1064,10 +1113,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 ||
@@ -1078,7 +1124,10 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
   do_cleanups (my_cleanups);
 
   if (objfile->sf == NULL)
-    return objfile;    /* No symbols. */
+    {
+      observer_notify_new_objfile (objfile);
+      return objfile;  /* No symbols. */
+    }
 
   new_symfile_objfile (objfile, add_flags);
 
@@ -1088,6 +1137,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.
@@ -1161,108 +1235,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)
 {
@@ -1295,27 +1272,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;
@@ -1332,42 +1345,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);
 
@@ -1383,23 +1378,25 @@ find_separate_debug_file (struct objfile *objfile)
   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);
+  /* Set I to max (strlen (canon_name), strlen (dir)). */
+  canon_name = lrealpath (dir);
+  i = strlen (dir);
+  if (canon_name && strlen (canon_name) > i)
+    i = strlen (canon_name);
+
+  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);
-      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);
@@ -1407,53 +1404,63 @@ find_separate_debug_file (struct objfile *objfile)
   strcat (debugfile, "/");
   strcat (debugfile, basename);
 
-  if (separate_debug_file_exists (debugfile, crc32))
-    {
-      xfree (basename);
-      xfree (dir);
-      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);
-      return xstrdup (debugfile);
-    }
+      char *debugdir_end;
 
-  /* If the file is in the sysroot, try using its base path in the
-     global debugfile directory.  */
-  canon_name = lrealpath (dir);
-  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;
 }
 
 
@@ -1524,26 +1531,36 @@ symbol_file_command (char *args, int from_tty)
 void
 set_initial_language (void)
 {
-  struct partial_symtab *pst;
+  char *filename;
   enum language lang = language_unknown;
 
-  pst = find_main_psymtab ();
-  if (pst != NULL)
+  filename = find_main_filename ();
+  if (filename != NULL)
+    lang = deduce_language_from_filename (filename);
+
+  if (lang == language_unknown)
     {
-      if (pst->filename != NULL)
-       lang = deduce_language_from_filename (pst->filename);
+      /* Make C the default language */
+      lang = language_c;
+    }
 
-      if (lang == language_unknown)
-       {
-         /* Make C the default language */
-         lang = language_c;
-       }
+  set_language (lang);
+  expected_language = current_language; /* Don't warn the user.  */
+}
 
-      set_language (lang);
-      expected_language = current_language; /* Don't warn the user.  */
-    }
+/* 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
@@ -1624,6 +1641,9 @@ symfile_bfd_open (char *name)
             bfd_errmsg (bfd_get_error ()));
     }
 
+  /* bfd_usrdata exists for applications and libbfd must not touch it.  */
+  gdb_assert (bfd_usrdata (sym_bfd) == NULL);
+
   return sym_bfd;
 }
 
@@ -1799,9 +1819,9 @@ load_progress (ULONGEST bytes, void *untyped_arg)
     {
       /* The write is just starting.  Let the user know we've started
         this section.  */
-      ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
-                     args->section_name, paddr_nz (args->section_size),
-                     paddr_nz (args->lma));
+      ui_out_message (uiout, 0, "Loading section %s, size %s lma %s\n",
+                     args->section_name, hex_string (args->section_size),
+                     paddress (target_gdbarch, args->lma));
       return;
     }
 
@@ -1818,11 +1838,11 @@ load_progress (ULONGEST bytes, void *untyped_arg)
       struct cleanup *verify_cleanups = make_cleanup (xfree, check);
 
       if (target_read_memory (args->lma, check, bytes) != 0)
-       error (_("Download verify read failed at 0x%s"),
-              paddr (args->lma));
+       error (_("Download verify read failed at %s"),
+              paddress (target_gdbarch, args->lma));
       if (memcmp (args->buffer, check, bytes) != 0)
-       error (_("Download verify compare failed at 0x%s"),
-              paddr (args->lma));
+       error (_("Download verify compare failed at %s"),
+              paddress (target_gdbarch, args->lma));
       do_cleanups (verify_cleanups);
     }
   totals->data_count += bytes;
@@ -1978,7 +1998,7 @@ generic_load (char *args, int from_tty)
 
   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_field_fmt (uiout, "address", "%s", paddress (target_gdbarch, entry));
   ui_out_text (uiout, ", load size ");
   ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
   ui_out_text (uiout, "\n");
@@ -1986,6 +2006,16 @@ generic_load (char *args, int from_tty)
      for other targets too.  */
   regcache_write_pc (get_current_regcache (), entry);
 
+  /* Reset breakpoints, now that we have changed the load image.  For
+     instance, breakpoints may have been set (or reset, by
+     post_create_inferior) while connected to the target but before we
+     loaded the program.  In that case, the prologue analyzer could
+     have read instructions from the target to find the right
+     breakpoint locations.  Loading has changed the contents of that
+     memory.  */
+
+  breakpoint_re_set ();
+
   /* 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
@@ -2080,6 +2110,7 @@ print_transfer_performance (struct ui_file *stream,
 static void
 add_symbol_file_command (char *args, int from_tty)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
   char *filename = NULL;
   int flags = OBJF_USERLOADED;
   char *arg;
@@ -2210,7 +2241,8 @@ add_symbol_file_command (char *args, int from_tty)
          entered on the command line. */
       section_addrs->other[sec_num].name = sec;
       section_addrs->other[sec_num].addr = addr;
-      printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr));
+      printf_unfiltered ("\t%s_addr = %s\n", sec,
+                        paddress (gdbarch, addr));
       sec_num++;
 
       /* The object's sections are initialized when a
@@ -2251,274 +2283,222 @@ 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)
+       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)
+           {
+             /* Reload EXEC_BFD without asking anything.  */
+
+             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 ()));
+         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)
            {
-             /* FIXME, should use print_sys_errmsg but it's not filtered. */
-             printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"),
-                              objfile->name);
-             continue;
+             (*objfile->sf->sym_finish) (objfile);
            }
-         new_modtime = new_statbuf.st_mtime;
-         if (new_modtime != objfile->mtime)
+
+         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)
            {
-             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.  */
-
-                 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.  */
-
-             /* 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));
-             clear_objfile_data (objfile);
-             if (objfile->sf != NULL)
-               {
-                 (*objfile->sf->sym_finish) (objfile);
-               }
-
-             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);
-               }
-
-             (*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 ("");
-               }
-
-             /* 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.  */
-
-             reinit_frame_cache ();
-
-             /* 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);
+             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);
+         /* 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);
+
+         /* Getting new symbols may change our opinion about what is
+            frameless.  */
+
+         reinit_frame_cache ();
+
+         /* 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;
+         init_entry_point_info (objfile);
        }
     }
 
   if (reread_one)
     {
+      /* Notify objfiles that we've modified objfile sections.  */
+      objfiles_changed ();
+
       clear_symtab_users ();
       /* At least one objfile has changed, so we can consider that
          the executable we're debugging has changed too.  */
       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
 
 
@@ -2688,7 +2668,6 @@ deduce_language_from_filename (char *filename)
    symtab->dirname
    symtab->free_code
    symtab->free_ptr
-   possibly free_named_symtabs (symtab->filename);
  */
 
 struct symtab *
@@ -2699,12 +2678,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 */
 
@@ -2714,73 +2692,6 @@ allocate_symtab (char *filename, struct objfile *objfile)
 
   return (symtab);
 }
-
-struct partial_symtab *
-allocate_psymtab (char *filename, struct objfile *objfile)
-{
-  struct partial_symtab *psymtab;
-
-  if (objfile->free_psymtabs)
-    {
-      psymtab = objfile->free_psymtabs;
-      objfile->free_psymtabs = psymtab->next;
-    }
-  else
-    psymtab = (struct partial_symtab *)
-      obstack_alloc (&objfile->objfile_obstack,
-                    sizeof (struct partial_symtab));
-
-  memset (psymtab, 0, sizeof (struct partial_symtab));
-  psymtab->filename = obsavestring (filename, strlen (filename),
-                                   &objfile->objfile_obstack);
-  psymtab->symtab = NULL;
-
-  /* Prepend it to the psymtab list for the objfile it belongs to.
-     Psymtabs are searched in most recent inserted -> least recent
-     inserted order. */
-
-  psymtab->objfile = objfile;
-  psymtab->next = objfile->psymtabs;
-  objfile->psymtabs = psymtab;
-#if 0
-  {
-    struct partial_symtab **prev_pst;
-    psymtab->objfile = objfile;
-    psymtab->next = NULL;
-    prev_pst = &(objfile->psymtabs);
-    while ((*prev_pst) != NULL)
-      prev_pst = &((*prev_pst)->next);
-    (*prev_pst) = psymtab;
-  }
-#endif
-
-  return (psymtab);
-}
-
-void
-discard_psymtab (struct partial_symtab *pst)
-{
-  struct partial_symtab **prev_pst;
-
-  /* From dbxread.c:
-     Empty psymtabs happen as a result of header files which don't
-     have any symbols in them.  There can be a lot of them.  But this
-     check is wrong, in that a psymtab with N_SLINE entries but
-     nothing else is not empty, but we don't realize that.  Fixing
-     that without slowing things down might be tricky.  */
-
-  /* First, snip it out of the psymtab chain */
-
-  prev_pst = &(pst->objfile->psymtabs);
-  while ((*prev_pst) != pst)
-    prev_pst = &((*prev_pst)->next);
-  (*prev_pst) = pst->next;
-
-  /* Next, put it on a free list for recycling */
-
-  pst->next = pst->objfile->free_psymtabs;
-  pst->objfile->free_psymtabs = pst;
-}
 \f
 
 /* Reset all data structures in gdb which may contain references to symbol
@@ -2798,7 +2709,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);
 
@@ -2818,375 +2729,7 @@ clear_symtab_users_cleanup (void *ignore)
 {
   clear_symtab_users ();
 }
-
-/* clear_symtab_users_once:
-
-   This function is run after symbol reading, or from a cleanup.
-   If an old symbol table was obsoleted, the old symbol table
-   has been blown away, but the other GDB data structures that may
-   reference it have not yet been cleared or re-directed.  (The old
-   symtab was zapped, and the cleanup queued, in free_named_symtab()
-   below.)
-
-   This function can be queued N times as a cleanup, or called
-   directly; it will do all the work the first time, and then will be a
-   no-op until the next time it is queued.  This works by bumping a
-   counter at queueing time.  Much later when the cleanup is run, or at
-   the end of symbol processing (in case the cleanup is discarded), if
-   the queued count is greater than the "done-count", we do the work
-   and set the done-count to the queued count.  If the queued count is
-   less than or equal to the done-count, we just ignore the call.  This
-   is needed because reading a single .o file will often replace many
-   symtabs (one per .h file, for example), and we don't want to reset
-   the breakpoints N times in the user's face.
-
-   The reason we both queue a cleanup, and call it directly after symbol
-   reading, is because the cleanup protects us in case of errors, but is
-   discarded if symbol reading is successful.  */
-
-#if 0
-/* FIXME:  As free_named_symtabs is currently a big noop this function
-   is no longer needed.  */
-static void clear_symtab_users_once (void);
-
-static int clear_symtab_users_queued;
-static int clear_symtab_users_done;
-
-static void
-clear_symtab_users_once (void)
-{
-  /* Enforce once-per-`do_cleanups'-semantics */
-  if (clear_symtab_users_queued <= clear_symtab_users_done)
-    return;
-  clear_symtab_users_done = clear_symtab_users_queued;
-
-  clear_symtab_users ();
-}
-#endif
-
-/* Delete the specified psymtab, and any others that reference it.  */
-
-static void
-cashier_psymtab (struct partial_symtab *pst)
-{
-  struct partial_symtab *ps, *pprev = NULL;
-  int i;
-
-  /* Find its previous psymtab in the chain */
-  for (ps = pst->objfile->psymtabs; ps; ps = ps->next)
-    {
-      if (ps == pst)
-       break;
-      pprev = ps;
-    }
-
-  if (ps)
-    {
-      /* Unhook it from the chain.  */
-      if (ps == pst->objfile->psymtabs)
-       pst->objfile->psymtabs = ps->next;
-      else
-       pprev->next = ps->next;
-
-      /* FIXME, we can't conveniently deallocate the entries in the
-         partial_symbol lists (global_psymbols/static_psymbols) that
-         this psymtab points to.  These just take up space until all
-         the psymtabs are reclaimed.  Ditto the dependencies list and
-         filename, which are all in the objfile_obstack.  */
-
-      /* We need to cashier any psymtab that has this one as a dependency... */
-    again:
-      for (ps = pst->objfile->psymtabs; ps; ps = ps->next)
-       {
-         for (i = 0; i < ps->number_of_dependencies; i++)
-           {
-             if (ps->dependencies[i] == pst)
-               {
-                 cashier_psymtab (ps);
-                 goto again;   /* Must restart, chain has been munged. */
-               }
-           }
-       }
-    }
-}
-
-/* If a symtab or psymtab for filename NAME is found, free it along
-   with any dependent breakpoints, displays, etc.
-   Used when loading new versions of object modules with the "add-file"
-   command.  This is only called on the top-level symtab or psymtab's name;
-   it is not called for subsidiary files such as .h files.
-
-   Return value is 1 if we blew away the environment, 0 if not.
-   FIXME.  The return value appears to never be used.
-
-   FIXME.  I think this is not the best way to do this.  We should
-   work on being gentler to the environment while still cleaning up
-   all stray pointers into the freed symtab.  */
-
-int
-free_named_symtabs (char *name)
-{
-#if 0
-  /* FIXME:  With the new method of each objfile having it's own
-     psymtab list, this function needs serious rethinking.  In particular,
-     why was it ever necessary to toss psymtabs with specific compilation
-     unit filenames, as opposed to all psymtabs from a particular symbol
-     file?  -- fnf
-     Well, the answer is that some systems permit reloading of particular
-     compilation units.  We want to blow away any old info about these
-     compilation units, regardless of which objfiles they arrived in. --gnu.  */
-
-  struct symtab *s;
-  struct symtab *prev;
-  struct partial_symtab *ps;
-  struct blockvector *bv;
-  int blewit = 0;
-
-  /* We only wack things if the symbol-reload switch is set.  */
-  if (!symbol_reloading)
-    return 0;
-
-  /* Some symbol formats have trouble providing file names... */
-  if (name == 0 || *name == '\0')
-    return 0;
-
-  /* Look for a psymtab with the specified name.  */
-
-again2:
-  for (ps = partial_symtab_list; ps; ps = ps->next)
-    {
-      if (strcmp (name, ps->filename) == 0)
-       {
-         cashier_psymtab (ps); /* Blow it away...and its little dog, too.  */
-         goto again2;          /* Must restart, chain has been munged */
-       }
-    }
-
-  /* Look for a symtab with the specified name.  */
-
-  for (s = symtab_list; s; s = s->next)
-    {
-      if (strcmp (name, s->filename) == 0)
-       break;
-      prev = s;
-    }
-
-  if (s)
-    {
-      if (s == symtab_list)
-       symtab_list = s->next;
-      else
-       prev->next = s->next;
-
-      /* For now, queue a delete for all breakpoints, displays, etc., whether
-         or not they depend on the symtab being freed.  This should be
-         changed so that only those data structures affected are deleted.  */
-
-      /* But don't delete anything if the symtab is empty.
-         This test is necessary due to a bug in "dbxread.c" that
-         causes empty symtabs to be created for N_SO symbols that
-         contain the pathname of the object file.  (This problem
-         has been fixed in GDB 3.9x).  */
-
-      bv = BLOCKVECTOR (s);
-      if (BLOCKVECTOR_NBLOCKS (bv) > 2
-         || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
-         || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)))
-       {
-         complaint (&symfile_complaints, _("Replacing old symbols for `%s'"),
-                    name);
-         clear_symtab_users_queued++;
-         make_cleanup (clear_symtab_users_once, 0);
-         blewit = 1;
-       }
-      else
-       complaint (&symfile_complaints, _("Empty symbol table found for `%s'"),
-                  name);
-
-      free_symtab (s);
-    }
-  else
-    {
-      /* It is still possible that some breakpoints will be affected
-         even though no symtab was found, since the file might have
-         been compiled without debugging, and hence not be associated
-         with a symtab.  In order to handle this correctly, we would need
-         to keep a list of text address ranges for undebuggable files.
-         For now, we do nothing, since this is a fairly obscure case.  */
-      ;
-    }
-
-  /* FIXME, what about the minimal symbol table? */
-  return blewit;
-#else
-  return (0);
-#endif
-}
-\f
-/* Allocate and partially fill a partial symtab.  It will be
-   completely filled at the end of the symbol list.
-
-   FILENAME is the name of the symbol-file we are reading from. */
-
-struct partial_symtab *
-start_psymtab_common (struct objfile *objfile,
-                     struct section_offsets *section_offsets, char *filename,
-                     CORE_ADDR textlow, struct partial_symbol **global_syms,
-                     struct partial_symbol **static_syms)
-{
-  struct partial_symtab *psymtab;
-
-  psymtab = allocate_psymtab (filename, objfile);
-  psymtab->section_offsets = section_offsets;
-  psymtab->textlow = textlow;
-  psymtab->texthigh = psymtab->textlow;                /* default */
-  psymtab->globals_offset = global_syms - objfile->global_psymbols.list;
-  psymtab->statics_offset = static_syms - objfile->static_psymbols.list;
-  return (psymtab);
-}
 \f
-/* Helper function, initialises partial symbol structure and stashes 
-   it into objfile's bcache.  Note that our caching mechanism will
-   use all fields of struct partial_symbol to determine hash value of the
-   structure.  In other words, having two symbols with the same name but
-   different domain (or address) is possible and correct.  */
-
-static const struct partial_symbol *
-add_psymbol_to_bcache (char *name, int namelength, 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';
-    }
-  /* val and coreaddr are mutually exclusive, one of them *will* be zero */
-  if (val != 0)
-    {
-      SYMBOL_VALUE (&psymbol) = val;
-    }
-  else
-    {
-      SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
-    }
-  SYMBOL_SECTION (&psymbol) = 0;
-  SYMBOL_LANGUAGE (&psymbol) = language;
-  PSYMBOL_DOMAIN (&psymbol) = domain;
-  PSYMBOL_CLASS (&psymbol) = class;
-
-  SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
-
-  /* Stash the partial symbol away in the cache */
-  return bcache_full (&psymbol, sizeof (struct partial_symbol),
-                     objfile->psymbol_cache, added);
-}
-
-/* Helper function, adds partial symbol to the given partial symbol
-   list.  */
-
-static void
-append_psymbol_to_list (struct psymbol_allocation_list *list,
-                       const struct partial_symbol *psym,
-                       struct objfile *objfile)
-{
-  if (list->next >= list->list + list->size)
-    extend_psymbol_list (list, objfile);
-  *list->next++ = (struct partial_symbol *) psym;
-  OBJSTAT (objfile, n_psyms++);
-}
-
-/* Add a symbol with a long value to a psymtab.
-   Since one arg is a struct, we pass in a ptr and deref it (sigh).
-   Return the partial symbol that has been added.  */
-
-/* NOTE: carlton/2003-09-11: The reason why we return the partial
-   symbol is so that callers can get access to the symbol's demangled
-   name, which they don't have any cheap way to determine otherwise.
-   (Currenly, dwarf2read.c is the only file who uses that information,
-   though it's possible that other readers might in the future.)
-   Elena wasn't thrilled about that, and I don't blame her, but we
-   couldn't come up with a better way to get that information.  If
-   it's needed in other situations, we could consider breaking up
-   SYMBOL_SET_NAMES to provide access to the demangled name lookup
-   cache.  */
-
-const struct partial_symbol *
-add_psymbol_to_list (char *name, int namelength, domain_enum domain,
-                    enum address_class class,
-                    struct psymbol_allocation_list *list, 
-                    long val,  /* Value as a long */
-                    CORE_ADDR coreaddr,        /* Value as a CORE_ADDR */
-                    enum language language, struct objfile *objfile)
-{
-  const struct partial_symbol *psym;
-
-  int added;
-
-  /* Stash the partial symbol away in the cache */
-  psym = add_psymbol_to_bcache (name, namelength, domain, class,
-                               val, coreaddr, language, objfile, &added);
-
-  /* Do not duplicate global partial symbols.  */
-  if (list == &objfile->global_psymbols
-      && !added)
-    return psym;
-
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
-  append_psymbol_to_list (list, psym, objfile);
-  return psym;
-}
-
-/* Initialize storage for partial symbols.  */
-
-void
-init_psymbol_list (struct objfile *objfile, int total_symbols)
-{
-  /* Free any previously allocated psymbol lists.  */
-
-  if (objfile->global_psymbols.list)
-    {
-      xfree (objfile->global_psymbols.list);
-    }
-  if (objfile->static_psymbols.list)
-    {
-      xfree (objfile->static_psymbols.list);
-    }
-
-  /* Current best guess is that approximately a twentieth
-     of the total symbols (in a debugging file) are global or static
-     oriented symbols */
-
-  objfile->global_psymbols.size = total_symbols / 10;
-  objfile->static_psymbols.size = total_symbols / 10;
-
-  if (objfile->global_psymbols.size > 0)
-    {
-      objfile->global_psymbols.next =
-       objfile->global_psymbols.list = (struct partial_symbol **)
-       xmalloc ((objfile->global_psymbols.size
-                 * sizeof (struct partial_symbol *)));
-    }
-  if (objfile->static_psymbols.size > 0)
-    {
-      objfile->static_psymbols.next =
-       objfile->static_psymbols.list = (struct partial_symbol **)
-       xmalloc ((objfile->static_psymbols.size
-                 * sizeof (struct partial_symbol *)));
-    }
-}
-
 /* OVERLAYS:
    The following code implements an abstraction for debugging overlay sections.
 
@@ -3288,6 +2831,8 @@ overlay_invalidate_all (void)
 int
 section_is_mapped (struct obj_section *osect)
 {
+  struct gdbarch *gdbarch;
+
   if (osect == 0 || !section_is_overlay (osect))
     return 0;
 
@@ -3299,7 +2844,8 @@ section_is_mapped (struct obj_section *osect)
     case ovly_auto:            /* overlay debugging automatic */
       /* Unles there is a gdbarch_overlay_update function,
          there's really nothing useful to do here (can't really go auto)  */
-      if (gdbarch_overlay_update_p (current_gdbarch))
+      gdbarch = get_objfile_arch (osect->objfile);
+      if (gdbarch_overlay_update_p (gdbarch))
        {
          if (overlay_cache_invalid)
            {
@@ -3307,7 +2853,7 @@ section_is_mapped (struct obj_section *osect)
              overlay_cache_invalid = 0;
            }
          if (osect->ovly_mapped == -1)
-           gdbarch_overlay_update (current_gdbarch, osect);
+           gdbarch_overlay_update (gdbarch, osect);
        }
       /* fall thru to manual case */
     case ovly_on:              /* overlay debugging manual */
@@ -3495,6 +3041,7 @@ list_overlays_command (char *args, int from_tty)
     ALL_OBJSECTIONS (objfile, osect)
       if (section_is_mapped (osect))
       {
+       struct gdbarch *gdbarch = get_objfile_arch (objfile);
        const char *name;
        bfd_vma lma, vma;
        int size;
@@ -3505,13 +3052,13 @@ list_overlays_command (char *args, int from_tty)
        name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
 
        printf_filtered ("Section %s, loaded at ", name);
-       fputs_filtered (paddress (lma), gdb_stdout);
+       fputs_filtered (paddress (gdbarch, lma), gdb_stdout);
        puts_filtered (" - ");
-       fputs_filtered (paddress (lma + size), gdb_stdout);
+       fputs_filtered (paddress (gdbarch, lma + size), gdb_stdout);
        printf_filtered (", mapped at ");
-       fputs_filtered (paddress (vma), gdb_stdout);
+       fputs_filtered (paddress (gdbarch, vma), gdb_stdout);
        puts_filtered (" - ");
-       fputs_filtered (paddress (vma + size), gdb_stdout);
+       fputs_filtered (paddress (gdbarch, vma + size), gdb_stdout);
        puts_filtered ("\n");
 
        nmapped++;
@@ -3636,8 +3183,10 @@ overlay_off_command (char *args, int from_tty)
 static void
 overlay_load_command (char *args, int from_tty)
 {
-  if (gdbarch_overlay_update_p (current_gdbarch))
-    gdbarch_overlay_update (current_gdbarch, NULL);
+  struct gdbarch *gdbarch = get_current_arch ();
+
+  if (gdbarch_overlay_update_p (gdbarch))
+    gdbarch_overlay_update (gdbarch, NULL);
   else
     error (_("This target does not know how to read its overlay state."));
 }
@@ -3708,8 +3257,6 @@ enum ovly_index
   {
     VMA, SIZE, LMA, MAPPED
   };
-#define TARGET_LONG_BYTES (gdbarch_long_bit (current_gdbarch) \
-                           / TARGET_CHAR_BIT)
 
 /* Throw away the cached copy of _ovly_table */
 static void
@@ -3735,19 +3282,19 @@ simple_free_overlay_region_table (void)
 }
 #endif
 
-/* Read an array of ints from the target into a local buffer.
+/* Read an array of ints of size SIZE from the target into a local buffer.
    Convert to host order.  int LEN is number of ints  */
 static void
-read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len)
+read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr,
+                       int len, int size, enum bfd_endian byte_order)
 {
   /* FIXME (alloca): Not safe if array is very large. */
-  gdb_byte *buf = alloca (len * TARGET_LONG_BYTES);
+  gdb_byte *buf = alloca (len * size);
   int i;
 
-  read_memory (memaddr, buf, len * TARGET_LONG_BYTES);
+  read_memory (memaddr, buf, len * size);
   for (i = 0; i < len; i++)
-    myaddr[i] = extract_unsigned_integer (TARGET_LONG_BYTES * i + buf,
-                                         TARGET_LONG_BYTES);
+    myaddr[i] = extract_unsigned_integer (size * i + buf, size, byte_order);
 }
 
 /* Find and grab a copy of the target _ovly_table
@@ -3756,6 +3303,9 @@ static int
 simple_read_overlay_table (void)
 {
   struct minimal_symbol *novlys_msym, *ovly_table_msym;
+  struct gdbarch *gdbarch;
+  int word_size;
+  enum bfd_endian byte_order;
 
   simple_free_overlay_table ();
   novlys_msym = lookup_minimal_symbol ("_novlys", NULL, NULL);
@@ -3776,13 +3326,18 @@ simple_read_overlay_table (void)
       return 0;
     }
 
-  cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (novlys_msym), 4);
+  gdbarch = get_objfile_arch (msymbol_objfile (ovly_table_msym));
+  word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+  byte_order = gdbarch_byte_order (gdbarch);
+
+  cache_novlys = read_memory_integer (SYMBOL_VALUE_ADDRESS (novlys_msym),
+                                     4, byte_order);
   cache_ovly_table
     = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
   cache_ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym);
   read_target_long_array (cache_ovly_table_base,
                           (unsigned int *) cache_ovly_table,
-                          cache_novlys * 4);
+                          cache_novlys * 4, word_size, byte_order);
 
   return 1;                    /* SUCCESS */
 }
@@ -3794,13 +3349,22 @@ static int
 simple_read_overlay_region_table (void)
 {
   struct minimal_symbol *msym;
+  struct gdbarch *gdbarch;
+  int word_size;
+  enum bfd_endian byte_order;
 
   simple_free_overlay_region_table ();
   msym = lookup_minimal_symbol ("_novly_regions", NULL, NULL);
-  if (msym != NULL)
-    cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym), 4);
-  else
+  if (msym == NULL)
     return 0;                  /* failure */
+
+  gdbarch = get_objfile_arch (msymbol_objfile (msym));
+  word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+  byte_order = gdbarch_byte_order (gdbarch);
+
+  cache_novly_regions = read_memory_integer (SYMBOL_VALUE_ADDRESS (msym),
+                                            4, byte_order);
+
   cache_ovly_region_table = (void *) xmalloc (cache_novly_regions * 12);
   if (cache_ovly_region_table != NULL)
     {
@@ -3810,7 +3374,8 @@ simple_read_overlay_region_table (void)
          cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym);
          read_target_long_array (cache_ovly_region_table_base,
                                  (unsigned int *) cache_ovly_region_table,
-                                 cache_novly_regions * 3);
+                                 cache_novly_regions * 3,
+                                 word_size, byte_order);
        }
       else
        return 0;               /* failure */
@@ -3835,6 +3400,9 @@ simple_overlay_update_1 (struct obj_section *osect)
   int i, size;
   bfd *obfd = osect->objfile->obfd;
   asection *bsect = osect->the_bfd_section;
+  struct gdbarch *gdbarch = get_objfile_arch (osect->objfile);
+  int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   size = bfd_get_section_size (osect->the_bfd_section);
   for (i = 0; i < cache_novlys; i++)
@@ -3842,8 +3410,9 @@ simple_overlay_update_1 (struct obj_section *osect)
        && 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,
-                               (unsigned int *) cache_ovly_table[i], 4);
+       read_target_long_array (cache_ovly_table_base + i * word_size,
+                               (unsigned int *) cache_ovly_table[i],
+                               4, word_size, byte_order);
        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 */ )
@@ -3921,6 +3490,27 @@ symfile_dummy_outputs (bfd *abfd, asection *sectp, void *dummy)
   sectp->output_offset = 0;
 }
 
+/* Default implementation for sym_relocate.  */
+
+
+bfd_byte *
+default_symfile_relocate (struct objfile *objfile, asection *sectp,
+                          bfd_byte *buf)
+{
+  bfd *abfd = objfile->obfd;
+
+  /* We're only interested in sections with relocation
+     information.  */
+  if ((sectp->flags & SEC_RELOC) == 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);
+}
+
 /* 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.
@@ -3936,18 +3526,12 @@ symfile_dummy_outputs (bfd *abfd, asection *sectp, void *dummy)
    debug section.  */
 
 bfd_byte *
-symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
+symfile_relocate_debug_section (struct objfile *objfile,
+                                asection *sectp, bfd_byte *buf)
 {
-  /* We're only interested in sections with relocation
-     information.  */
-  if ((sectp->flags & SEC_RELOC) == 0)
-    return NULL;
+  gdb_assert (objfile->sf->sym_relocate);
 
-  /* 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);
+  return (*objfile->sf->sym_relocate) (objfile, sectp, buf);
 }
 
 struct symfile_segment_data *
@@ -3996,7 +3580,7 @@ symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
 
   /* It doesn't make sense to call this function unless you have some
      segment base addresses.  */
-  gdb_assert (segment_bases > 0);
+  gdb_assert (num_segment_bases > 0);
 
   /* If we do not have segment mappings for the object file, we
      can not relocate it by segments.  */
@@ -4146,21 +3730,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);
 }
This page took 0.049444 seconds and 4 git commands to generate.