* target.h (struct section_table): Rename to ...
[deliverable/binutils-gdb.git] / gdb / symfile.c
index ddd198d77ed60213502baf2840c01f081189af96..ea97d3c5117bdfb8f85ad9dc48292a7f9a37ad3c 100644 (file)
@@ -1,7 +1,8 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
@@ -9,7 +10,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,9 +19,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "bfdlink.h"
@@ -38,7 +37,8 @@
 #include "language.h"
 #include "complaints.h"
 #include "demangle.h"
-#include "inferior.h"          /* for write_pc */
+#include "inferior.h"
+#include "regcache.h"
 #include "filenames.h"         /* for DOSish file names */
 #include "gdb-stabs.h"
 #include "gdb_obstack.h"
 #include "block.h"
 #include "observer.h"
 #include "exec.h"
+#include "parser-defs.h"
+#include "varobj.h"
+#include "elf-bfd.h"
+#include "solib.h"
+#include "remote.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -59,9 +64,6 @@
 #include <time.h>
 #include <sys/time.h>
 
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
 
 int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num);
 void (*deprecated_show_load_progress) (const char *section,
@@ -71,7 +73,6 @@ void (*deprecated_show_load_progress) (const char *section,
                            unsigned long total_size);
 void (*deprecated_pre_add_symbol_hook) (const char *);
 void (*deprecated_post_add_symbol_hook) (void);
-void (*deprecated_target_new_objfile_hook) (struct objfile *);
 
 static void clear_symtab_users_cleanup (void *ignore);
 
@@ -89,8 +90,6 @@ static int simple_read_overlay_region_table (void);
 static void simple_free_overlay_region_table (void);
 #endif
 
-static void set_initial_language (void);
-
 static void load_command (char *, int);
 
 static void symbol_file_add_main_1 (char *args, int from_tty, int flags);
@@ -107,14 +106,12 @@ bfd *symfile_bfd_open (char *);
 
 int get_section_index (struct objfile *, char *);
 
-static void find_sym_fns (struct objfile *);
+static struct sym_fns *find_sym_fns (bfd *);
 
 static void decrement_reading_symtab (void *);
 
 static void overlay_invalidate_all (void);
 
-static int overlay_is_mapped (struct obj_section *);
-
 void list_overlays_command (char *, int);
 
 void map_overlay_command (char *, int);
@@ -147,6 +144,8 @@ 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);
+
 void _initialize_symfile (void);
 
 /* List of all available sym_fns.  On gdb startup, each object file reader
@@ -172,6 +171,12 @@ 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
@@ -364,11 +369,11 @@ copy_section_addr_info (struct section_addr_info *addrs)
    an existing section table. */
 
 extern struct section_addr_info *
-build_section_addr_info_from_section_table (const struct section_table *start,
-                                            const struct section_table *end)
+build_section_addr_info_from_section_table (const struct target_section *start,
+                                            const struct target_section *end)
 {
   struct section_addr_info *sap;
-  const struct section_table *stp;
+  const struct target_section *stp;
   int oidx;
 
   sap = alloc_section_addr_info (end - start);
@@ -431,12 +436,19 @@ init_objfile_sect_indices (struct objfile *objfile)
   /* This is where things get really weird...  We MUST have valid
      indices for the various sect_index_* members or gdb will abort.
      So if for example, there is no ".text" section, we have to
-     accomodate that.  Except when explicitly adding symbol files at
-     some address, section_offsets contains nothing but zeros, so it
-     doesn't matter which slot in section_offsets the individual
-     sect_index_* members index into.  So if they are all zero, it is
-     safe to just point all the currently uninitialized indices to the
-     first slot. */
+     accomodate that.  First, check for a file with the standard
+     one or two segments.  */
+
+  symfile_find_segment_sections (objfile);
+
+  /* Except when explicitly adding symbol files at some address,
+     section_offsets contains nothing but zeros, so it doesn't matter
+     which slot in section_offsets the individual sect_index_* members
+     index into.  So if they are all zero, it is safe to just point
+     all the currently uninitialized indices to the first slot.  But
+     beware: if this is the main executable, it may be relocated
+     later, e.g. by the remote qOffsets packet, and then this will
+     be wrong!  That's why we try segments first.  */
 
   for (i = 0; i < objfile->num_sections; i++)
     {
@@ -469,15 +481,16 @@ struct place_section_arg
 /* Find a unique offset to use for loadable section SECT if
    the user did not provide an offset.  */
 
-void
+static void
 place_section (bfd *abfd, asection *sect, void *obj)
 {
   struct place_section_arg *arg = obj;
   CORE_ADDR *offsets = arg->offsets->offsets, start_addr;
   int done;
+  ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
 
-  /* We are only interested in loadable sections.  */
-  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+  /* We are only interested in allocated sections.  */
+  if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
     return;
 
   /* If the user specified an offset, honor it.  */
@@ -485,11 +498,11 @@ place_section (bfd *abfd, asection *sect, void *obj)
     return;
 
   /* Otherwise, let's try to find a place for the section.  */
+  start_addr = (arg->lowest + align - 1) & -align;
+
   do {
     asection *cur_sec;
-    ULONGEST align = 1 << bfd_get_section_alignment (abfd, sect);
 
-    start_addr = (arg->lowest + align - 1) & -align;
     done = 1;
 
     for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
@@ -501,13 +514,8 @@ place_section (bfd *abfd, asection *sect, void *obj)
        if (cur_sec == sect)
          continue;
 
-       /* We can only conflict with loadable sections.  */
-       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_LOAD) == 0)
-         continue;
-
-       /* We do not expect this to happen; just ignore sections in a
-          relocatable file with an assigned VMA.  */
-       if (bfd_section_vma (abfd, cur_sec) != 0)
+       /* We can only conflict with allocated sections.  */
+       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
          continue;
 
        /* If the section offset is 0, either the section has not been placed
@@ -523,7 +531,7 @@ place_section (bfd *abfd, asection *sect, void *obj)
            start_addr = offsets[indx] + bfd_get_section_size (cur_sec);
            start_addr = (start_addr + align - 1) & -align;
            done = 0;
-           continue;
+           break;
          }
 
        /* Otherwise, we appear to be OK.  So far.  */
@@ -533,8 +541,6 @@ place_section (bfd *abfd, asection *sect, void *obj)
 
   offsets[sect->index] = start_addr;
   arg->lowest = start_addr + bfd_get_section_size (sect);
-
-  exec_set_section_address (bfd_get_filename (abfd), sect->index, start_addr);
 }
 
 /* Parse the user's idea of an offset for dynamic linking, into our idea
@@ -580,9 +586,64 @@ default_symfile_offsets (struct objfile *objfile,
   if ((bfd_get_file_flags (objfile->obfd) & (EXEC_P | DYNAMIC)) == 0)
     {
       struct place_section_arg arg;
-      arg.offsets = objfile->section_offsets;
-      arg.lowest = 0;
-      bfd_map_over_sections (objfile->obfd, place_section, &arg);
+      bfd *abfd = objfile->obfd;
+      asection *cur_sec;
+      CORE_ADDR lowest = 0;
+
+      for (cur_sec = abfd->sections; cur_sec != NULL; cur_sec = cur_sec->next)
+       /* We do not expect this to happen; just skip this step if the
+          relocatable file has a section with an assigned VMA.  */
+       if (bfd_section_vma (abfd, cur_sec) != 0)
+         break;
+
+      if (cur_sec == NULL)
+       {
+         CORE_ADDR *offsets = objfile->section_offsets->offsets;
+
+         /* Pick non-overlapping offsets for sections the user did not
+            place explicitly.  */
+         arg.offsets = objfile->section_offsets;
+         arg.lowest = 0;
+         bfd_map_over_sections (objfile->obfd, place_section, &arg);
+
+         /* Correctly filling in the section offsets is not quite
+            enough.  Relocatable files have two properties that
+            (most) shared objects do not:
+
+            - Their debug information will contain relocations.  Some
+            shared libraries do also, but many do not, so this can not
+            be assumed.
+
+            - If there are multiple code sections they will be loaded
+            at different relative addresses in memory than they are
+            in the objfile, since all sections in the file will start
+            at address zero.
+
+            Because GDB has very limited ability to map from an
+            address in debug info to the correct code section,
+            it relies on adding SECT_OFF_TEXT to things which might be
+            code.  If we clear all the section offsets, and set the
+            section VMAs instead, then symfile_relocate_debug_section
+            will return meaningful debug information pointing at the
+            correct sections.
+
+            GDB has too many different data structures for section
+            addresses - a bfd, objfile, and so_list all have section
+            tables, as does exec_ops.  Some of these could probably
+            be eliminated.  */
+
+         for (cur_sec = abfd->sections; cur_sec != NULL;
+              cur_sec = cur_sec->next)
+           {
+             if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
+               continue;
+
+             bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+             exec_set_section_address (bfd_get_filename (abfd), cur_sec->index,
+                                       offsets[cur_sec->index]);
+             offsets[cur_sec->index] = 0;
+           }
+       }
     }
 
   /* Remember the bfd indexes for the .text, .data, .bss and
@@ -591,6 +652,70 @@ default_symfile_offsets (struct objfile *objfile,
 }
 
 
+/* Divide the file into segments, which are individual relocatable units.
+   This is the default version of the sym_fns.sym_segments function for
+   symbol readers that do not have an explicit representation of segments.
+   It assumes that object files do not have segments, and fully linked
+   files have a single segment.  */
+
+struct symfile_segment_data *
+default_symfile_segments (bfd *abfd)
+{
+  int num_sections, i;
+  asection *sect;
+  struct symfile_segment_data *data;
+  CORE_ADDR low, high;
+
+  /* Relocatable files contain enough information to position each
+     loadable section independently; they should not be relocated
+     in segments.  */
+  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) == 0)
+    return NULL;
+
+  /* Make sure there is at least one loadable section in the file.  */
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    {
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+       continue;
+
+      break;
+    }
+  if (sect == NULL)
+    return NULL;
+
+  low = bfd_get_section_vma (abfd, sect);
+  high = low + bfd_get_section_size (sect);
+
+  data = XZALLOC (struct symfile_segment_data);
+  data->num_segments = 1;
+  data->segment_bases = XCALLOC (1, CORE_ADDR);
+  data->segment_sizes = XCALLOC (1, CORE_ADDR);
+
+  num_sections = bfd_count_sections (abfd);
+  data->segment_info = XCALLOC (num_sections, int);
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      CORE_ADDR vma;
+
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+       continue;
+
+      vma = bfd_get_section_vma (abfd, sect);
+      if (vma < low)
+       low = vma;
+      if (vma + bfd_get_section_size (sect) > high)
+       high = vma + bfd_get_section_size (sect);
+
+      data->segment_info[i] = 1;
+    }
+
+  data->segment_bases[0] = low;
+  data->segment_sizes[0] = high - low;
+
+  return data;
+}
+
 /* Process a symbol file, as either the main file or as a dynamically
    loaded file.
 
@@ -637,7 +762,7 @@ syms_from_objfile (struct objfile *objfile,
   gdb_assert (! (addrs && offsets));
 
   init_entry_point_info (objfile);
-  find_sym_fns (objfile);
+  objfile->sf = find_sym_fns (objfile->obfd);
 
   if (objfile->sf == NULL)
     return;    /* No symbols. */
@@ -702,18 +827,13 @@ syms_from_objfile (struct objfile *objfile,
        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);
-      else
-       if ((bfd_get_section_flags (objfile->obfd, lower_sect) & SEC_CODE) == 0)
-         warning (_("Lowest section in %s is %s at %s"),
-                  objfile->name,
-                  bfd_section_name (objfile->obfd, lower_sect),
-                  paddr (bfd_section_vma (objfile->obfd, lower_sect)));
-      if (lower_sect != NULL)
-       lower_offset = bfd_section_vma (objfile->obfd, lower_sect);
+       {
+         warning (_("no loadable sections found in added symbol-file %s"),
+                  objfile->name);
+         lower_offset = 0;
+       }
       else
-       lower_offset = 0;
+       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
@@ -775,74 +895,12 @@ syms_from_objfile (struct objfile *objfile,
       init_objfile_sect_indices (objfile);
     }
 
-#ifndef DEPRECATED_IBM6000_TARGET
-  /* This is a SVR4/SunOS specific hack, I think.  In any event, it
-     screws RS/6000.  sym_offsets should be doing this sort of thing,
-     because it knows the mapping between bfd sections and
-     section_offsets.  */
-  /* This is a hack.  As far as I can tell, section offsets are not
-     target dependent.  They are all set to addr with a couple of
-     exceptions.  The exceptions are sysvr4 shared libraries, whose
-     offsets are kept in solib structures anyway and rs6000 xcoff
-     which handles shared libraries in a completely unique way.
-
-     Section offsets are built similarly, except that they are built
-     by adding addr in all cases because there is no clear mapping
-     from section_offsets into actual sections.  Note that solib.c
-     has a different algorithm for finding section offsets.
-
-     These should probably all be collapsed into some target
-     independent form of shared library support.  FIXME.  */
-
-  if (addrs)
-    {
-      struct obj_section *s;
-
-       /* Map section offsets in "addr" back to the object's
-          sections by comparing the section names with bfd's
-          section names.  Then adjust the section address by
-          the offset. */ /* for gdb/13815 */
-
-      ALL_OBJFILE_OSECTIONS (objfile, s)
-       {
-         CORE_ADDR s_addr = 0;
-         int i;
-
-           for (i = 0;
-                !s_addr && i < addrs->num_sections && addrs->other[i].name;
-                i++)
-             if (strcmp (bfd_section_name (s->objfile->obfd,
-                                           s->the_bfd_section),
-                         addrs->other[i].name) == 0)
-               s_addr = addrs->other[i].addr; /* end added for gdb/13815 */
-
-         s->addr -= s->offset;
-         s->addr += s_addr;
-         s->endaddr -= s->offset;
-         s->endaddr += s_addr;
-         s->offset += s_addr;
-       }
-    }
-#endif /* not DEPRECATED_IBM6000_TARGET */
-
   (*objfile->sf->sym_read) (objfile, mainline);
 
-  /* Don't allow char * to have a typename (else would get caddr_t).
-     Ditto void *.  FIXME: Check whether this is now done by all the
-     symbol readers themselves (many of them now do), and if so remove
-     it from here.  */
-
-  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
-  TYPE_NAME (lookup_pointer_type (builtin_type_void)) = 0;
-
-  /* Mark the objfile has having had initial symbol read attempted.  Note
-     that this does not mean we found any symbols... */
-
-  objfile->flags |= OBJF_SYMS;
-
   /* Discard cleanups as symbol reading was successful.  */
 
   discard_cleanups (old_chain);
+  xfree (local_addr);
 }
 
 /* Perform required actions after either reading in the initial
@@ -865,7 +923,7 @@ new_symfile_objfile (struct objfile *objfile, int mainline, int verbo)
     }
   else
     {
-      breakpoint_re_set ();
+      breakpoint_re_set_objfile (objfile);
     }
 
   /* We're done reading the symbol file; finish off complaints.  */
@@ -898,7 +956,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
 {
   struct objfile *objfile;
   struct partial_symtab *psymtab;
-  char *debugfile;
+  char *debugfile = NULL;
   struct section_addr_info *orig_addrs = NULL;
   struct cleanup *my_cleanups;
   const char *name = bfd_get_filename (abfd);
@@ -911,7 +969,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
   if ((have_full_symbols () || have_partial_symbols ())
       && mainline
       && from_tty
-      && !query ("Load new symbol table from \"%s\"? ", name))
+      && !query (_("Load new symbol table from \"%s\"? "), name))
     error (_("Not confirmed."));
 
   objfile = allocate_objfile (abfd, flags);
@@ -932,9 +990,12 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
        deprecated_pre_add_symbol_hook (name);
       else
        {
-         printf_unfiltered (_("Reading symbols from %s..."), name);
-         wrap_here ("");
-         gdb_flush (gdb_stdout);
+          if (print_symbol_loading)
+           {
+             printf_unfiltered (_("Reading symbols from %s..."), name);
+             wrap_here ("");
+             gdb_flush (gdb_stdout);
+           }
        }
     }
   syms_from_objfile (objfile, addrs, offsets, num_offsets,
@@ -947,7 +1008,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
 
   if ((flags & OBJF_READNOW) || readnow_symbol_files)
     {
-      if (from_tty || info_verbose)
+      if ((from_tty || info_verbose) && print_symbol_loading)
        {
          printf_unfiltered (_("expanding to full symbols..."));
          wrap_here ("");
@@ -962,7 +1023,11 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
        }
     }
 
-  debugfile = find_separate_debug_file (objfile);
+  /* 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)
@@ -985,14 +1050,15 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
       xfree (debugfile);
     }
 
-  if (!have_partial_symbols () && !have_full_symbols ())
+  if (!have_partial_symbols () && !have_full_symbols ()
+      && print_symbol_loading)
     {
       wrap_here ("");
-      printf_filtered (_("(no debugging symbols found)"));
+      printf_unfiltered (_("(no debugging symbols found)"));
       if (from_tty || info_verbose)
-        printf_filtered ("...");
+        printf_unfiltered ("...");
       else
-        printf_filtered ("\n");
+        printf_unfiltered ("\n");
       wrap_here ("");
     }
 
@@ -1002,7 +1068,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
        deprecated_post_add_symbol_hook ();
       else
        {
-         printf_unfiltered (_("done.\n"));
+         if (print_symbol_loading)
+           printf_unfiltered (_("done.\n"));
        }
     }
 
@@ -1018,8 +1085,7 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, int from_tty,
 
   new_symfile_objfile (objfile, mainline, from_tty);
 
-  if (deprecated_target_new_objfile_hook)
-    deprecated_target_new_objfile_hook (objfile);
+  observer_notify_new_objfile (objfile);
 
   bfd_cache_close_all ();
   return (objfile);
@@ -1085,22 +1151,119 @@ symbol_file_clear (int from_tty)
 {
   if ((have_full_symbols () || have_partial_symbols ())
       && from_tty
-      && !query ("Discard symbol table from `%s'? ",
-                symfile_objfile->name))
+      && (symfile_objfile
+         ? !query (_("Discard symbol table from `%s'? "),
+                   symfile_objfile->name)
+         : !query (_("Discard symbol table? "))))
     error (_("Not confirmed."));
-    free_all_objfiles ();
-
-    /* solib descriptors may have handles to objfiles.  Since their
-       storage has just been released, we'd better wipe the solib
-       descriptors as well.
-     */
-#if defined(SOLIB_RESTART)
-    SOLIB_RESTART ();
-#endif
 
-    symfile_objfile = NULL;
-    if (from_tty)
-      printf_unfiltered (_("No symbol file now.\n"));
+  free_all_objfiles ();
+
+  /* solib descriptors may have handles to objfiles.  Since their
+     storage has just been released, we'd better wipe the solib
+     descriptors as well.  */
+  no_shared_libraries (NULL, from_tty);
+
+  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 *
@@ -1138,23 +1301,27 @@ static int
 separate_debug_file_exists (const char *name, unsigned long crc)
 {
   unsigned long file_crc = 0;
-  int fd;
-  char buffer[8*1024];
+  bfd *abfd;
+  gdb_byte buffer[8*1024];
   int count;
 
-  fd = open (name, O_RDONLY | O_BINARY);
-  if (fd < 0)
+  if (remote_filename_p (name))
+    abfd = remote_bfd_open (name, gnutarget);
+  else
+    abfd = bfd_openr (name, gnutarget);
+
+  if (!abfd)
     return 0;
 
-  while ((count = read (fd, buffer, sizeof (buffer))) > 0)
+  while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0)
     file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
 
-  close (fd);
+  bfd_close (abfd);
 
   return crc == file_crc;
 }
 
-static char *debug_file_directory = NULL;
+char *debug_file_directory = NULL;
 static void
 show_debug_file_directory (struct ui_file *file, int from_tty,
                           struct cmd_list_element *c, const char *value)
@@ -1176,9 +1343,29 @@ find_separate_debug_file (struct objfile *objfile)
   char *dir;
   char *debugfile;
   char *name_copy;
+  char *canon_name;
   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);
 
@@ -1243,6 +1430,30 @@ find_separate_debug_file (struct objfile *objfile)
       return xstrdup (debugfile);
     }
 
+  /* 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));
+      strcat (debugfile, "/");
+      strcat (debugfile, basename);
+
+      if (separate_debug_file_exists (debugfile, crc32))
+       {
+         xfree (canon_name);
+         xfree (basename);
+         xfree (dir);
+         return xstrdup (debugfile);
+       }
+    }
+  
+  if (canon_name)
+    xfree (canon_name);
+
   xfree (basename);
   xfree (dir);
   return NULL;
@@ -1274,14 +1485,11 @@ symbol_file_command (char *args, int from_tty)
     }
   else
     {
-      char **argv = buildargv (args);
+      char **argv = gdb_buildargv (args);
       int flags = OBJF_USERLOADED;
       struct cleanup *cleanups;
       char *name = NULL;
 
-      if (argv == NULL)
-       nomem (0);
-
       cleanups = make_cleanup_freeargv (argv);
       while (*argv != NULL)
        {
@@ -1316,7 +1524,7 @@ symbol_file_command (char *args, int from_tty)
    stabs we find, but we can't do that until later when we read in
    full symbols.  */
 
-static void
+void
 set_initial_language (void)
 {
   struct partial_symtab *pst;
@@ -1351,18 +1559,40 @@ symfile_bfd_open (char *name)
   int desc;
   char *absolute_name;
 
+  if (remote_filename_p (name))
+    {
+      name = xstrdup (name);
+      sym_bfd = remote_bfd_open (name, gnutarget);
+      if (!sym_bfd)
+       {
+         make_cleanup (xfree, name);
+         error (_("`%s': can't open to read symbols: %s."), name,
+                bfd_errmsg (bfd_get_error ()));
+       }
+
+      if (!bfd_check_format (sym_bfd, bfd_object))
+       {
+         bfd_close (sym_bfd);
+         make_cleanup (xfree, name);
+         error (_("`%s': can't read symbols: %s."), name,
+                bfd_errmsg (bfd_get_error ()));
+       }
+
+      return sym_bfd;
+    }
+
   name = tilde_expand (name);  /* Returns 1st new malloc'd copy.  */
 
   /* Look down path for it, allocate 2nd new malloc'd copy.  */
   desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, name,
-               O_RDONLY | O_BINARY, 0, &absolute_name);
+               O_RDONLY | O_BINARY, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
   if (desc < 0)
     {
       char *exename = alloca (strlen (name) + 5);
       strcat (strcpy (exename, name), ".exe");
       desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename,
-                   O_RDONLY | O_BINARY, 0, &absolute_name);
+                   O_RDONLY | O_BINARY, &absolute_name);
     }
 #endif
   if (desc < 0)
@@ -1381,7 +1611,7 @@ symfile_bfd_open (char *name)
     {
       close (desc);
       make_cleanup (xfree, name);
-      error (_("\"%s\": can't open to read symbols: %s."), name,
+      error (_("`%s': can't open to read symbols: %s."), name,
             bfd_errmsg (bfd_get_error ()));
     }
   bfd_set_cacheable (sym_bfd, 1);
@@ -1393,7 +1623,7 @@ symfile_bfd_open (char *name)
          with the bfd).  */
       bfd_close (sym_bfd);     /* This also closes desc.  */
       make_cleanup (xfree, name);
-      error (_("\"%s\": can't read symbols: %s."), name,
+      error (_("`%s': can't read symbols: %s."), name,
             bfd_errmsg (bfd_get_error ()));
     }
 
@@ -1431,29 +1661,23 @@ add_symtab_fns (struct sym_fns *sf)
    struct sym_fns in the objfile structure, that contains cached
    information about the symbol file.  */
 
-static void
-find_sym_fns (struct objfile *objfile)
+static struct sym_fns *
+find_sym_fns (bfd *abfd)
 {
   struct sym_fns *sf;
-  enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd);
-  char *our_target = bfd_get_target (objfile->obfd);
+  enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
 
   if (our_flavour == bfd_target_srec_flavour
       || our_flavour == bfd_target_ihex_flavour
       || our_flavour == bfd_target_tekhex_flavour)
-    return;    /* No symbols.  */
+    return NULL;       /* No symbols.  */
 
   for (sf = symtab_fns; sf != NULL; sf = sf->next)
-    {
-      if (our_flavour == sf->sym_flavour)
-       {
-         objfile->sf = sf;
-         return;
-       }
-    }
+    if (our_flavour == sf->sym_flavour)
+      return sf;
 
   error (_("I'm sorry, Dave, I can't do that.  Symbol format `%s' unknown."),
-        bfd_get_target (objfile->obfd));
+        bfd_get_target (abfd));
 }
 \f
 
@@ -1462,8 +1686,48 @@ find_sym_fns (struct objfile *objfile)
 static void
 load_command (char *arg, int from_tty)
 {
+  /* The user might be reloading because the binary has changed.  Take
+     this opportunity to check.  */
+  reopen_exec_file ();
+  reread_symbols ();
+
   if (arg == NULL)
-    arg = get_exec_file (1);
+    {
+      char *parg;
+      int count = 0;
+
+      parg = arg = get_exec_file (1);
+
+      /* Count how many \ " ' tab space there are in the name.  */
+      while ((parg = strpbrk (parg, "\\\"'\t ")))
+       {
+         parg++;
+         count++;
+       }
+
+      if (count)
+       {
+         /* We need to quote this string so buildargv can pull it apart.  */
+         char *temp = xmalloc (strlen (arg) + count + 1 );
+         char *ptemp = temp;
+         char *prev;
+
+         make_cleanup (xfree, temp);
+
+         prev = parg = arg;
+         while ((parg = strpbrk (parg, "\\\"'\t ")))
+           {
+             strncpy (ptemp, prev, parg - prev);
+             ptemp += parg - prev;
+             prev = parg++;
+             *ptemp++ = '\\';
+           }
+         strcpy (ptemp, prev);
+
+         arg = temp;
+       }
+    }
+
   target_load (arg, from_tty);
 
   /* After re-loading the executable, we don't really know which
@@ -1480,15 +1744,6 @@ load_command (char *arg, int from_tty)
    we don't want to run a subprocess.  On the other hand, I'm not sure how
    performance compares.  */
 
-static int download_write_size = 512;
-static void
-show_download_write_size (struct ui_file *file, int from_tty,
-                         struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file, _("\
-The write size used when downloading a program is %s.\n"),
-                   value);
-}
 static int validate_download = 0;
 
 /* Callback service function for generic_load (bfd_map_over_sections).  */
@@ -1504,139 +1759,193 @@ add_section_size_callback (bfd *abfd, asection *asec, void *data)
 /* Opaque data for load_section_callback.  */
 struct load_section_data {
   unsigned long load_offset;
+  struct load_progress_data *progress_data;
+  VEC(memory_write_request_s) *requests;
+};
+
+/* Opaque data for load_progress.  */
+struct load_progress_data {
+  /* Cumulative data.  */
   unsigned long write_count;
   unsigned long data_count;
   bfd_size_type total_size;
 };
 
+/* Opaque data for load_progress for a single section.  */
+struct load_progress_section_data {
+  struct load_progress_data *cumulative;
+
+  /* Per-section data.  */
+  const char *section_name;
+  ULONGEST section_sent;
+  ULONGEST section_size;
+  CORE_ADDR lma;
+  gdb_byte *buffer;
+};
+
+/* Target write callback routine for progress reporting.  */
+
+static void
+load_progress (ULONGEST bytes, void *untyped_arg)
+{
+  struct load_progress_section_data *args = untyped_arg;
+  struct load_progress_data *totals;
+
+  if (args == NULL)
+    /* Writing padding data.  No easy way to get at the cumulative
+       stats, so just ignore this.  */
+    return;
+
+  totals = args->cumulative;
+
+  if (bytes == 0 && args->section_sent == 0)
+    {
+      /* 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));
+      return;
+    }
+
+  if (validate_download)
+    {
+      /* Broken memories and broken monitors manifest themselves here
+        when bring new computers to life.  This doubles already slow
+        downloads.  */
+      /* NOTE: cagney/1999-10-18: A more efficient implementation
+        might add a verify_memory() method to the target vector and
+        then use that.  remote.c could implement that method using
+        the ``qCRC'' packet.  */
+      gdb_byte *check = xmalloc (bytes);
+      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));
+      if (memcmp (args->buffer, check, bytes) != 0)
+       error (_("Download verify compare failed at 0x%s"),
+              paddr (args->lma));
+      do_cleanups (verify_cleanups);
+    }
+  totals->data_count += bytes;
+  args->lma += bytes;
+  args->buffer += bytes;
+  totals->write_count += 1;
+  args->section_sent += bytes;
+  if (quit_flag
+      || (deprecated_ui_load_progress_hook != NULL
+         && deprecated_ui_load_progress_hook (args->section_name,
+                                              args->section_sent)))
+    error (_("Canceled the download"));
+
+  if (deprecated_show_load_progress != NULL)
+    deprecated_show_load_progress (args->section_name,
+                                  args->section_sent,
+                                  args->section_size,
+                                  totals->data_count,
+                                  totals->total_size);
+}
+
 /* Callback service function for generic_load (bfd_map_over_sections).  */
 
 static void
 load_section_callback (bfd *abfd, asection *asec, void *data)
 {
+  struct memory_write_request *new_request;
   struct load_section_data *args = data;
+  struct load_progress_section_data *section_data;
+  bfd_size_type size = bfd_get_section_size (asec);
+  gdb_byte *buffer;
+  const char *sect_name = bfd_get_section_name (abfd, asec);
 
-  if (bfd_get_section_flags (abfd, asec) & SEC_LOAD)
-    {
-      bfd_size_type size = bfd_get_section_size (asec);
-      if (size > 0)
-       {
-         char *buffer;
-         struct cleanup *old_chain;
-         CORE_ADDR lma = bfd_section_lma (abfd, asec) + args->load_offset;
-         bfd_size_type block_size;
-         int err;
-         const char *sect_name = bfd_get_section_name (abfd, asec);
-         bfd_size_type sent;
-
-         if (download_write_size > 0 && size > download_write_size)
-           block_size = download_write_size;
-         else
-           block_size = size;
+  if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
+    return;
 
-         buffer = xmalloc (size);
-         old_chain = make_cleanup (xfree, buffer);
+  if (size == 0)
+    return;
 
-         /* Is this really necessary?  I guess it gives the user something
-            to look at during a long download.  */
-         ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n",
-                         sect_name, paddr_nz (size), paddr_nz (lma));
+  new_request = VEC_safe_push (memory_write_request_s,
+                              args->requests, NULL);
+  memset (new_request, 0, sizeof (struct memory_write_request));
+  section_data = xcalloc (1, sizeof (struct load_progress_section_data));
+  new_request->begin = bfd_section_lma (abfd, asec) + args->load_offset;
+  new_request->end = new_request->begin + size; /* FIXME Should size be in instead?  */
+  new_request->data = xmalloc (size);
+  new_request->baton = section_data;
 
-         bfd_get_section_contents (abfd, asec, buffer, 0, size);
+  buffer = new_request->data;
 
-         sent = 0;
-         do
-           {
-             int len;
-             bfd_size_type this_transfer = size - sent;
-
-             if (this_transfer >= block_size)
-               this_transfer = block_size;
-             len = target_write_memory_partial (lma, buffer,
-                                                this_transfer, &err);
-             if (err)
-               break;
-             if (validate_download)
-               {
-                 /* Broken memories and broken monitors manifest
-                    themselves here when bring new computers to
-                    life.  This doubles already slow downloads.  */
-                 /* NOTE: cagney/1999-10-18: A more efficient
-                    implementation might add a verify_memory()
-                    method to the target vector and then use
-                    that.  remote.c could implement that method
-                    using the ``qCRC'' packet.  */
-                 char *check = xmalloc (len);
-                 struct cleanup *verify_cleanups =
-                   make_cleanup (xfree, check);
-
-                 if (target_read_memory (lma, check, len) != 0)
-                   error (_("Download verify read failed at 0x%s"),
-                          paddr (lma));
-                 if (memcmp (buffer, check, len) != 0)
-                   error (_("Download verify compare failed at 0x%s"),
-                          paddr (lma));
-                 do_cleanups (verify_cleanups);
-               }
-             args->data_count += len;
-             lma += len;
-             buffer += len;
-             args->write_count += 1;
-             sent += len;
-             if (quit_flag
-                 || (deprecated_ui_load_progress_hook != NULL
-                     && deprecated_ui_load_progress_hook (sect_name, sent)))
-               error (_("Canceled the download"));
-
-             if (deprecated_show_load_progress != NULL)
-               deprecated_show_load_progress (sect_name, sent, size,
-                                              args->data_count,
-                                              args->total_size);
-           }
-         while (sent < size);
+  section_data->cumulative = args->progress_data;
+  section_data->section_name = sect_name;
+  section_data->section_size = size;
+  section_data->lma = new_request->begin;
+  section_data->buffer = buffer;
 
-         if (err != 0)
-           error (_("Memory access error while loading section %s."), sect_name);
+  bfd_get_section_contents (abfd, asec, buffer, 0, size);
+}
 
-         do_cleanups (old_chain);
-       }
+/* Clean up an entire memory request vector, including load
+   data and progress records.  */
+
+static void
+clear_memory_write_data (void *arg)
+{
+  VEC(memory_write_request_s) **vec_p = arg;
+  VEC(memory_write_request_s) *vec = *vec_p;
+  int i;
+  struct memory_write_request *mr;
+
+  for (i = 0; VEC_iterate (memory_write_request_s, vec, i, mr); ++i)
+    {
+      xfree (mr->data);
+      xfree (mr->baton);
     }
+  VEC_free (memory_write_request_s, vec);
 }
 
 void
 generic_load (char *args, int from_tty)
 {
-  asection *s;
   bfd *loadfile_bfd;
   struct timeval start_time, end_time;
   char *filename;
-  struct cleanup *old_cleanups;
-  char *offptr;
+  struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
   struct load_section_data cbdata;
+  struct load_progress_data total_progress;
+
   CORE_ADDR entry;
+  char **argv;
 
-  cbdata.load_offset = 0;      /* Offset to add to vma for each section. */
-  cbdata.write_count = 0;      /* Number of writes needed. */
-  cbdata.data_count = 0;       /* Number of bytes written to target memory. */
-  cbdata.total_size = 0;       /* Total size of all bfd sectors. */
+  memset (&cbdata, 0, sizeof (cbdata));
+  memset (&total_progress, 0, sizeof (total_progress));
+  cbdata.progress_data = &total_progress;
 
-  /* Parse the input argument - the user can specify a load offset as
-     a second argument. */
-  filename = xmalloc (strlen (args) + 1);
-  old_cleanups = make_cleanup (xfree, filename);
-  strcpy (filename, args);
-  offptr = strchr (filename, ' ');
-  if (offptr != NULL)
+  make_cleanup (clear_memory_write_data, &cbdata.requests);
+
+  if (args == NULL)
+    error_no_arg (_("file to load"));
+
+  argv = gdb_buildargv (args);
+  make_cleanup_freeargv (argv);
+
+  filename = tilde_expand (argv[0]);
+  make_cleanup (xfree, filename);
+
+  if (argv[1] != NULL)
     {
       char *endptr;
 
-      cbdata.load_offset = strtoul (offptr, &endptr, 0);
-      if (offptr == endptr)
-       error (_("Invalid download offset:%s."), offptr);
-      *offptr = '\0';
+      cbdata.load_offset = strtoul (argv[1], &endptr, 0);
+
+      /* If the last word was not a valid number then
+         treat it as a file name with spaces in.  */
+      if (argv[1] == endptr)
+        error (_("Invalid download offset:%s."), argv[1]);
+
+      if (argv[2] != NULL)
+       error (_("Too many parameters."));
     }
-  else
-    cbdata.load_offset = 0;
 
   /* Open the file for loading. */
   loadfile_bfd = bfd_openr (filename, gnutarget);
@@ -1658,11 +1967,15 @@ generic_load (char *args, int from_tty)
     }
 
   bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
-                        (void *) &cbdata.total_size);
+                        (void *) &total_progress.total_size);
+
+  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
 
   gettimeofday (&start_time, NULL);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  if (target_write_memory_blocks (cbdata.requests, flash_discard,
+                                 load_progress) != 0)
+    error (_("Load failed"));
 
   gettimeofday (&end_time, NULL);
 
@@ -1670,11 +1983,11 @@ generic_load (char *args, int from_tty)
   ui_out_text (uiout, "Start address ");
   ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (entry));
   ui_out_text (uiout, ", load size ");
-  ui_out_field_fmt (uiout, "load-size", "%lu", cbdata.data_count);
+  ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
   ui_out_text (uiout, "\n");
   /* We were doing this in remote-mips.c, I suspect it is right
      for other targets too.  */
-  write_pc (entry);
+  regcache_write_pc (get_current_regcache (), entry);
 
   /* FIXME: are we supposed to call symbol_file_add or not?  According
      to a comment from remote-mips.c (where a call to symbol_file_add
@@ -1682,8 +1995,9 @@ generic_load (char *args, int from_tty)
      file is loaded in.  Some targets do (e.g., remote-vx.c) but
      others don't (or didn't - perhaps they have all been deleted).  */
 
-  print_transfer_performance (gdb_stdout, cbdata.data_count,
-                             cbdata.write_count, &start_time, &end_time);
+  print_transfer_performance (gdb_stdout, total_progress.data_count,
+                             total_progress.write_count,
+                             &start_time, &end_time);
 
   do_cleanups (old_cleanups);
 }
@@ -1715,7 +2029,7 @@ print_transfer_performance (struct ui_file *stream,
                            const struct timeval *start_time,
                            const struct timeval *end_time)
 {
-  unsigned long time_count;
+  ULONGEST time_count;
 
   /* Compute the elapsed time in milliseconds, as a tradeoff between
      accuracy and overflow.  */
@@ -1725,9 +2039,23 @@ print_transfer_performance (struct ui_file *stream,
   ui_out_text (uiout, "Transfer rate: ");
   if (time_count > 0)
     {
-      ui_out_field_fmt (uiout, "transfer-rate", "%lu",
-                       1000 * (data_count * 8) / time_count);
-      ui_out_text (uiout, " bits/sec");
+      unsigned long rate = ((ULONGEST) data_count * 1000) / time_count;
+
+      if (ui_out_is_mi_like_p (uiout))
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate * 8);
+         ui_out_text (uiout, " bits/sec");
+       }
+      else if (rate < 1024)
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate);
+         ui_out_text (uiout, " bytes/sec");
+       }
+      else
+       {
+         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024);
+         ui_out_text (uiout, " KB/sec");
+       }
     }
   else
     {
@@ -1765,6 +2093,7 @@ add_symbol_file_command (char *args, int from_tty)
   int i;
   int expecting_sec_name = 0;
   int expecting_sec_addr = 0;
+  char **argv;
 
   struct sect_opt
   {
@@ -1786,28 +2115,12 @@ add_symbol_file_command (char *args, int from_tty)
   if (args == NULL)
     error (_("add-symbol-file takes a file name and an address"));
 
-  /* Make a copy of the string that we can safely write into. */
-  args = xstrdup (args);
+  argv = gdb_buildargv (args);
+  make_cleanup_freeargv (argv);
 
-  while (*args != '\000')
+  for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
     {
-      /* Any leading spaces? */
-      while (isspace (*args))
-       args++;
-
-      /* Point arg to the beginning of the argument. */
-      arg = args;
-
-      /* Move args pointer over the argument. */
-      while ((*args != '\000') && !isspace (*args))
-       args++;
-
-      /* If there are more arguments, terminate arg and
-         proceed past it. */
-      if (*args != '\000')
-       *args++ = '\000';
-
-      /* Now process the argument. */
+      /* Process the argument. */
       if (argcnt == 0)
        {
          /* The first argument is the file name. */
@@ -1821,7 +2134,7 @@ add_symbol_file_command (char *args, int from_tty)
                to load the program. */
            sect_opts[section_index].name = ".text";
            sect_opts[section_index].value = arg;
-           if (++section_index > num_sect_opts)
+           if (++section_index >= num_sect_opts)
              {
                num_sect_opts *= 2;
                sect_opts = ((struct sect_opt *)
@@ -1857,7 +2170,7 @@ add_symbol_file_command (char *args, int from_tty)
                    {
                      sect_opts[section_index].value = arg;
                      expecting_sec_addr = 0;
-                     if (++section_index > num_sect_opts)
+                     if (++section_index >= num_sect_opts)
                        {
                          num_sect_opts *= 2;
                          sect_opts = ((struct sect_opt *)
@@ -1870,9 +2183,15 @@ add_symbol_file_command (char *args, int from_tty)
                    error (_("USAGE: add-symbol-file <filename> <textaddress> [-mapped] [-readnow] [-s <secname> <addr>]*"));
              }
          }
-      argcnt++;
     }
 
+  /* This command takes at least two arguments.  The first one is a
+     filename, and the second is the address where this file has been
+     loaded.  Abort now if this address hasn't been provided by the
+     user.  */
+  if (section_index < 1)
+    error (_("The address where %s has been loaded is missing"), filename);
+
   /* Print the prompt for the query below. And save the arguments into
      a sect_addr_info structure to be passed around to other
      functions.  We have to split this up into separate print
@@ -1894,8 +2213,7 @@ 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, hex_string ((unsigned long)addr));
+      printf_unfiltered ("\t%s_addr = %s\n", sec, paddress (addr));
       sec_num++;
 
       /* The object's sections are initialized when a
@@ -1987,6 +2305,14 @@ reread_symbols (void)
              /* 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.  */
@@ -1994,7 +2320,10 @@ reread_symbols (void)
              if (!bfd_close (objfile->obfd))
                error (_("Can't close BFD for %s: %s"), objfile->name,
                       bfd_errmsg (bfd_get_error ()));
-             objfile->obfd = bfd_openr (obfd_filename, gnutarget);
+             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.  */
@@ -2010,6 +2339,10 @@ reread_symbols (void)
              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.  */
@@ -2048,15 +2381,12 @@ reread_symbols (void)
                      sizeof (objfile->msymbol_hash));
              memset (&objfile->msymbol_demangled_hash, 0,
                      sizeof (objfile->msymbol_demangled_hash));
-             objfile->fundamental_types = NULL;
              clear_objfile_data (objfile);
              if (objfile->sf != NULL)
                {
                  (*objfile->sf->sym_finish) (objfile);
                }
 
-             /* We never make this a mapped file.  */
-             objfile->md = NULL;
              objfile->psymbol_cache = bcache_xmalloc ();
              objfile->macro_cache = bcache_xmalloc ();
              /* obstack_init also initializes the obstack so it is
@@ -2100,7 +2430,6 @@ reread_symbols (void)
                  printf_unfiltered (_("(no debugging symbols found)\n"));
                  wrap_here ("");
                }
-             objfile->flags |= OBJF_SYMS;
 
              /* We're done reading the symbol file; finish off complaints.  */
              clear_complaints (&symfile_complaints, 0, 1);
@@ -2119,6 +2448,7 @@ reread_symbols (void)
              objfile->mtime = new_modtime;
              reread_one = 1;
               reread_separate_symbols (objfile);
+             init_entry_point_info (objfile);
            }
        }
     }
@@ -2128,7 +2458,7 @@ reread_symbols (void)
       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 (NULL);
+      observer_notify_executable_changed ();
     }
       
 }
@@ -2195,6 +2525,8 @@ reread_separate_symbols (struct objfile *objfile)
       objfile->separate_debug_objfile->separate_debug_objfile_backlink
         = objfile;
     }
+  if (debug_file)
+    xfree (debug_file);
 }
 
 
@@ -2329,6 +2661,7 @@ init_filename_language_table (void)
       add_filename_language (".f", language_fortran);
       add_filename_language (".F", language_fortran);
       add_filename_language (".s", language_asm);
+      add_filename_language (".sx", language_asm);
       add_filename_language (".S", language_asm);
       add_filename_language (".pas", language_pascal);
       add_filename_language (".p", language_pascal);
@@ -2390,14 +2723,6 @@ allocate_symtab (char *filename, struct objfile *objfile)
   symtab->next = objfile->symtabs;
   objfile->symtabs = symtab;
 
-  /* FIXME: This should go away.  It is only defined for the Z8000,
-     and the Z8000 definition of this macro doesn't have anything to
-     do with the now-nonexistent EXTRA_SYMTAB_INFO macro, it's just
-     here for convenience.  */
-#ifdef INIT_EXTRA_SYMTAB_INFO
-  INIT_EXTRA_SYMTAB_INFO (symtab);
-#endif
-
   return (symtab);
 }
 
@@ -2482,14 +2807,21 @@ clear_symtab_users (void)
      breakpoint_re_set may try to access the current symtab.  */
   clear_current_source_symtab_and_line ();
 
-  clear_value_history ();
   clear_displays ();
-  clear_internalvars ();
   breakpoint_re_set ();
   set_default_breakpoint (0, 0, 0, 0);
   clear_pc_function_cache ();
-  if (deprecated_target_new_objfile_hook)
-    deprecated_target_new_objfile_hook (NULL);
+  observer_notify_new_objfile (NULL);
+
+  /* Clear globals which might have pointed into a removed objfile.
+     FIXME: It's not clear which of these are supposed to persist
+     between expressions and which ought to be reset each time.  */
+  expression_context_block = NULL;
+  innermost_block = NULL;
+
+  /* Varobj may refer to old symbols, perform a cleanup.  */
+  varobj_invalidate ();
+
 }
 
 static void
@@ -2724,38 +3056,33 @@ start_psymtab_common (struct objfile *objfile,
   return (psymtab);
 }
 \f
-/* 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)
+/* 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)
 {
-  struct partial_symbol *psym;
-  char *buf = alloca (namelength + 1);
+  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;
-
-  /* Create local copy of the partial symbol */
-  memcpy (buf, name, namelength);
-  buf[namelength] = '\0';
+  
+  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)
     {
@@ -2773,87 +3100,63 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain,
   SYMBOL_SET_NAMES (&psymbol, buf, namelength, objfile);
 
   /* Stash the partial symbol away in the cache */
-  psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol),
-                           objfile->psymbol_cache);
+  return bcache_full (&psymbol, sizeof (struct partial_symbol),
+                     objfile->psymbol_cache, added);
+}
 
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+/* 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++ = psym;
+    extend_psymbol_list (list, objfile);
+  *list->next++ = (struct partial_symbol *) psym;
   OBJSTAT (objfile, n_psyms++);
-
-  return psym;
 }
 
-/* Add a symbol with a long value to a psymtab. This differs from
- * add_psymbol_to_list above in taking both a mangled and a demangled
- * name. */
-
-void
-add_psymbol_with_dem_name_to_list (char *name, int namelength, char *dem_name,
-                                  int dem_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)
-{
-  struct partial_symbol *psym;
-  char *buf = alloca (namelength + 1);
-  /* 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;
-
-  /* Create local copy of the partial symbol */
-
-  memcpy (buf, name, namelength);
-  buf[namelength] = '\0';
-  DEPRECATED_SYMBOL_NAME (&psymbol) = deprecated_bcache (buf, namelength + 1,
-                                                        objfile->psymbol_cache);
+/* 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.  */
 
-  buf = alloca (dem_namelength + 1);
-  memcpy (buf, dem_name, dem_namelength);
-  buf[dem_namelength] = '\0';
+/* 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.  */
 
-  switch (language)
-    {
-    case language_c:
-    case language_cplus:
-      SYMBOL_CPLUS_DEMANGLED_NAME (&psymbol) =
-       deprecated_bcache (buf, dem_namelength + 1, objfile->psymbol_cache);
-      break;
-      /* FIXME What should be done for the default case? Ignoring for now. */
-    }
+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;
 
-  /* 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_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+  int added;
 
   /* Stash the partial symbol away in the cache */
-  psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol),
-                           objfile->psymbol_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. */
-  if (list->next >= list->list + list->size)
-    {
-      extend_psymbol_list (list, objfile);
-    }
-  *list->next++ = psym;
-  OBJSTAT (objfile, n_psyms++);
+  append_psymbol_to_list (list, psym, objfile);
+  return psym;
 }
 
 /* Initialize storage for partial symbols.  */
@@ -2932,7 +3235,7 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
    section, return that section.
    find_pc_overlay(pc):       find any overlay section that contains
    the pc, either in its VMA or its LMA
-   overlay_is_mapped(sect):       true if overlay is marked as mapped
+   section_is_mapped(sect):       true if overlay is marked as mapped
    section_is_overlay(sect):      true if section's VMA != LMA
    pc_in_mapped_range(pc,sec):    true if pc belongs to section's VMA
    pc_in_unmapped_range(...):     true if pc belongs to section's LMA
@@ -2949,23 +3252,23 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
 enum overlay_debugging_state overlay_debugging = ovly_off;
 int overlay_cache_invalid = 0; /* True if need to refresh mapped state */
 
-/* Target vector for refreshing overlay mapped state */
-static void simple_overlay_update (struct obj_section *);
-void (*target_overlay_update) (struct obj_section *) = simple_overlay_update;
-
 /* Function: section_is_overlay (SECTION)
    Returns true if SECTION has VMA not equal to LMA, ie.
    SECTION is loaded at an address different from where it will "run".  */
 
 int
-section_is_overlay (asection *section)
+section_is_overlay (struct obj_section *section)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
-
-  if (overlay_debugging)
-    if (section && section->lma != 0 &&
-       section->vma != section->lma)
-      return 1;
+  if (overlay_debugging && section)
+    {
+      bfd *abfd = section->objfile->obfd;
+      asection *bfd_section = section->the_bfd_section;
+  
+      if (bfd_section_lma (abfd, bfd_section) != 0
+         && bfd_section_lma (abfd, bfd_section)
+            != bfd_section_vma (abfd, bfd_section))
+       return 1;
+    }
 
   return 0;
 }
@@ -2980,13 +3283,12 @@ overlay_invalidate_all (void)
   struct obj_section *sect;
 
   ALL_OBJSECTIONS (objfile, sect)
-    if (section_is_overlay (sect->the_bfd_section))
-    sect->ovly_mapped = -1;
+    if (section_is_overlay (sect))
+      sect->ovly_mapped = -1;
 }
 
-/* Function: overlay_is_mapped (SECTION)
+/* Function: section_is_mapped (SECTION)
    Returns true if section is an overlay, and is currently mapped.
-   Private: public access is thru function section_is_mapped.
 
    Access to the ovly_mapped flag is restricted to this function, so
    that we can do automatic update.  If the global flag
@@ -2994,10 +3296,10 @@ overlay_invalidate_all (void)
    overlay_invalidate_all.  If the mapped state of the particular
    section is stale, then call TARGET_OVERLAY_UPDATE to refresh it.  */
 
-static int
-overlay_is_mapped (struct obj_section *osect)
+int
+section_is_mapped (struct obj_section *osect)
 {
-  if (osect == 0 || !section_is_overlay (osect->the_bfd_section))
+  if (osect == 0 || !section_is_overlay (osect))
     return 0;
 
   switch (overlay_debugging)
@@ -3006,9 +3308,9 @@ overlay_is_mapped (struct obj_section *osect)
     case ovly_off:
       return 0;                        /* overlay debugging off */
     case ovly_auto:            /* overlay debugging automatic */
-      /* Unles there is a target_overlay_update function,
+      /* Unles there is a gdbarch_overlay_update function,
          there's really nothing useful to do here (can't really go auto)  */
-      if (target_overlay_update)
+      if (gdbarch_overlay_update_p (current_gdbarch))
        {
          if (overlay_cache_invalid)
            {
@@ -3016,7 +3318,7 @@ overlay_is_mapped (struct obj_section *osect)
              overlay_cache_invalid = 0;
            }
          if (osect->ovly_mapped == -1)
-           (*target_overlay_update) (osect);
+           gdbarch_overlay_update (current_gdbarch, osect);
        }
       /* fall thru to manual case */
     case ovly_on:              /* overlay debugging manual */
@@ -3024,41 +3326,26 @@ overlay_is_mapped (struct obj_section *osect)
     }
 }
 
-/* Function: section_is_mapped
-   Returns true if section is an overlay, and is currently mapped.  */
-
-int
-section_is_mapped (asection *section)
-{
-  struct objfile *objfile;
-  struct obj_section *osect;
-
-  if (overlay_debugging)
-    if (section && section_is_overlay (section))
-      ALL_OBJSECTIONS (objfile, osect)
-       if (osect->the_bfd_section == section)
-       return overlay_is_mapped (osect);
-
-  return 0;
-}
-
 /* Function: pc_in_unmapped_range
    If PC falls into the lma range of SECTION, return true, else false.  */
 
 CORE_ADDR
-pc_in_unmapped_range (CORE_ADDR pc, asection *section)
+pc_in_unmapped_range (CORE_ADDR pc, struct obj_section *section)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
+  if (section_is_overlay (section))
+    {
+      bfd *abfd = section->objfile->obfd;
+      asection *bfd_section = section->the_bfd_section;
 
-  int size;
+      /* We assume the LMA is relocated by the same offset as the VMA.  */
+      bfd_vma size = bfd_get_section_size (bfd_section);
+      CORE_ADDR offset = obj_section_offset (section);
+
+      if (bfd_get_section_lma (abfd, bfd_section) + offset <= pc
+         && pc < bfd_get_section_lma (abfd, bfd_section) + offset + size)
+       return 1;
+    }
 
-  if (overlay_debugging)
-    if (section && section_is_overlay (section))
-      {
-       size = bfd_get_section_size (section);
-       if (section->lma <= pc && pc < section->lma + size)
-         return 1;
-      }
   return 0;
 }
 
@@ -3066,19 +3353,15 @@ pc_in_unmapped_range (CORE_ADDR pc, asection *section)
    If PC falls into the vma range of SECTION, return true, else false.  */
 
 CORE_ADDR
-pc_in_mapped_range (CORE_ADDR pc, asection *section)
+pc_in_mapped_range (CORE_ADDR pc, struct obj_section *section)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
-
-  int size;
+  if (section_is_overlay (section))
+    {
+      if (obj_section_addr (section) <= pc
+         && pc < obj_section_endaddr (section))
+       return 1;
+    }
 
-  if (overlay_debugging)
-    if (section && section_is_overlay (section))
-      {
-       size = bfd_get_section_size (section);
-       if (section->vma <= pc && pc < section->vma + size)
-         return 1;
-      }
   return 0;
 }
 
@@ -3086,14 +3369,12 @@ pc_in_mapped_range (CORE_ADDR pc, asection *section)
 /* Return true if the mapped ranges of sections A and B overlap, false
    otherwise.  */
 static int
-sections_overlap (asection *a, asection *b)
+sections_overlap (struct obj_section *a, struct obj_section *b)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
-
-  CORE_ADDR a_start = a->vma;
-  CORE_ADDR a_end = a->vma + bfd_get_section_size (a);
-  CORE_ADDR b_start = b->vma;
-  CORE_ADDR b_end = b->vma + bfd_get_section_size (b);
+  CORE_ADDR a_start = obj_section_addr (a);
+  CORE_ADDR a_end = obj_section_endaddr (a);
+  CORE_ADDR b_start = obj_section_addr (b);
+  CORE_ADDR b_end = obj_section_endaddr (b);
 
   return (a_start < b_end && b_start < a_end);
 }
@@ -3103,14 +3384,16 @@ sections_overlap (asection *a, asection *b)
    May be the same as PC.  */
 
 CORE_ADDR
-overlay_unmapped_address (CORE_ADDR pc, asection *section)
+overlay_unmapped_address (CORE_ADDR pc, struct obj_section *section)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_lma methods. */
+  if (section_is_overlay (section) && pc_in_mapped_range (pc, section))
+    {
+      bfd *abfd = section->objfile->obfd;
+      asection *bfd_section = section->the_bfd_section;
 
-  if (overlay_debugging)
-    if (section && section_is_overlay (section) &&
-       pc_in_mapped_range (pc, section))
-      return pc + section->lma - section->vma;
+      return pc + bfd_section_lma (abfd, bfd_section)
+               - bfd_section_vma (abfd, bfd_section);
+    }
 
   return pc;
 }
@@ -3120,14 +3403,16 @@ overlay_unmapped_address (CORE_ADDR pc, asection *section)
    May be the same as PC.  */
 
 CORE_ADDR
-overlay_mapped_address (CORE_ADDR pc, asection *section)
+overlay_mapped_address (CORE_ADDR pc, struct obj_section *section)
 {
-  /* FIXME: need bfd *, so we can use bfd_section_vma methods. */
+  if (section_is_overlay (section) && pc_in_unmapped_range (pc, section))
+    {
+      bfd *abfd = section->objfile->obfd;
+      asection *bfd_section = section->the_bfd_section;
 
-  if (overlay_debugging)
-    if (section && section_is_overlay (section) &&
-       pc_in_unmapped_range (pc, section))
-      return pc + section->vma - section->lma;
+      return pc + bfd_section_vma (abfd, bfd_section)
+               - bfd_section_lma (abfd, bfd_section);
+    }
 
   return pc;
 }
@@ -3138,7 +3423,7 @@ overlay_mapped_address (CORE_ADDR pc, asection *section)
    depending on whether the section is mapped or not.  */
 
 CORE_ADDR
-symbol_overlayed_address (CORE_ADDR address, asection *section)
+symbol_overlayed_address (CORE_ADDR address, struct obj_section *section)
 {
   if (overlay_debugging)
     {
@@ -3166,7 +3451,7 @@ symbol_overlayed_address (CORE_ADDR address, asection *section)
    Else if PC matches an unmapped section's VMA, return that section.
    Else if PC matches an unmapped section's LMA, return that section.  */
 
-asection *
+struct obj_section *
 find_pc_overlay (CORE_ADDR pc)
 {
   struct objfile *objfile;
@@ -3174,26 +3459,26 @@ find_pc_overlay (CORE_ADDR pc)
 
   if (overlay_debugging)
     ALL_OBJSECTIONS (objfile, osect)
-      if (section_is_overlay (osect->the_bfd_section))
+      if (section_is_overlay (osect))
       {
-       if (pc_in_mapped_range (pc, osect->the_bfd_section))
+       if (pc_in_mapped_range (pc, osect))
          {
-           if (overlay_is_mapped (osect))
-             return osect->the_bfd_section;
+           if (section_is_mapped (osect))
+             return osect;
            else
              best_match = osect;
          }
-       else if (pc_in_unmapped_range (pc, osect->the_bfd_section))
+       else if (pc_in_unmapped_range (pc, osect))
          best_match = osect;
       }
-  return best_match ? best_match->the_bfd_section : NULL;
+  return best_match;
 }
 
 /* Function: find_pc_mapped_section (PC)
    If PC falls into the VMA address range of an overlay section that is
    currently marked as MAPPED, return that section.  Else return NULL.  */
 
-asection *
+struct obj_section *
 find_pc_mapped_section (CORE_ADDR pc)
 {
   struct objfile *objfile;
@@ -3201,9 +3486,8 @@ find_pc_mapped_section (CORE_ADDR pc)
 
   if (overlay_debugging)
     ALL_OBJSECTIONS (objfile, osect)
-      if (pc_in_mapped_range (pc, osect->the_bfd_section) &&
-         overlay_is_mapped (osect))
-      return osect->the_bfd_section;
+      if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
+       return osect;
 
   return NULL;
 }
@@ -3220,7 +3504,7 @@ list_overlays_command (char *args, int from_tty)
 
   if (overlay_debugging)
     ALL_OBJSECTIONS (objfile, osect)
-      if (overlay_is_mapped (osect))
+      if (section_is_mapped (osect))
       {
        const char *name;
        bfd_vma lma, vma;
@@ -3232,13 +3516,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);
-       deprecated_print_address_numeric (lma, 1, gdb_stdout);
+       fputs_filtered (paddress (lma), gdb_stdout);
        puts_filtered (" - ");
-       deprecated_print_address_numeric (lma + size, 1, gdb_stdout);
+       fputs_filtered (paddress (lma + size), gdb_stdout);
        printf_filtered (", mapped at ");
-       deprecated_print_address_numeric (vma, 1, gdb_stdout);
+       fputs_filtered (paddress (vma), gdb_stdout);
        puts_filtered (" - ");
-       deprecated_print_address_numeric (vma + size, 1, gdb_stdout);
+       fputs_filtered (paddress (vma + size), gdb_stdout);
        puts_filtered ("\n");
 
        nmapped++;
@@ -3255,7 +3539,6 @@ map_overlay_command (char *args, int from_tty)
 {
   struct objfile *objfile, *objfile2;
   struct obj_section *sec, *sec2;
-  asection *bfdsec;
 
   if (!overlay_debugging)
     error (_("\
@@ -3270,8 +3553,7 @@ the 'overlay manual' command."));
     if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args))
     {
       /* Now, check to see if the section is an overlay. */
-      bfdsec = sec->the_bfd_section;
-      if (!section_is_overlay (bfdsec))
+      if (!section_is_overlay (sec))
        continue;               /* not an overlay section */
 
       /* Mark the overlay as "mapped" */
@@ -3280,11 +3562,7 @@ the 'overlay manual' command."));
       /* Next, make a pass and unmap any sections that are
          overlapped by this new section: */
       ALL_OBJSECTIONS (objfile2, sec2)
-       if (sec2->ovly_mapped
-            && sec != sec2
-            && sec->the_bfd_section != sec2->the_bfd_section
-            && sections_overlap (sec->the_bfd_section,
-                                 sec2->the_bfd_section))
+       if (sec2->ovly_mapped && sec != sec2 && sections_overlap (sec, sec2))
        {
          if (info_verbose)
            printf_unfiltered (_("Note: section %s unmapped by overlap\n"),
@@ -3369,8 +3647,8 @@ overlay_off_command (char *args, int from_tty)
 static void
 overlay_load_command (char *args, int from_tty)
 {
-  if (target_overlay_update)
-    (*target_overlay_update) (NULL);
+  if (gdbarch_overlay_update_p (current_gdbarch))
+    gdbarch_overlay_update (current_gdbarch, NULL);
   else
     error (_("This target does not know how to read its overlay state."));
 }
@@ -3394,7 +3672,7 @@ overlay_command (char *args, int from_tty)
 
    This is GDB's default target overlay layer.  It works with the
    minimal overlay manager supplied as an example by Cygnus.  The
-   entry point is via a function pointer "target_overlay_update",
+   entry point is via a function pointer "gdbarch_overlay_update",
    so targets that use a different runtime overlay manager can
    substitute their own overlay_update function and take over the
    function pointer.
@@ -3441,7 +3719,8 @@ enum ovly_index
   {
     VMA, SIZE, LMA, MAPPED
   };
-#define TARGET_LONG_BYTES (TARGET_LONG_BIT / TARGET_CHAR_BIT)
+#define TARGET_LONG_BYTES (gdbarch_long_bit (current_gdbarch) \
+                           / TARGET_CHAR_BIT)
 
 /* Throw away the cached copy of _ovly_table */
 static void
@@ -3473,7 +3752,7 @@ static void
 read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr, int len)
 {
   /* FIXME (alloca): Not safe if array is very large. */
-  char *buf = alloca (len * TARGET_LONG_BYTES);
+  gdb_byte *buf = alloca (len * TARGET_LONG_BYTES);
   int i;
 
   read_memory (memaddr, buf, len * TARGET_LONG_BYTES);
@@ -3513,7 +3792,7 @@ simple_read_overlay_table (void)
     = (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,
-                          (int *) cache_ovly_table,
+                          (unsigned int *) cache_ovly_table,
                           cache_novlys * 4);
 
   return 1;                    /* SUCCESS */
@@ -3541,7 +3820,7 @@ simple_read_overlay_region_table (void)
        {
          cache_ovly_region_table_base = SYMBOL_VALUE_ADDRESS (msym);
          read_target_long_array (cache_ovly_region_table_base,
-                                 (int *) cache_ovly_region_table,
+                                 (unsigned int *) cache_ovly_region_table,
                                  cache_novly_regions * 3);
        }
       else
@@ -3575,7 +3854,7 @@ simple_overlay_update_1 (struct obj_section *osect)
        /* && cache_ovly_table[i][SIZE] == size */ )
       {
        read_target_long_array (cache_ovly_table_base + i * TARGET_LONG_BYTES,
-                               (int *) cache_ovly_table[i], 4);
+                               (unsigned int *) cache_ovly_table[i], 4);
        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 */ )
@@ -3597,7 +3876,7 @@ simple_overlay_update_1 (struct obj_section *osect)
    If a cached entry can't be found or the cache isn't valid, then
    re-read the entire cache, and go ahead and update all sections.  */
 
-static void
+void
 simple_overlay_update (struct obj_section *osect)
 {
   struct objfile *objfile;
@@ -3623,7 +3902,7 @@ simple_overlay_update (struct obj_section *osect)
 
   /* Now may as well update all sections, even if only one was requested. */
   ALL_OBJSECTIONS (objfile, osect)
-    if (section_is_overlay (osect->the_bfd_section))
+    if (section_is_overlay (osect))
     {
       int i, size;
       bfd *obfd = osect->objfile->obfd;
@@ -3662,17 +3941,18 @@ symfile_dummy_outputs (bfd *abfd, asection *sectp, void *dummy)
    one affected platform is PowerPC GNU/Linux, although it depends on
    the version of the linker in use).  Also, ELF object files naturally
    have unresolved relocations for their debug sections.  We need to apply
-   the relocations in order to get the locations of symbols correct.  */
+   the relocations in order to get the locations of symbols correct.
+   Another example that may require relocation processing, is the
+   DWARF-2 .eh_frame section in .o files, although it isn't strictly a
+   debug section.  */
 
 bfd_byte *
 symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
 {
-  /* We're only interested in debugging sections with relocation
+  /* We're only interested in sections with relocation
      information.  */
   if ((sectp->flags & SEC_RELOC) == 0)
     return NULL;
-  if ((sectp->flags & SEC_DEBUGGING) == 0)
-    return NULL;
 
   /* We will handle section offsets properly elsewhere, so relocate as if
      all sections begin at 0.  */
@@ -3681,6 +3961,126 @@ symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
   return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL);
 }
 
+struct symfile_segment_data *
+get_symfile_segment_data (bfd *abfd)
+{
+  struct sym_fns *sf = find_sym_fns (abfd);
+
+  if (sf == NULL)
+    return NULL;
+
+  return sf->sym_segments (abfd);
+}
+
+void
+free_symfile_segment_data (struct symfile_segment_data *data)
+{
+  xfree (data->segment_bases);
+  xfree (data->segment_sizes);
+  xfree (data->segment_info);
+  xfree (data);
+}
+
+
+/* Given:
+   - DATA, containing segment addresses from the object file ABFD, and
+     the mapping from ABFD's sections onto the segments that own them,
+     and
+   - SEGMENT_BASES[0 .. NUM_SEGMENT_BASES - 1], holding the actual
+     segment addresses reported by the target,
+   store the appropriate offsets for each section in OFFSETS.
+
+   If there are fewer entries in SEGMENT_BASES than there are segments
+   in DATA, then apply SEGMENT_BASES' last entry to all the segments.
+
+   If there are more entries, then ignore the extra.  The target may
+   not be able to distinguish between an empty data segment and a
+   missing data segment; a missing text segment is less plausible.  */
+int
+symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
+                                struct section_offsets *offsets,
+                                int num_segment_bases,
+                                const CORE_ADDR *segment_bases)
+{
+  int i;
+  asection *sect;
+
+  /* It doesn't make sense to call this function unless you have some
+     segment base addresses.  */
+  gdb_assert (segment_bases > 0);
+
+  /* If we do not have segment mappings for the object file, we
+     can not relocate it by segments.  */
+  gdb_assert (data != NULL);
+  gdb_assert (data->num_segments > 0);
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      int which = data->segment_info[i];
+
+      gdb_assert (0 <= which && which <= data->num_segments);
+
+      /* Don't bother computing offsets for sections that aren't
+         loaded as part of any segment.  */
+      if (! which)
+        continue;
+
+      /* Use the last SEGMENT_BASES entry as the address of any extra
+         segments mentioned in DATA->segment_info.  */
+      if (which > num_segment_bases)
+        which = num_segment_bases;
+
+      offsets->offsets[i] = (segment_bases[which - 1]
+                             - data->segment_bases[which - 1]);
+    }
+
+  return 1;
+}
+
+static void
+symfile_find_segment_sections (struct objfile *objfile)
+{
+  bfd *abfd = objfile->obfd;
+  int i;
+  asection *sect;
+  struct symfile_segment_data *data;
+
+  data = get_symfile_segment_data (objfile->obfd);
+  if (data == NULL)
+    return;
+
+  if (data->num_segments != 1 && data->num_segments != 2)
+    {
+      free_symfile_segment_data (data);
+      return;
+    }
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      CORE_ADDR vma;
+      int which = data->segment_info[i];
+
+      if (which == 1)
+       {
+         if (objfile->sect_index_text == -1)
+           objfile->sect_index_text = sect->index;
+
+         if (objfile->sect_index_rodata == -1)
+           objfile->sect_index_rodata = sect->index;
+       }
+      else if (which == 2)
+       {
+         if (objfile->sect_index_data == -1)
+           objfile->sect_index_data = sect->index;
+
+         if (objfile->sect_index_bss == -1)
+           objfile->sect_index_bss = sect->index;
+       }
+    }
+
+  free_symfile_segment_data (data);
+}
+
 void
 _initialize_symfile (void)
 {
@@ -3693,8 +4093,8 @@ to execute."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command, _("\
+Load symbols from FILE, assuming FILE has been dynamically loaded.\n\
 Usage: add-symbol-file FILE ADDR [-s <SECT> <SECT_ADDR> -s <SECT> <SECT_ADDR> ...]\n\
-Load the symbols from FILE, assuming FILE has been dynamically loaded.\n\
 ADDR is the starting address of the file's text.\n\
 The optional arguments are section-name section-address pairs and\n\
 should be specified if the data and bss segments are not contiguous\n\
@@ -3711,7 +4111,8 @@ Load the symbols from shared objects in the dynamic linker's link map."),
 
   c = add_cmd ("load", class_files, load_command, _("\
 Dynamically load FILE into the running program, and record its symbols\n\
-for access from GDB."), &cmdlist);
+for access from GDB.\n\
+A load OFFSET may also be given."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_setshow_boolean_cmd ("symbol-reloading", class_support,
@@ -3761,20 +4162,6 @@ Usage: set extension-language .foo bar"),
   add_info ("extensions", info_ext_lang_command,
            _("All filename extensions associated with a source language."));
 
-  add_setshow_integer_cmd ("download-write-size", class_obscure,
-                          &download_write_size, _("\
-Set the write size used when downloading a program."), _("\
-Show the write size used when downloading a program."), _("\
-Only used when downloading a program onto a remote\n\
-target. Specify zero, or a negative value, to disable\n\
-blocked writes. The actual size of each transfer is also\n\
-limited by the size of the target packet and the memory\n\
-cache."),
-                          NULL,
-                          show_download_write_size,
-                          &setlist, &showlist);
-
-  debug_file_directory = xstrdup (DEBUGDIR);
   add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
                                     &debug_file_directory, _("\
 Set the directory where separate debug symbols are searched for."), _("\
@@ -3786,4 +4173,12 @@ the global debug-file directory 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.052594 seconds and 4 git commands to generate.