* spu-tdep.c: Update for unwinder changes.
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 7dbbb7b53ebe876e1a68a51c7b541a982628a57c..3bbd1c3f203f0f058dcecdbb445c8064ab3da2ef 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
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
@@ -10,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,
@@ -19,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., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "bfdlink.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 <sys/types.h>
 #include <fcntl.h>
@@ -69,7 +71,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);
 
@@ -87,8 +88,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);
@@ -105,7 +104,7 @@ 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 *);
 
@@ -145,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
@@ -429,12 +430,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++)
     {
@@ -475,8 +483,8 @@ place_section (bfd *abfd, asection *sect, void *obj)
   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.  */
@@ -500,13 +508,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
@@ -579,9 +582,62 @@ 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]);
+             offsets[cur_sec->index] = 0;
+           }
+       }
     }
 
   /* Remember the bfd indexes for the .text, .data, .bss and
@@ -590,6 +646,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.
 
@@ -636,7 +756,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. */
@@ -701,18 +821,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
@@ -897,7 +1012,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);
@@ -961,7 +1076,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)
@@ -1017,8 +1136,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);
@@ -1095,15 +1213,104 @@ symbol_file_clear (int from_tty)
        storage has just been released, we'd better wipe the solib
        descriptors as well.
      */
-#if defined(SOLIB_RESTART)
-    SOLIB_RESTART ();
-#endif
+    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.  */
+  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 ()));
+  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)
 {
@@ -1155,7 +1362,7 @@ separate_debug_file_exists (const char *name, unsigned long crc)
   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)
@@ -1177,9 +1384,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);
+      free (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);
 
@@ -1244,6 +1471,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;
@@ -1317,7 +1568,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;
@@ -1432,29 +1683,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
 
@@ -1521,15 +1766,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).  */
@@ -1545,121 +1781,169 @@ 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)
-       {
-         gdb_byte *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.  */
-                 gdb_byte *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 = 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;
+
+  make_cleanup (clear_memory_write_data, &cbdata.requests);
 
   argv = buildargv (args);
 
@@ -1706,11 +1990,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);
 
@@ -1718,7 +2006,7 @@ 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.  */
@@ -1730,8 +2018,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);
 }
@@ -1763,7 +2052,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.  */
@@ -1773,9 +2062,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
     {
@@ -1857,7 +2160,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 *)
@@ -1893,7 +2196,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 *)
@@ -2094,7 +2397,6 @@ 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)
                {
@@ -2241,6 +2543,8 @@ reread_separate_symbols (struct objfile *objfile)
       objfile->separate_debug_objfile->separate_debug_objfile_backlink
         = objfile;
     }
+  if (debug_file)
+    xfree (debug_file);
 }
 
 
@@ -2375,6 +2679,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);
@@ -2436,14 +2741,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);
 }
 
@@ -2532,8 +2829,17 @@ clear_symtab_users (void)
   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
@@ -2831,75 +3137,6 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain,
   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);
-
-  buf = alloca (dem_namelength + 1);
-  memcpy (buf, dem_name, dem_namelength);
-  buf[dem_namelength] = '\0';
-
-  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. */
-    }
-
-  /* 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);
-
-  /* Stash the partial symbol away in the cache */
-  psym = deprecated_bcache (&psymbol, sizeof (struct partial_symbol),
-                           objfile->psymbol_cache);
-
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
-  if (list->next >= list->list + list->size)
-    {
-      extend_psymbol_list (list, objfile);
-    }
-  *list->next++ = psym;
-  OBJSTAT (objfile, n_psyms++);
-}
-
 /* Initialize storage for partial symbols.  */
 
 void
@@ -2993,10 +3230,6 @@ 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".  */
@@ -3050,9 +3283,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)
            {
@@ -3060,7 +3293,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 */
@@ -3276,13 +3509,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++;
@@ -3413,8 +3646,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."));
 }
@@ -3438,7 +3671,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.
@@ -3485,7 +3718,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
@@ -3641,7 +3875,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;
@@ -3725,6 +3959,133 @@ 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, then verify that all the excess addresses are
+   the same as the last legitimate one, and then ignore them.  This
+   allows "TextSeg=X;DataSeg=X" qOffset replies for files which have
+   only a single segment.  */
+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);
+
+  /* Check any extra SEGMENT_BASES entries.  */
+  if (num_segment_bases > data->num_segments)
+    for (i = data->num_segments; i < num_segment_bases; i++)
+      if (segment_bases[i] != segment_bases[data->num_segments - 1])
+       return 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)
 {
@@ -3806,20 +4167,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."), _("\
This page took 0.038415 seconds and 4 git commands to generate.