ld testsuite fixes for alpha
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 01ff6aef379654f8d518c7608fcf0af335572e54..b29f864b3735989392dae7684754e7958413a08d 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
 /* Generic symbol file reading for the GNU debugger, GDB.
 
-   Copyright (C) 1990-2014 Free Software Foundation, Inc.
+   Copyright (C) 1990-2020 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
@@ -44,9 +44,9 @@
 #include "completer.h"
 #include "bcache.h"
 #include "hashtab.h"
 #include "completer.h"
 #include "bcache.h"
 #include "hashtab.h"
-#include "readline/readline.h"
+#include "readline/tilde.h"
 #include "block.h"
 #include "block.h"
-#include "observer.h"
+#include "observable.h"
 #include "exec.h"
 #include "parser-defs.h"
 #include "varobj.h"
 #include "exec.h"
 #include "parser-defs.h"
 #include "varobj.h"
 #include "stack.h"
 #include "gdb_bfd.h"
 #include "cli/cli-utils.h"
 #include "stack.h"
 #include "gdb_bfd.h"
 #include "cli/cli-utils.h"
+#include "gdbsupport/byte-vector.h"
+#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/selftest.h"
+#include "cli/cli-style.h"
+#include "gdbsupport/forward-scope-exit.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <ctype.h>
 
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <ctype.h>
-#include <time.h>
-#include <sys/time.h>
+#include <chrono>
+#include <algorithm>
 
 #include "psymtab.h"
 
 
 #include "psymtab.h"
 
@@ -76,35 +81,22 @@ void (*deprecated_show_load_progress) (const char *section,
 void (*deprecated_pre_add_symbol_hook) (const char *);
 void (*deprecated_post_add_symbol_hook) (void);
 
 void (*deprecated_pre_add_symbol_hook) (const char *);
 void (*deprecated_post_add_symbol_hook) (void);
 
-static void clear_symtab_users_cleanup (void *ignore);
+using clear_symtab_users_cleanup
+  = FORWARD_SCOPE_EXIT (clear_symtab_users);
 
 /* Global variables owned by this file.  */
 int readnow_symbol_files;      /* Read full symbols immediately.  */
 
 /* Global variables owned by this file.  */
 int readnow_symbol_files;      /* Read full symbols immediately.  */
+int readnever_symbol_files;    /* Never read full symbols.  */
 
 /* Functions this file defines.  */
 
 
 /* Functions this file defines.  */
 
-static void load_command (char *, int);
-
-static void symbol_file_add_main_1 (const char *args, int from_tty, int flags);
-
-static void add_symbol_file_command (char *, int);
+static void symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags,
+                                   objfile_flags flags, CORE_ADDR reloff);
 
 static const struct sym_fns *find_sym_fns (bfd *);
 
 
 static const struct sym_fns *find_sym_fns (bfd *);
 
-static void decrement_reading_symtab (void *);
-
 static void overlay_invalidate_all (void);
 
 static void overlay_invalidate_all (void);
 
-static void overlay_auto_command (char *, int);
-
-static void overlay_manual_command (char *, int);
-
-static void overlay_off_command (char *, int);
-
-static void overlay_load_command (char *, int);
-
-static void overlay_command (char *, int);
-
 static void simple_free_overlay_table (void);
 
 static void read_target_long_array (CORE_ADDR, unsigned int *, int, int,
 static void simple_free_overlay_table (void);
 
 static void read_target_long_array (CORE_ADDR, unsigned int *, int, int,
@@ -114,32 +106,26 @@ static int simple_read_overlay_table (void);
 
 static int simple_overlay_update_1 (struct obj_section *);
 
 
 static int simple_overlay_update_1 (struct obj_section *);
 
-static void add_filename_language (char *ext, enum language lang);
-
-static void info_ext_lang_command (char *args, int from_tty);
-
-static void init_filename_language_table (void);
-
 static void symfile_find_segment_sections (struct objfile *objfile);
 
 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
    calls add_symtab_fns() to register information on each format it is
    prepared to read.  */
 
 /* List of all available sym_fns.  On gdb startup, each object file reader
    calls add_symtab_fns() to register information on each format it is
    prepared to read.  */
 
-typedef struct
+struct registered_sym_fns
 {
 {
+  registered_sym_fns (bfd_flavour sym_flavour_, const struct sym_fns *sym_fns_)
+  : sym_flavour (sym_flavour_), sym_fns (sym_fns_)
+  {}
+
   /* BFD flavour that we handle.  */
   enum bfd_flavour sym_flavour;
 
   /* The "vtable" of symbol functions.  */
   const struct sym_fns *sym_fns;
   /* BFD flavour that we handle.  */
   enum bfd_flavour sym_flavour;
 
   /* The "vtable" of symbol functions.  */
   const struct sym_fns *sym_fns;
-} registered_sym_fns;
-
-DEF_VEC_O (registered_sym_fns);
+};
 
 
-static VEC (registered_sym_fns) *symtab_fns = NULL;
+static std::vector<registered_sym_fns> symtab_fns;
 
 /* Values for "set print symbol-loading".  */
 
 
 /* Values for "set print symbol-loading".  */
 
@@ -155,17 +141,9 @@ static const char *print_symbol_loading_enums[] =
 };
 static const char *print_symbol_loading = print_symbol_loading_full;
 
 };
 static const char *print_symbol_loading = print_symbol_loading_full;
 
-/* If non-zero, shared library symbols will be added automatically
-   when the inferior is created, new libraries are loaded, or when
-   attaching to the inferior.  This is almost always what users will
-   want to have happen; but for very large programs, the startup time
-   will be excessive, and so if this is a problem, the user can clear
-   this flag and then add the shared library symbols as needed.  Note
-   that there is a potential for confusion, since if the shared
-   library symbols are not loaded, commands like "info fun" will *not*
-   report all the functions that are actually present.  */
-
-int auto_solib_add = 1;
+/* See symfile.h.  */
+
+bool auto_solib_add = true;
 \f
 
 /* Return non-zero if symbol-loading messages should be printed.
 \f
 
 /* Return non-zero if symbol-loading messages should be printed.
@@ -197,22 +175,15 @@ print_symbol_loading_p (int from_tty, int exec, int full)
 
 int currently_reading_symtab = 0;
 
 
 int currently_reading_symtab = 0;
 
-static void
-decrement_reading_symtab (void *dummy)
-{
-  currently_reading_symtab--;
-  gdb_assert (currently_reading_symtab >= 0);
-}
-
 /* Increment currently_reading_symtab and return a cleanup that can be
    used to decrement it.  */
 
 /* Increment currently_reading_symtab and return a cleanup that can be
    used to decrement it.  */
 
-struct cleanup *
+scoped_restore_tmpl<int>
 increment_reading_symtab (void)
 {
 increment_reading_symtab (void)
 {
-  ++currently_reading_symtab;
-  gdb_assert (currently_reading_symtab > 0);
-  return make_cleanup (decrement_reading_symtab, NULL);
+  gdb_assert (currently_reading_symtab >= 0);
+  return make_scoped_restore (&currently_reading_symtab,
+                             currently_reading_symtab + 1);
 }
 
 /* Remember the lowest-addressed loadable section we've seen.
 }
 
 /* Remember the lowest-addressed loadable section we've seen.
@@ -229,126 +200,80 @@ find_lowest_section (bfd *abfd, asection *sect, void *obj)
 {
   asection **lowest = (asection **) obj;
 
 {
   asection **lowest = (asection **) obj;
 
-  if (0 == (bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD)))
+  if (0 == (bfd_section_flags (sect) & (SEC_ALLOC | SEC_LOAD)))
     return;
   if (!*lowest)
     *lowest = sect;            /* First loadable section */
     return;
   if (!*lowest)
     *lowest = sect;            /* First loadable section */
-  else if (bfd_section_vma (abfd, *lowest) > bfd_section_vma (abfd, sect))
+  else if (bfd_section_vma (*lowest) > bfd_section_vma (sect))
     *lowest = sect;            /* A lower loadable section */
     *lowest = sect;            /* A lower loadable section */
-  else if (bfd_section_vma (abfd, *lowest) == bfd_section_vma (abfd, sect)
-          && (bfd_section_size (abfd, (*lowest))
-              <= bfd_section_size (abfd, sect)))
+  else if (bfd_section_vma (*lowest) == bfd_section_vma (sect)
+          && (bfd_section_size (*lowest) <= bfd_section_size (sect)))
     *lowest = sect;
 }
 
     *lowest = sect;
 }
 
-/* Create a new section_addr_info, with room for NUM_SECTIONS.  The
-   new object's 'num_sections' field is set to 0; it must be updated
-   by the caller.  */
-
-struct section_addr_info *
-alloc_section_addr_info (size_t num_sections)
-{
-  struct section_addr_info *sap;
-  size_t size;
-
-  size = (sizeof (struct section_addr_info)
-         +  sizeof (struct other_sections) * (num_sections - 1));
-  sap = (struct section_addr_info *) xmalloc (size);
-  memset (sap, 0, size);
-
-  return sap;
-}
-
 /* Build (allocate and populate) a section_addr_info struct from
    an existing section table.  */
 
 /* Build (allocate and populate) a section_addr_info struct from
    an existing section table.  */
 
-extern struct section_addr_info *
+section_addr_info
 build_section_addr_info_from_section_table (const struct target_section *start,
                                             const struct target_section *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 target_section *stp;
   const struct target_section *stp;
-  int oidx;
 
 
-  sap = alloc_section_addr_info (end - start);
+  section_addr_info sap;
 
 
-  for (stp = start, oidx = 0; stp != end; stp++)
+  for (stp = start; stp != end; stp++)
     {
       struct bfd_section *asect = stp->the_bfd_section;
       bfd *abfd = asect->owner;
 
     {
       struct bfd_section *asect = stp->the_bfd_section;
       bfd *abfd = asect->owner;
 
-      if (bfd_get_section_flags (abfd, asect) & (SEC_ALLOC | SEC_LOAD)
-         && oidx < end - start)
-       {
-         sap->other[oidx].addr = stp->addr;
-         sap->other[oidx].name = xstrdup (bfd_section_name (abfd, asect));
-         sap->other[oidx].sectindex = gdb_bfd_section_index (abfd, asect);
-         oidx++;
-       }
+      if (bfd_section_flags (asect) & (SEC_ALLOC | SEC_LOAD)
+         && sap.size () < end - start)
+       sap.emplace_back (stp->addr,
+                         bfd_section_name (asect),
+                         gdb_bfd_section_index (abfd, asect));
     }
 
     }
 
-  sap->num_sections = oidx;
-
   return sap;
 }
 
 /* Create a section_addr_info from section offsets in ABFD.  */
 
   return sap;
 }
 
 /* Create a section_addr_info from section offsets in ABFD.  */
 
-static struct section_addr_info *
+static section_addr_info
 build_section_addr_info_from_bfd (bfd *abfd)
 {
 build_section_addr_info_from_bfd (bfd *abfd)
 {
-  struct section_addr_info *sap;
-  int i;
   struct bfd_section *sec;
 
   struct bfd_section *sec;
 
-  sap = alloc_section_addr_info (bfd_count_sections (abfd));
-  for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next)
-    if (bfd_get_section_flags (abfd, sec) & (SEC_ALLOC | SEC_LOAD))
-      {
-       sap->other[i].addr = bfd_get_section_vma (abfd, sec);
-       sap->other[i].name = xstrdup (bfd_get_section_name (abfd, sec));
-       sap->other[i].sectindex = gdb_bfd_section_index (abfd, sec);
-       i++;
-      }
-
-  sap->num_sections = i;
+  section_addr_info sap;
+  for (sec = abfd->sections; sec != NULL; sec = sec->next)
+    if (bfd_section_flags (sec) & (SEC_ALLOC | SEC_LOAD))
+      sap.emplace_back (bfd_section_vma (sec),
+                       bfd_section_name (sec),
+                       gdb_bfd_section_index (abfd, sec));
 
   return sap;
 }
 
 /* Create a section_addr_info from section offsets in OBJFILE.  */
 
 
   return sap;
 }
 
 /* Create a section_addr_info from section offsets in OBJFILE.  */
 
-struct section_addr_info *
+section_addr_info
 build_section_addr_info_from_objfile (const struct objfile *objfile)
 {
 build_section_addr_info_from_objfile (const struct objfile *objfile)
 {
-  struct section_addr_info *sap;
   int i;
 
   /* Before reread_symbols gets rewritten it is not safe to call:
      gdb_assert (objfile->num_sections == bfd_count_sections (objfile->obfd));
      */
   int i;
 
   /* Before reread_symbols gets rewritten it is not safe to call:
      gdb_assert (objfile->num_sections == bfd_count_sections (objfile->obfd));
      */
-  sap = build_section_addr_info_from_bfd (objfile->obfd);
-  for (i = 0; i < sap->num_sections; i++)
+  section_addr_info sap = build_section_addr_info_from_bfd (objfile->obfd);
+  for (i = 0; i < sap.size (); i++)
     {
     {
-      int sectindex = sap->other[i].sectindex;
+      int sectindex = sap[i].sectindex;
 
 
-      sap->other[i].addr += objfile->section_offsets->offsets[sectindex];
+      sap[i].addr += objfile->section_offsets[sectindex];
     }
   return sap;
 }
 
     }
   return sap;
 }
 
-/* Free all memory allocated by build_section_addr_info_from_section_table.  */
-
-extern void
-free_section_addr_info (struct section_addr_info *sap)
-{
-  int idx;
-
-  for (idx = 0; idx < sap->num_sections; idx++)
-    xfree (sap->other[idx].name);
-  xfree (sap);
-}
-
 /* Initialize OBJFILE's sect_index_* members.  */
 
 static void
 /* Initialize OBJFILE's sect_index_* members.  */
 
 static void
@@ -390,14 +315,14 @@ init_objfile_sect_indices (struct objfile *objfile)
      later, e.g. by the remote qOffsets packet, and then this will
      be wrong!  That's why we try segments first.  */
 
      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++)
+  for (i = 0; i < objfile->section_offsets.size (); i++)
     {
     {
-      if (ANOFFSET (objfile->section_offsets, i) != 0)
+      if (objfile->section_offsets[i] != 0)
        {
          break;
        }
     }
        {
          break;
        }
     }
-  if (i == objfile->num_sections)
+  if (i == objfile->section_offsets.size ())
     {
       if (objfile->sect_index_text == -1)
        objfile->sect_index_text = 0;
     {
       if (objfile->sect_index_text == -1)
        objfile->sect_index_text = 0;
@@ -414,7 +339,7 @@ init_objfile_sect_indices (struct objfile *objfile)
 
 struct place_section_arg
 {
 
 struct place_section_arg
 {
-  struct section_offsets *offsets;
+  section_offsets *offsets;
   CORE_ADDR lowest;
 };
 
   CORE_ADDR lowest;
 };
 
@@ -424,13 +349,14 @@ struct place_section_arg
 static void
 place_section (bfd *abfd, asection *sect, void *obj)
 {
 static void
 place_section (bfd *abfd, asection *sect, void *obj)
 {
-  struct place_section_arg *arg = obj;
-  CORE_ADDR *offsets = arg->offsets->offsets, start_addr;
+  struct place_section_arg *arg = (struct place_section_arg *) obj;
+  section_offsets &offsets = *arg->offsets;
+  CORE_ADDR start_addr;
   int done;
   int done;
-  ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
+  ULONGEST align = ((ULONGEST) 1) << bfd_section_alignment (sect);
 
   /* We are only interested in allocated sections.  */
 
   /* We are only interested in allocated sections.  */
-  if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+  if ((bfd_section_flags (sect) & SEC_ALLOC) == 0)
     return;
 
   /* If the user specified an offset, honor it.  */
     return;
 
   /* If the user specified an offset, honor it.  */
@@ -454,7 +380,7 @@ place_section (bfd *abfd, asection *sect, void *obj)
          continue;
 
        /* We can only conflict with allocated sections.  */
          continue;
 
        /* We can only conflict with allocated sections.  */
-       if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
+       if ((bfd_section_flags (cur_sec) & SEC_ALLOC) == 0)
          continue;
 
        /* If the section offset is 0, either the section has not been placed
          continue;
 
        /* If the section offset is 0, either the section has not been placed
@@ -464,10 +390,10 @@ place_section (bfd *abfd, asection *sect, void *obj)
          continue;
 
        /* If this section would overlap us, then we must move up.  */
          continue;
 
        /* If this section would overlap us, then we must move up.  */
-       if (start_addr + bfd_get_section_size (sect) > offsets[indx]
-           && start_addr < offsets[indx] + bfd_get_section_size (cur_sec))
+       if (start_addr + bfd_section_size (sect) > offsets[indx]
+           && start_addr < offsets[indx] + bfd_section_size (cur_sec))
          {
          {
-           start_addr = offsets[indx] + bfd_get_section_size (cur_sec);
+           start_addr = offsets[indx] + bfd_section_size (cur_sec);
            start_addr = (start_addr + align - 1) & -align;
            done = 0;
            break;
            start_addr = (start_addr + align - 1) & -align;
            done = 0;
            break;
@@ -479,35 +405,33 @@ place_section (bfd *abfd, asection *sect, void *obj)
   while (!done);
 
   offsets[gdb_bfd_section_index (abfd, sect)] = start_addr;
   while (!done);
 
   offsets[gdb_bfd_section_index (abfd, sect)] = start_addr;
-  arg->lowest = start_addr + bfd_get_section_size (sect);
+  arg->lowest = start_addr + bfd_section_size (sect);
 }
 
 }
 
-/* Store struct section_addr_info as prepared (made relative and with SECTINDEX
-   filled-in) by addr_info_make_relative into SECTION_OFFSETS of NUM_SECTIONS
-   entries.  */
+/* Store section_addr_info as prepared (made relative and with SECTINDEX
+   filled-in) by addr_info_make_relative into SECTION_OFFSETS.  */
 
 void
 
 void
-relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
-                                      int num_sections,
-                                      const struct section_addr_info *addrs)
+relative_addr_info_to_section_offsets (section_offsets &section_offsets,
+                                      const section_addr_info &addrs)
 {
   int i;
 
 {
   int i;
 
-  memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections));
+  section_offsets.assign (section_offsets.size (), 0);
 
   /* Now calculate offsets for section that were specified by the caller.  */
 
   /* Now calculate offsets for section that were specified by the caller.  */
-  for (i = 0; i < addrs->num_sections; i++)
+  for (i = 0; i < addrs.size (); i++)
     {
       const struct other_sections *osp;
 
     {
       const struct other_sections *osp;
 
-      osp = &addrs->other[i];
+      osp = &addrs[i];
       if (osp->sectindex == -1)
        continue;
 
       /* Record all sections in offsets.  */
       /* The section_offsets in the objfile are here filled in using
          the BFD index.  */
       if (osp->sectindex == -1)
        continue;
 
       /* Record all sections in offsets.  */
       /* The section_offsets in the objfile are here filled in using
          the BFD index.  */
-      section_offsets->offsets[osp->sectindex] = osp->addr;
+      section_offsets[osp->sectindex] = osp->addr;
     }
 }
 
     }
 }
 
@@ -528,39 +452,36 @@ addr_section_name (const char *s)
   return s;
 }
 
   return s;
 }
 
-/* qsort comparator for addrs_section_sort.  Sort entries in ascending order by
-   their (name, sectindex) pair.  sectindex makes the sort by name stable.  */
+/* std::sort comparator for addrs_section_sort.  Sort entries in
+   ascending order by their (name, sectindex) pair.  sectindex makes
+   the sort by name stable.  */
 
 
-static int
-addrs_section_compar (const void *ap, const void *bp)
+static bool
+addrs_section_compar (const struct other_sections *a,
+                     const struct other_sections *b)
 {
 {
-  const struct other_sections *a = *((struct other_sections **) ap);
-  const struct other_sections *b = *((struct other_sections **) bp);
   int retval;
 
   int retval;
 
-  retval = strcmp (addr_section_name (a->name), addr_section_name (b->name));
-  if (retval)
-    return retval;
+  retval = strcmp (addr_section_name (a->name.c_str ()),
+                  addr_section_name (b->name.c_str ()));
+  if (retval != 0)
+    return retval < 0;
 
 
-  return a->sectindex - b->sectindex;
+  return a->sectindex < b->sectindex;
 }
 
 }
 
-/* Provide sorted array of pointers to sections of ADDRS.  The array is
-   terminated by NULL.  Caller is responsible to call xfree for it.  */
+/* Provide sorted array of pointers to sections of ADDRS.  */
 
 
-static struct other_sections **
-addrs_section_sort (struct section_addr_info *addrs)
+static std::vector<const struct other_sections *>
+addrs_section_sort (const section_addr_info &addrs)
 {
 {
-  struct other_sections **array;
   int i;
 
   int i;
 
-  /* `+ 1' for the NULL terminator.  */
-  array = xmalloc (sizeof (*array) * (addrs->num_sections + 1));
-  for (i = 0; i < addrs->num_sections; i++)
-    array[i] = &addrs->other[i];
-  array[i] = NULL;
+  std::vector<const struct other_sections *> array (addrs.size ());
+  for (i = 0; i < addrs.size (); i++)
+    array[i] = &addrs[i];
 
 
-  qsort (array, i, sizeof (*array), addrs_section_compar);
+  std::sort (array.begin (), array.end (), addrs_section_compar);
 
   return array;
 }
 
   return array;
 }
@@ -570,18 +491,14 @@ addrs_section_sort (struct section_addr_info *addrs)
    rebase ADDRS to start referencing different BFD than before.  */
 
 void
    rebase ADDRS to start referencing different BFD than before.  */
 
 void
-addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
+addr_info_make_relative (section_addr_info *addrs, bfd *abfd)
 {
   asection *lower_sect;
   CORE_ADDR lower_offset;
   int i;
 {
   asection *lower_sect;
   CORE_ADDR lower_offset;
   int i;
-  struct cleanup *my_cleanup;
-  struct section_addr_info *abfd_addrs;
-  struct other_sections **addrs_sorted, **abfd_addrs_sorted;
-  struct other_sections **addrs_to_abfd_addrs;
 
   /* Find lowest loadable section to be used as starting point for
 
   /* Find lowest loadable section to be used as starting point for
-     continguous sections.  */
+     contiguous sections.  */
   lower_sect = NULL;
   bfd_map_over_sections (abfd, find_lowest_section, &lower_sect);
   if (lower_sect == NULL)
   lower_sect = NULL;
   bfd_map_over_sections (abfd, find_lowest_section, &lower_sect);
   if (lower_sect == NULL)
@@ -591,7 +508,7 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
       lower_offset = 0;
     }
   else
       lower_offset = 0;
     }
   else
-    lower_offset = bfd_section_vma (bfd_get_filename (abfd), lower_sect);
+    lower_offset = bfd_section_vma (lower_sect);
 
   /* Create ADDRS_TO_ABFD_ADDRS array to map the sections in ADDRS to sections
      in ABFD.  Section names are not unique - there can be multiple sections of
 
   /* Create ADDRS_TO_ABFD_ADDRS array to map the sections in ADDRS to sections
      in ABFD.  Section names are not unique - there can be multiple sections of
@@ -603,46 +520,44 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
      Use stable sort by name for the sections in both files.  Then linearly
      scan both lists matching as most of the entries as possible.  */
 
      Use stable sort by name for the sections in both files.  Then linearly
      scan both lists matching as most of the entries as possible.  */
 
-  addrs_sorted = addrs_section_sort (addrs);
-  my_cleanup = make_cleanup (xfree, addrs_sorted);
+  std::vector<const struct other_sections *> addrs_sorted
+    = addrs_section_sort (*addrs);
 
 
-  abfd_addrs = build_section_addr_info_from_bfd (abfd);
-  make_cleanup_free_section_addr_info (abfd_addrs);
-  abfd_addrs_sorted = addrs_section_sort (abfd_addrs);
-  make_cleanup (xfree, abfd_addrs_sorted);
+  section_addr_info abfd_addrs = build_section_addr_info_from_bfd (abfd);
+  std::vector<const struct other_sections *> abfd_addrs_sorted
+    = addrs_section_sort (abfd_addrs);
 
   /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and
      ABFD_ADDRS_SORTED.  */
 
 
   /* Now create ADDRS_TO_ABFD_ADDRS from ADDRS_SORTED and
      ABFD_ADDRS_SORTED.  */
 
-  addrs_to_abfd_addrs = xzalloc (sizeof (*addrs_to_abfd_addrs)
-                                * addrs->num_sections);
-  make_cleanup (xfree, addrs_to_abfd_addrs);
+  std::vector<const struct other_sections *>
+    addrs_to_abfd_addrs (addrs->size (), nullptr);
 
 
-  while (*addrs_sorted)
+  std::vector<const struct other_sections *>::iterator abfd_sorted_iter
+    = abfd_addrs_sorted.begin ();
+  for (const other_sections *sect : addrs_sorted)
     {
     {
-      const char *sect_name = addr_section_name ((*addrs_sorted)->name);
+      const char *sect_name = addr_section_name (sect->name.c_str ());
 
 
-      while (*abfd_addrs_sorted
-            && strcmp (addr_section_name ((*abfd_addrs_sorted)->name),
+      while (abfd_sorted_iter != abfd_addrs_sorted.end ()
+            && strcmp (addr_section_name ((*abfd_sorted_iter)->name.c_str ()),
                        sect_name) < 0)
                        sect_name) < 0)
-       abfd_addrs_sorted++;
+       abfd_sorted_iter++;
 
 
-      if (*abfd_addrs_sorted
-         && strcmp (addr_section_name ((*abfd_addrs_sorted)->name),
+      if (abfd_sorted_iter != abfd_addrs_sorted.end ()
+         && strcmp (addr_section_name ((*abfd_sorted_iter)->name.c_str ()),
                     sect_name) == 0)
        {
          int index_in_addrs;
 
          /* Make the found item directly addressable from ADDRS.  */
                     sect_name) == 0)
        {
          int index_in_addrs;
 
          /* Make the found item directly addressable from ADDRS.  */
-         index_in_addrs = *addrs_sorted - addrs->other;
+         index_in_addrs = sect - addrs->data ();
          gdb_assert (addrs_to_abfd_addrs[index_in_addrs] == NULL);
          gdb_assert (addrs_to_abfd_addrs[index_in_addrs] == NULL);
-         addrs_to_abfd_addrs[index_in_addrs] = *abfd_addrs_sorted;
+         addrs_to_abfd_addrs[index_in_addrs] = *abfd_sorted_iter;
 
          /* Never use the same ABFD entry twice.  */
 
          /* Never use the same ABFD entry twice.  */
-         abfd_addrs_sorted++;
+         abfd_sorted_iter++;
        }
        }
-
-      addrs_sorted++;
     }
 
   /* Calculate offsets for the loadable sections.
     }
 
   /* Calculate offsets for the loadable sections.
@@ -655,27 +570,27 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
      (the loadable section directly below it in memory).
      this_offset = lower_offset = lower_addr - lower_orig_addr */
 
      (the loadable section directly below it in memory).
      this_offset = lower_offset = lower_addr - lower_orig_addr */
 
-  for (i = 0; i < addrs->num_sections; i++)
+  for (i = 0; i < addrs->size (); i++)
     {
     {
-      struct other_sections *sect = addrs_to_abfd_addrs[i];
+      const struct other_sections *sect = addrs_to_abfd_addrs[i];
 
       if (sect)
        {
          /* This is the index used by BFD.  */
 
       if (sect)
        {
          /* This is the index used by BFD.  */
-         addrs->other[i].sectindex = sect->sectindex;
+         (*addrs)[i].sectindex = sect->sectindex;
 
 
-         if (addrs->other[i].addr != 0)
+         if ((*addrs)[i].addr != 0)
            {
            {
-             addrs->other[i].addr -= sect->addr;
-             lower_offset = addrs->other[i].addr;
+             (*addrs)[i].addr -= sect->addr;
+             lower_offset = (*addrs)[i].addr;
            }
          else
            }
          else
-           addrs->other[i].addr = lower_offset;
+           (*addrs)[i].addr = lower_offset;
        }
       else
        {
          /* addr_section_name transformation is not used for SECT_NAME.  */
        }
       else
        {
          /* addr_section_name transformation is not used for SECT_NAME.  */
-         const char *sect_name = addrs->other[i].name;
+         const std::string &sect_name = (*addrs)[i].name;
 
          /* This section does not exist in ABFD, which is normally
             unexpected and we want to issue a warning.
 
          /* This section does not exist in ABFD, which is normally
             unexpected and we want to issue a warning.
@@ -691,25 +606,23 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 
             For the sections `.bss' and `.sbss' see addr_section_name.  */
 
 
             For the sections `.bss' and `.sbss' see addr_section_name.  */
 
-         if (!(strcmp (sect_name, ".gnu.liblist") == 0
-               || strcmp (sect_name, ".gnu.conflict") == 0
-               || (strcmp (sect_name, ".bss") == 0
+         if (!(sect_name == ".gnu.liblist"
+               || sect_name == ".gnu.conflict"
+               || (sect_name == ".bss"
                    && i > 0
                    && i > 0
-                   && strcmp (addrs->other[i - 1].name, ".dynbss") == 0
+                   && (*addrs)[i - 1].name == ".dynbss"
                    && addrs_to_abfd_addrs[i - 1] != NULL)
                    && addrs_to_abfd_addrs[i - 1] != NULL)
-               || (strcmp (sect_name, ".sbss") == 0
+               || (sect_name == ".sbss"
                    && i > 0
                    && i > 0
-                   && strcmp (addrs->other[i - 1].name, ".sdynbss") == 0
+                   && (*addrs)[i - 1].name == ".sdynbss"
                    && addrs_to_abfd_addrs[i - 1] != NULL)))
                    && addrs_to_abfd_addrs[i - 1] != NULL)))
-           warning (_("section %s not found in %s"), sect_name,
+           warning (_("section %s not found in %s"), sect_name.c_str (),
                     bfd_get_filename (abfd));
 
                     bfd_get_filename (abfd));
 
-         addrs->other[i].addr = 0;
-         addrs->other[i].sectindex = -1;
+         (*addrs)[i].addr = 0;
+         (*addrs)[i].sectindex = -1;
        }
     }
        }
     }
-
-  do_cleanups (my_cleanup);
 }
 
 /* Parse the user's idea of an offset for dynamic linking, into our idea
 }
 
 /* Parse the user's idea of an offset for dynamic linking, into our idea
@@ -720,14 +633,10 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 
 void
 default_symfile_offsets (struct objfile *objfile,
 
 void
 default_symfile_offsets (struct objfile *objfile,
-                        const struct section_addr_info *addrs)
+                        const section_addr_info &addrs)
 {
 {
-  objfile->num_sections = gdb_bfd_count_sections (objfile->obfd);
-  objfile->section_offsets = (struct section_offsets *)
-    obstack_alloc (&objfile->objfile_obstack,
-                  SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
-  relative_addr_info_to_section_offsets (objfile->section_offsets,
-                                        objfile->num_sections, addrs);
+  objfile->section_offsets.resize (gdb_bfd_count_sections (objfile->obfd));
+  relative_addr_info_to_section_offsets (objfile->section_offsets, addrs);
 
   /* For relocatable files, all loadable sections will start at zero.
      The zero is meaningless, so try to pick arbitrary addresses such
 
   /* For relocatable files, all loadable sections will start at zero.
      The zero is meaningless, so try to pick arbitrary addresses such
@@ -743,16 +652,16 @@ default_symfile_offsets (struct objfile *objfile,
       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.  */
       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)
+       if (bfd_section_vma (cur_sec) != 0)
          break;
 
       if (cur_sec == NULL)
        {
          break;
 
       if (cur_sec == NULL)
        {
-         CORE_ADDR *offsets = objfile->section_offsets->offsets;
+         section_offsets &offsets = objfile->section_offsets;
 
          /* Pick non-overlapping offsets for sections the user did not
             place explicitly.  */
 
          /* Pick non-overlapping offsets for sections the user did not
             place explicitly.  */
-         arg.offsets = objfile->section_offsets;
+         arg.offsets = &objfile->section_offsets;
          arg.lowest = 0;
          bfd_map_over_sections (objfile->obfd, place_section, &arg);
 
          arg.lowest = 0;
          bfd_map_over_sections (objfile->obfd, place_section, &arg);
 
@@ -785,10 +694,10 @@ default_symfile_offsets (struct objfile *objfile,
          for (cur_sec = abfd->sections; cur_sec != NULL;
               cur_sec = cur_sec->next)
            {
          for (cur_sec = abfd->sections; cur_sec != NULL;
               cur_sec = cur_sec->next)
            {
-             if ((bfd_get_section_flags (abfd, cur_sec) & SEC_ALLOC) == 0)
+             if ((bfd_section_flags (cur_sec) & SEC_ALLOC) == 0)
                continue;
 
                continue;
 
-             bfd_set_section_vma (abfd, cur_sec, offsets[cur_sec->index]);
+             bfd_set_section_vma (cur_sec, offsets[cur_sec->index]);
              exec_set_section_address (bfd_get_filename (abfd),
                                        cur_sec->index,
                                        offsets[cur_sec->index]);
              exec_set_section_address (bfd_get_filename (abfd),
                                        cur_sec->index,
                                        offsets[cur_sec->index]);
@@ -808,12 +717,11 @@ default_symfile_offsets (struct objfile *objfile,
    It assumes that object files do not have segments, and fully linked
    files have a single segment.  */
 
    It assumes that object files do not have segments, and fully linked
    files have a single segment.  */
 
-struct symfile_segment_data *
+symfile_segment_data_up
 default_symfile_segments (bfd *abfd)
 {
   int num_sections, i;
   asection *sect;
 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
   CORE_ADDR low, high;
 
   /* Relocatable files contain enough information to position each
@@ -825,7 +733,7 @@ default_symfile_segments (bfd *abfd)
   /* Make sure there is at least one loadable section in the file.  */
   for (sect = abfd->sections; sect != NULL; sect = sect->next)
     {
   /* 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)
+      if ((bfd_section_flags (sect) & SEC_ALLOC) == 0)
        continue;
 
       break;
        continue;
 
       break;
@@ -833,35 +741,33 @@ default_symfile_segments (bfd *abfd)
   if (sect == NULL)
     return NULL;
 
   if (sect == NULL)
     return NULL;
 
-  low = bfd_get_section_vma (abfd, sect);
-  high = low + bfd_get_section_size (sect);
+  low = bfd_section_vma (sect);
+  high = low + bfd_section_size (sect);
 
 
-  data = XCNEW (struct symfile_segment_data);
-  data->num_segments = 1;
-  data->segment_bases = XCNEW (CORE_ADDR);
-  data->segment_sizes = XCNEW (CORE_ADDR);
+  symfile_segment_data_up data (new symfile_segment_data);
 
   num_sections = bfd_count_sections (abfd);
 
   num_sections = bfd_count_sections (abfd);
-  data->segment_info = XCNEWVEC (int, num_sections);
+
+  /* All elements are initialized to 0 (map to no segment).  */
+  data->segment_info.resize (num_sections);
 
   for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
     {
       CORE_ADDR vma;
 
 
   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)
+      if ((bfd_section_flags (sect) & SEC_ALLOC) == 0)
        continue;
 
        continue;
 
-      vma = bfd_get_section_vma (abfd, sect);
+      vma = bfd_section_vma (sect);
       if (vma < low)
        low = vma;
       if (vma < low)
        low = vma;
-      if (vma + bfd_get_section_size (sect) > high)
-       high = vma + bfd_get_section_size (sect);
+      if (vma + bfd_section_size (sect) > high)
+       high = vma + bfd_section_size (sect);
 
       data->segment_info[i] = 1;
     }
 
 
       data->segment_info[i] = 1;
     }
 
-  data->segment_bases[0] = low;
-  data->segment_sizes[0] = high - low;
+  data->segments.emplace_back (low, high - low);
 
   return data;
 }
 
   return data;
 }
@@ -870,10 +776,10 @@ default_symfile_segments (bfd *abfd)
    possibly force the partial symbols to be read.  */
 
 static void
    possibly force the partial symbols to be read.  */
 
 static void
-read_symbols (struct objfile *objfile, int add_flags)
+read_symbols (struct objfile *objfile, symfile_add_flags add_flags)
 {
   (*objfile->sf->sym_read) (objfile, add_flags);
 {
   (*objfile->sf->sym_read) (objfile, add_flags);
-  objfile->per_bfd->minsyms_read = 1;
+  objfile->per_bfd->minsyms_read = true;
 
   /* find_separate_debug_file_in_section should be called only if there is
      single binary with no existing separate debug info file.  */
 
   /* find_separate_debug_file_in_section should be called only if there is
      single binary with no existing separate debug info file.  */
@@ -881,8 +787,7 @@ read_symbols (struct objfile *objfile, int add_flags)
       && objfile->separate_debug_objfile == NULL
       && objfile->separate_debug_objfile_backlink == NULL)
     {
       && objfile->separate_debug_objfile == NULL
       && objfile->separate_debug_objfile_backlink == NULL)
     {
-      bfd *abfd = find_separate_debug_file_in_section (objfile);
-      struct cleanup *cleanup = make_cleanup_bfd_unref (abfd);
+      gdb_bfd_ref_ptr abfd (find_separate_debug_file_in_section (objfile));
 
       if (abfd != NULL)
        {
 
       if (abfd != NULL)
        {
@@ -890,14 +795,13 @@ read_symbols (struct objfile *objfile, int add_flags)
             virtual section-as-bfd like the bfd filename containing the
             section.  Therefore use also non-canonical name form for the same
             file containing the section.  */
             virtual section-as-bfd like the bfd filename containing the
             section.  Therefore use also non-canonical name form for the same
             file containing the section.  */
-         symbol_file_add_separate (abfd, objfile->original_name, add_flags,
-                                   objfile);
+         symbol_file_add_separate (abfd.get (),
+                                   bfd_get_filename (abfd.get ()),
+                                   add_flags | SYMFILE_NOT_FILENAME, objfile);
        }
        }
-
-      do_cleanups (cleanup);
     }
   if ((add_flags & SYMFILE_NO_READ) == 0)
     }
   if ((add_flags & SYMFILE_NO_READ) == 0)
-    require_partial_symbols (objfile, 0);
+    require_partial_symbols (objfile, false);
 }
 
 /* Initialize entry point information for this objfile.  */
 }
 
 /* Initialize entry point information for this objfile.  */
@@ -945,23 +849,23 @@ init_entry_point_info (struct objfile *objfile)
       /* Make certain that the address points at real code, and not a
         function descriptor.  */
       entry_point
       /* Make certain that the address points at real code, and not a
         function descriptor.  */
       entry_point
-       = gdbarch_convert_from_func_ptr_addr (get_objfile_arch (objfile),
+       = gdbarch_convert_from_func_ptr_addr (objfile->arch (),
                                              entry_point,
                                              entry_point,
-                                             &current_target);
+                                             current_top_target ());
 
       /* Remove any ISA markers, so that this matches entries in the
         symbol table.  */
       ei->entry_point
 
       /* Remove any ISA markers, so that this matches entries in the
         symbol table.  */
       ei->entry_point
-       = gdbarch_addr_bits_remove (get_objfile_arch (objfile), entry_point);
+       = gdbarch_addr_bits_remove (objfile->arch (), entry_point);
 
       found = 0;
       ALL_OBJFILE_OSECTIONS (objfile, osect)
        {
          struct bfd_section *sect = osect->the_bfd_section;
 
 
       found = 0;
       ALL_OBJFILE_OSECTIONS (objfile, osect)
        {
          struct bfd_section *sect = osect->the_bfd_section;
 
-         if (entry_point >= bfd_get_section_vma (objfile->obfd, sect)
-             && entry_point < (bfd_get_section_vma (objfile->obfd, sect)
-                               + bfd_get_section_size (sect)))
+         if (entry_point >= bfd_section_vma (sect)
+             && entry_point < (bfd_section_vma (sect)
+                               + bfd_section_size (sect)))
            {
              ei->the_bfd_section_index
                = gdb_bfd_section_index (objfile->obfd, sect);
            {
              ei->the_bfd_section_index
                = gdb_bfd_section_index (objfile->obfd, sect);
@@ -990,19 +894,21 @@ init_entry_point_info (struct objfile *objfile)
    (as gleaned by GDB's shared library code).  We convert each address
    into an offset from the section VMA's as it appears in the object
    file, and then call the file's sym_offsets function to convert this
    (as gleaned by GDB's shared library code).  We convert each address
    into an offset from the section VMA's as it appears in the object
    file, and then call the file's sym_offsets function to convert this
-   into a format-specific offset table --- a `struct section_offsets'.
+   into a format-specific offset table --- a `section_offsets'.
+   The sectindex field is used to control the ordering of sections
+   with the same name.  Upon return, it is updated to contain the
+   corresponding BFD section index, or -1 if the section was not found.
 
    ADD_FLAGS encodes verbosity level, whether this is main symbol or
 
    ADD_FLAGS encodes verbosity level, whether this is main symbol or
-   an extra symbol file such as dynamically loaded code, and wether
+   an extra symbol file such as dynamically loaded code, and whether
    breakpoint reset should be deferred.  */
 
 static void
 syms_from_objfile_1 (struct objfile *objfile,
    breakpoint reset should be deferred.  */
 
 static void
 syms_from_objfile_1 (struct objfile *objfile,
-                    struct section_addr_info *addrs,
-                    int add_flags)
+                    section_addr_info *addrs,
+                    symfile_add_flags add_flags)
 {
 {
-  struct section_addr_info *local_addr = NULL;
-  struct cleanup *old_chain;
+  section_addr_info local_addr;
   const int mainline = add_flags & SYMFILE_MAINLINE;
 
   objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
   const int mainline = add_flags & SYMFILE_MAINLINE;
 
   objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
@@ -1012,40 +918,34 @@ syms_from_objfile_1 (struct objfile *objfile,
       /* No symbols to load, but we still need to make sure
         that the section_offsets table is allocated.  */
       int num_sections = gdb_bfd_count_sections (objfile->obfd);
       /* No symbols to load, but we still need to make sure
         that the section_offsets table is allocated.  */
       int num_sections = gdb_bfd_count_sections (objfile->obfd);
-      size_t size = SIZEOF_N_SECTION_OFFSETS (num_sections);
 
 
-      objfile->num_sections = num_sections;
-      objfile->section_offsets
-        = obstack_alloc (&objfile->objfile_obstack, size);
-      memset (objfile->section_offsets, 0, size);
+      objfile->section_offsets.assign (num_sections, 0);
       return;
     }
 
   /* Make sure that partially constructed symbol tables will be cleaned up
      if an error occurs during symbol reading.  */
       return;
     }
 
   /* Make sure that partially constructed symbol tables will be cleaned up
      if an error occurs during symbol reading.  */
-  old_chain = make_cleanup_free_objfile (objfile);
+  gdb::optional<clear_symtab_users_cleanup> defer_clear_users;
+
+  objfile_up objfile_holder (objfile);
 
   /* If ADDRS is NULL, put together a dummy address list.
      We now establish the convention that an addr of zero means
      no load address was specified.  */
   if (! addrs)
 
   /* If ADDRS is NULL, put together a dummy address list.
      We now establish the convention that an addr of zero means
      no load address was specified.  */
   if (! addrs)
-    {
-      local_addr = alloc_section_addr_info (1);
-      make_cleanup (xfree, local_addr);
-      addrs = local_addr;
-    }
+    addrs = &local_addr;
 
   if (mainline)
     {
       /* We will modify the main symbol table, make sure that all its users
          will be cleaned up if an error occurs during symbol reading.  */
 
   if (mainline)
     {
       /* We will modify the main symbol table, make sure that all its users
          will be cleaned up if an error occurs during symbol reading.  */
-      make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
+      defer_clear_users.emplace ((symfile_add_flag) 0);
 
       /* Since no error yet, throw away the old symbol table.  */
 
       if (symfile_objfile != NULL)
        {
 
       /* Since no error yet, throw away the old symbol table.  */
 
       if (symfile_objfile != NULL)
        {
-         free_objfile (symfile_objfile);
+         symfile_objfile->unlink ();
          gdb_assert (symfile_objfile == NULL);
        }
 
          gdb_assert (symfile_objfile == NULL);
        }
 
@@ -1063,7 +963,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 
      We no longer warn if the lowest section is not a text segment (as
      happens for the PA64 port.  */
 
      We no longer warn if the lowest section is not a text segment (as
      happens for the PA64 port.  */
-  if (addrs->num_sections > 0)
+  if (addrs->size () > 0)
     addr_info_make_relative (addrs, objfile->obfd);
 
   /* Initialize symbol reading routines for this objfile, allow complaints to
     addr_info_make_relative (addrs, objfile->obfd);
 
   /* Initialize symbol reading routines for this objfile, allow complaints to
@@ -1071,16 +971,17 @@ syms_from_objfile_1 (struct objfile *objfile,
      initial symbol reading for this file.  */
 
   (*objfile->sf->sym_init) (objfile);
      initial symbol reading for this file.  */
 
   (*objfile->sf->sym_init) (objfile);
-  clear_complaints (&symfile_complaints, 1, add_flags & SYMFILE_VERBOSE);
+  clear_complaints ();
 
 
-  (*objfile->sf->sym_offsets) (objfile, addrs);
+  (*objfile->sf->sym_offsets) (objfile, *addrs);
 
   read_symbols (objfile, add_flags);
 
   /* Discard cleanups as symbol reading was successful.  */
 
 
   read_symbols (objfile, add_flags);
 
   /* Discard cleanups as symbol reading was successful.  */
 
-  discard_cleanups (old_chain);
-  xfree (local_addr);
+  objfile_holder.release ();
+  if (defer_clear_users)
+    defer_clear_users->release ();
 }
 
 /* Same as syms_from_objfile_1, but also initializes the objfile
 }
 
 /* Same as syms_from_objfile_1, but also initializes the objfile
@@ -1088,8 +989,8 @@ syms_from_objfile_1 (struct objfile *objfile,
 
 static void
 syms_from_objfile (struct objfile *objfile,
 
 static void
 syms_from_objfile (struct objfile *objfile,
-                  struct section_addr_info *addrs,
-                  int add_flags)
+                  section_addr_info *addrs,
+                  symfile_add_flags add_flags)
 {
   syms_from_objfile_1 (objfile, addrs, add_flags);
   init_entry_point_info (objfile);
 {
   syms_from_objfile_1 (objfile, addrs, add_flags);
   init_entry_point_info (objfile);
@@ -1099,8 +1000,8 @@ syms_from_objfile (struct objfile *objfile,
    symbols for a new objfile, or mapping in the symbols from a reusable
    objfile.  ADD_FLAGS is a bitmask of enum symfile_add_flags.  */
 
    symbols for a new objfile, or mapping in the symbols from a reusable
    objfile.  ADD_FLAGS is a bitmask of enum symfile_add_flags.  */
 
-void
-new_symfile_objfile (struct objfile *objfile, int add_flags)
+static void
+finish_new_objfile (struct objfile *objfile, symfile_add_flags add_flags)
 {
   /* If this is the main symbol file we have to clean up all users of the
      old main symbol file.  Otherwise it is sufficient to fixup all the
 {
   /* If this is the main symbol file we have to clean up all users of the
      old main symbol file.  Otherwise it is sufficient to fixup all the
@@ -1118,7 +1019,7 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
     }
 
   /* We're done reading the symbol file; finish off complaints.  */
     }
 
   /* We're done reading the symbol file; finish off complaints.  */
-  clear_complaints (&symfile_complaints, 0, add_flags & SYMFILE_VERBOSE);
+  clear_complaints ();
 }
 
 /* Process a symbol file, as either the main file or as a dynamically
 }
 
 /* Process a symbol file, as either the main file or as a dynamically
@@ -1127,10 +1028,10 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
    ABFD is a BFD already open on the file, as from symfile_bfd_open.
    A new reference is acquired by this function.
 
    ABFD is a BFD already open on the file, as from symfile_bfd_open.
    A new reference is acquired by this function.
 
-   For NAME description see allocate_objfile's definition.
+   For NAME description see the objfile constructor.
 
    ADD_FLAGS encodes verbosity, whether this is main symbol file or
 
    ADD_FLAGS encodes verbosity, whether this is main symbol file or
-   extra, such as dynamically loaded code, and what to do with breakpoins.
+   extra, such as dynamically loaded code, and what to do with breakpoints.
 
    ADDRS is as described for syms_from_objfile_1, above.
    ADDRS is ignored when SYMFILE_MAINLINE bit is set in ADD_FLAGS.
 
    ADDRS is as described for syms_from_objfile_1, above.
    ADDRS is ignored when SYMFILE_MAINLINE bit is set in ADD_FLAGS.
@@ -1142,9 +1043,10 @@ new_symfile_objfile (struct objfile *objfile, int add_flags)
    Upon failure, jumps back to command level (never returns).  */
 
 static struct objfile *
    Upon failure, jumps back to command level (never returns).  */
 
 static struct objfile *
-symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
-                           struct section_addr_info *addrs,
-                           int flags, struct objfile *parent)
+symbol_file_add_with_addrs (bfd *abfd, const char *name,
+                           symfile_add_flags add_flags,
+                           section_addr_info *addrs,
+                           objfile_flags flags, struct objfile *parent)
 {
   struct objfile *objfile;
   const int from_tty = add_flags & SYMFILE_VERBOSE;
 {
   struct objfile *objfile;
   const int from_tty = add_flags & SYMFILE_VERBOSE;
@@ -1158,6 +1060,14 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
       flags |= OBJF_READNOW;
       add_flags &= ~SYMFILE_NO_READ;
     }
       flags |= OBJF_READNOW;
       add_flags &= ~SYMFILE_NO_READ;
     }
+  else if (readnever_symbol_files
+          || (parent != NULL && (parent->flags & OBJF_READNEVER)))
+    {
+      flags |= OBJF_READNEVER;
+      add_flags |= SYMFILE_NO_READ;
+    }
+  if ((add_flags & SYMFILE_NOT_FILENAME) != 0)
+    flags |= OBJF_NOT_FILENAME;
 
   /* Give user a chance to burp if we'd be
      interactively wiping out any existing symbols.  */
 
   /* Give user a chance to burp if we'd be
      interactively wiping out any existing symbols.  */
@@ -1168,11 +1078,9 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
       && !query (_("Load new symbol table from \"%s\"? "), name))
     error (_("Not confirmed."));
 
       && !query (_("Load new symbol table from \"%s\"? "), name))
     error (_("Not confirmed."));
 
-  objfile = allocate_objfile (abfd, name,
-                             flags | (mainline ? OBJF_MAINLINE : 0));
-
-  if (parent)
-    add_separate_debug_objfile (objfile, parent);
+  if (mainline)
+    flags |= OBJF_MAINLINE;
+  objfile = objfile::make (abfd, name, flags, parent);
 
   /* We either created a new mapped symbol table, mapped an existing
      symbol table file which has not had initial symbol reading
 
   /* We either created a new mapped symbol table, mapped an existing
      symbol table file which has not had initial symbol reading
@@ -1182,11 +1090,8 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
       if (deprecated_pre_add_symbol_hook)
        deprecated_pre_add_symbol_hook (name);
       else
       if (deprecated_pre_add_symbol_hook)
        deprecated_pre_add_symbol_hook (name);
       else
-       {
-         printf_unfiltered (_("Reading symbols from %s..."), name);
-         wrap_here ("");
-         gdb_flush (gdb_stdout);
-       }
+       printf_filtered (_("Reading symbols from %ps...\n"),
+                        styled_string (file_name_style.style (), name));
     }
   syms_from_objfile (objfile, addrs, add_flags);
 
     }
   syms_from_objfile (objfile, addrs, add_flags);
 
@@ -1198,29 +1103,26 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
   if ((flags & OBJF_READNOW))
     {
       if (should_print)
   if ((flags & OBJF_READNOW))
     {
       if (should_print)
-       {
-         printf_unfiltered (_("expanding to full symbols..."));
-         wrap_here ("");
-         gdb_flush (gdb_stdout);
-       }
+       printf_filtered (_("Expanding full symbols from %ps...\n"),
+                        styled_string (file_name_style.style (), name));
 
       if (objfile->sf)
        objfile->sf->qf->expand_all_symtabs (objfile);
     }
 
 
       if (objfile->sf)
        objfile->sf->qf->expand_all_symtabs (objfile);
     }
 
-  if (should_print && !objfile_has_symbols (objfile))
-    {
-      wrap_here ("");
-      printf_unfiltered (_("(no debugging symbols found)..."));
-      wrap_here ("");
-    }
+  /* Note that we only print a message if we have no symbols and have
+     no separate debug file.  If there is a separate debug file which
+     does not have symbols, we'll have emitted this message for that
+     file, and so printing it twice is just redundant.  */
+  if (should_print && !objfile_has_symbols (objfile)
+      && objfile->separate_debug_objfile == nullptr)
+    printf_filtered (_("(No debugging symbols found in %ps)\n"),
+                    styled_string (file_name_style.style (), name));
 
   if (should_print)
     {
       if (deprecated_post_add_symbol_hook)
        deprecated_post_add_symbol_hook ();
 
   if (should_print)
     {
       if (deprecated_post_add_symbol_hook)
        deprecated_post_add_symbol_hook ();
-      else
-       printf_unfiltered (_("done.\n"));
     }
 
   /* We print some messages regardless of whether 'from_tty ||
     }
 
   /* We print some messages regardless of whether 'from_tty ||
@@ -1230,42 +1132,36 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
 
   if (objfile->sf == NULL)
     {
 
   if (objfile->sf == NULL)
     {
-      observer_notify_new_objfile (objfile);
+      gdb::observers::new_objfile.notify (objfile);
       return objfile;  /* No symbols.  */
     }
 
       return objfile;  /* No symbols.  */
     }
 
-  new_symfile_objfile (objfile, add_flags);
+  finish_new_objfile (objfile, add_flags);
 
 
-  observer_notify_new_objfile (objfile);
+  gdb::observers::new_objfile.notify (objfile);
 
   bfd_cache_close_all ();
   return (objfile);
 }
 
 /* Add BFD as a separate debug file for OBJFILE.  For NAME description
 
   bfd_cache_close_all ();
   return (objfile);
 }
 
 /* Add BFD as a separate debug file for OBJFILE.  For NAME description
-   see allocate_objfile's definition.  */
+   see the objfile constructor.  */
 
 void
 
 void
-symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags,
+symbol_file_add_separate (bfd *bfd, const char *name,
+                         symfile_add_flags symfile_flags,
                          struct objfile *objfile)
 {
                          struct objfile *objfile)
 {
-  struct objfile *new_objfile;
-  struct section_addr_info *sap;
-  struct cleanup *my_cleanup;
-
   /* Create section_addr_info.  We can't directly use offsets from OBJFILE
      because sections of BFD may not match sections of OBJFILE and because
      vma may have been modified by tools such as prelink.  */
   /* Create section_addr_info.  We can't directly use offsets from OBJFILE
      because sections of BFD may not match sections of OBJFILE and because
      vma may have been modified by tools such as prelink.  */
-  sap = build_section_addr_info_from_objfile (objfile);
-  my_cleanup = make_cleanup_free_section_addr_info (sap);
+  section_addr_info sap = build_section_addr_info_from_objfile (objfile);
 
 
-  new_objfile = symbol_file_add_with_addrs
-    (bfd, name, symfile_flags, sap,
+  symbol_file_add_with_addrs
+    (bfd, name, symfile_flags, &sap,
      objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
      objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
-                      | OBJF_USERLOADED),
+                      | OBJF_USERLOADED | OBJF_MAINLINE),
      objfile);
      objfile);
-
-  do_cleanups (my_cleanup);
 }
 
 /* Process the symbol file ABFD, as either the main file or as a
 }
 
 /* Process the symbol file ABFD, as either the main file or as a
@@ -1273,9 +1169,10 @@ symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags,
    See symbol_file_add_with_addrs's comments for details.  */
 
 struct objfile *
    See symbol_file_add_with_addrs's comments for details.  */
 
 struct objfile *
-symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags,
-                          struct section_addr_info *addrs,
-                          int flags, struct objfile *parent)
+symbol_file_add_from_bfd (bfd *abfd, const char *name,
+                         symfile_add_flags add_flags,
+                         section_addr_info *addrs,
+                          objfile_flags flags, struct objfile *parent)
 {
   return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
                                     parent);
 {
   return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
                                     parent);
@@ -1285,16 +1182,13 @@ symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags,
    loaded file.  See symbol_file_add_with_addrs's comments for details.  */
 
 struct objfile *
    loaded file.  See symbol_file_add_with_addrs's comments for details.  */
 
 struct objfile *
-symbol_file_add (const char *name, int add_flags,
-                struct section_addr_info *addrs, int flags)
+symbol_file_add (const char *name, symfile_add_flags add_flags,
+                section_addr_info *addrs, objfile_flags flags)
 {
 {
-  bfd *bfd = symfile_bfd_open (name);
-  struct cleanup *cleanup = make_cleanup_bfd_unref (bfd);
-  struct objfile *objf;
+  gdb_bfd_ref_ptr bfd (symfile_bfd_open (name));
 
 
-  objf = symbol_file_add_from_bfd (bfd, name, add_flags, addrs, flags, NULL);
-  do_cleanups (cleanup);
-  return objf;
+  return symbol_file_add_from_bfd (bfd.get (), name, add_flags, addrs,
+                                  flags, NULL);
 }
 
 /* Call symbol_file_add() with default values and update whatever is
 }
 
 /* Call symbol_file_add() with default values and update whatever is
@@ -1306,24 +1200,26 @@ symbol_file_add (const char *name, int add_flags,
    command itself.  */
 
 void
    command itself.  */
 
 void
-symbol_file_add_main (const char *args, int from_tty)
+symbol_file_add_main (const char *args, symfile_add_flags add_flags)
 {
 {
-  symbol_file_add_main_1 (args, from_tty, 0);
+  symbol_file_add_main_1 (args, add_flags, 0, 0);
 }
 
 static void
 }
 
 static void
-symbol_file_add_main_1 (const char *args, int from_tty, int flags)
+symbol_file_add_main_1 (const char *args, symfile_add_flags add_flags,
+                       objfile_flags flags, CORE_ADDR reloff)
 {
 {
-  const int add_flags = (current_inferior ()->symfile_flags
-                        | SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0));
+  add_flags |= current_inferior ()->symfile_flags | SYMFILE_MAINLINE;
 
 
-  symbol_file_add (args, add_flags, NULL, flags);
+  struct objfile *objfile = symbol_file_add (args, add_flags, NULL, flags);
+  if (reloff != 0)
+    objfile_rebase (objfile, reloff);
 
   /* Getting new symbols may change our opinion about
      what is frameless.  */
   reinit_frame_cache ();
 
 
   /* Getting new symbols may change our opinion about
      what is frameless.  */
   reinit_frame_cache ();
 
-  if ((flags & SYMFILE_NO_READ) == 0)
+  if ((add_flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
 }
 
     set_initial_language ();
 }
 
@@ -1342,20 +1238,25 @@ symbol_file_clear (int from_tty)
      objfiles get stale by free_all_objfiles.  */
   no_shared_libraries (NULL, from_tty);
 
      objfiles get stale by free_all_objfiles.  */
   no_shared_libraries (NULL, from_tty);
 
-  free_all_objfiles ();
+  current_program_space->free_all_objfiles ();
+
+  clear_symtab_users (0);
 
   gdb_assert (symfile_objfile == NULL);
   if (from_tty)
 
   gdb_assert (symfile_objfile == NULL);
   if (from_tty)
-    printf_unfiltered (_("No symbol file now.\n"));
+    printf_filtered (_("No symbol file now.\n"));
 }
 
 }
 
+/* See symfile.h.  */
+
+bool separate_debug_file_debug = false;
+
 static int
 static int
-separate_debug_file_exists (const char *name, unsigned long crc,
+separate_debug_file_exists (const std::string &name, unsigned long crc,
                            struct objfile *parent_objfile)
 {
   unsigned long file_crc;
   int file_crc_p;
                            struct objfile *parent_objfile)
 {
   unsigned long file_crc;
   int file_crc_p;
-  bfd *abfd;
   struct stat parent_stat, abfd_stat;
   int verified_as_different;
 
   struct stat parent_stat, abfd_stat;
   int verified_as_different;
 
@@ -1365,32 +1266,46 @@ separate_debug_file_exists (const char *name, unsigned long crc,
      ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where
      the separate debug infos with the same basename can exist.  */
 
      ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where
      the separate debug infos with the same basename can exist.  */
 
-  if (filename_cmp (name, objfile_name (parent_objfile)) == 0)
+  if (filename_cmp (name.c_str (), objfile_name (parent_objfile)) == 0)
     return 0;
 
     return 0;
 
-  abfd = gdb_bfd_open_maybe_remote (name);
+  if (separate_debug_file_debug)
+    {
+      printf_filtered (_("  Trying %s..."), name.c_str ());
+      gdb_flush (gdb_stdout);
+    }
 
 
-  if (!abfd)
-    return 0;
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (name.c_str (), gnutarget));
+
+  if (abfd == NULL)
+    {
+      if (separate_debug_file_debug)
+       printf_filtered (_(" no, unable to open.\n"));
+
+      return 0;
+    }
 
   /* Verify symlinks were not the cause of filename_cmp name difference above.
 
      Some operating systems, e.g. Windows, do not provide a meaningful
      st_ino; they always set it to zero.  (Windows does provide a
 
   /* Verify symlinks were not the cause of filename_cmp name difference above.
 
      Some operating systems, e.g. Windows, do not provide a meaningful
      st_ino; they always set it to zero.  (Windows does provide a
-     meaningful st_dev.)  Do not indicate a duplicate library in that
-     case.  While there is no guarantee that a system that provides
-     meaningful inode numbers will never set st_ino to zero, this is
-     merely an optimization, so we do not need to worry about false
-     negatives.  */
-
-  if (bfd_stat (abfd, &abfd_stat) == 0
+     meaningful st_dev.)  Files accessed from gdbservers that do not
+     support the vFile:fstat packet will also have st_ino set to zero.
+     Do not indicate a duplicate library in either case.  While there
+     is no guarantee that a system that provides meaningful inode
+     numbers will never set st_ino to zero, this is merely an
+     optimization, so we do not need to worry about false negatives.  */
+
+  if (bfd_stat (abfd.get (), &abfd_stat) == 0
       && abfd_stat.st_ino != 0
       && bfd_stat (parent_objfile->obfd, &parent_stat) == 0)
     {
       if (abfd_stat.st_dev == parent_stat.st_dev
          && abfd_stat.st_ino == parent_stat.st_ino)
        {
       && abfd_stat.st_ino != 0
       && bfd_stat (parent_objfile->obfd, &parent_stat) == 0)
     {
       if (abfd_stat.st_dev == parent_stat.st_dev
          && abfd_stat.st_ino == parent_stat.st_ino)
        {
-         gdb_bfd_unref (abfd);
+         if (separate_debug_file_debug)
+           printf_filtered (_(" no, same file as the objfile.\n"));
+
          return 0;
        }
       verified_as_different = 1;
          return 0;
        }
       verified_as_different = 1;
@@ -1398,35 +1313,49 @@ separate_debug_file_exists (const char *name, unsigned long crc,
   else
     verified_as_different = 0;
 
   else
     verified_as_different = 0;
 
-  file_crc_p = gdb_bfd_crc (abfd, &file_crc);
-
-  gdb_bfd_unref (abfd);
+  file_crc_p = gdb_bfd_crc (abfd.get (), &file_crc);
 
   if (!file_crc_p)
 
   if (!file_crc_p)
-    return 0;
+    {
+      if (separate_debug_file_debug)
+       printf_filtered (_(" no, error computing CRC.\n"));
+
+      return 0;
+    }
 
   if (crc != file_crc)
     {
       unsigned long parent_crc;
 
 
   if (crc != file_crc)
     {
       unsigned long parent_crc;
 
-      /* If one (or both) the files are accessed for example the via "remote:"
-        gdbserver way it does not support the bfd_stat operation.  Verify
-        whether those two files are not the same manually.  */
+      /* If the files could not be verified as different with
+        bfd_stat then we need to calculate the parent's CRC
+        to verify whether the files are different or not.  */
 
       if (!verified_as_different)
        {
          if (!gdb_bfd_crc (parent_objfile->obfd, &parent_crc))
 
       if (!verified_as_different)
        {
          if (!gdb_bfd_crc (parent_objfile->obfd, &parent_crc))
-           return 0;
+           {
+             if (separate_debug_file_debug)
+               printf_filtered (_(" no, error computing CRC.\n"));
+
+             return 0;
+           }
        }
 
       if (verified_as_different || parent_crc != file_crc)
        warning (_("the debug information found in \"%s\""
                   " does not match \"%s\" (CRC mismatch).\n"),
        }
 
       if (verified_as_different || parent_crc != file_crc)
        warning (_("the debug information found in \"%s\""
                   " does not match \"%s\" (CRC mismatch).\n"),
-                name, objfile_name (parent_objfile));
+                name.c_str (), objfile_name (parent_objfile));
+
+      if (separate_debug_file_debug)
+       printf_filtered (_(" no, CRC doesn't match.\n"));
 
       return 0;
     }
 
 
       return 0;
     }
 
+  if (separate_debug_file_debug)
+    printf_filtered (_(" yes!\n"));
+
   return 1;
 }
 
   return 1;
 }
 
@@ -1450,45 +1379,31 @@ show_debug_file_directory (struct ui_file *file, int from_tty,
    dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are
    looking for.  CANON_DIR is the "realpath" form of DIR.
    DIR must contain a trailing '/'.
    dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are
    looking for.  CANON_DIR is the "realpath" form of DIR.
    DIR must contain a trailing '/'.
-   Returns the path of the file with separate debug info, of NULL.  */
+   Returns the path of the file with separate debug info, or an empty
+   string.  */
 
 
-static char *
+static std::string
 find_separate_debug_file (const char *dir,
                          const char *canon_dir,
                          const char *debuglink,
                          unsigned long crc32, struct objfile *objfile)
 {
 find_separate_debug_file (const char *dir,
                          const char *canon_dir,
                          const char *debuglink,
                          unsigned long crc32, struct objfile *objfile)
 {
-  char *debugdir;
-  char *debugfile;
-  int i;
-  VEC (char_ptr) *debugdir_vec;
-  struct cleanup *back_to;
-  int ix;
-
-  /* Set I to max (strlen (canon_dir), strlen (dir)).  */
-  i = strlen (dir);
-  if (canon_dir != NULL && strlen (canon_dir) > i)
-    i = strlen (canon_dir);
-
-  debugfile = xmalloc (strlen (debug_file_directory) + 1
-                      + i
-                      + strlen (DEBUG_SUBDIRECTORY)
-                      + strlen ("/")
-                      + strlen (debuglink)
-                      + 1);
+  if (separate_debug_file_debug)
+    printf_filtered (_("\nLooking for separate debug info (debug link) for "
+                      "%s\n"), objfile_name (objfile));
 
   /* First try in the same directory as the original file.  */
 
   /* First try in the same directory as the original file.  */
-  strcpy (debugfile, dir);
-  strcat (debugfile, debuglink);
+  std::string debugfile = dir;
+  debugfile += debuglink;
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
     return debugfile;
 
   /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
     return debugfile;
 
   /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
-  strcpy (debugfile, dir);
-  strcat (debugfile, DEBUG_SUBDIRECTORY);
-  strcat (debugfile, "/");
-  strcat (debugfile, debuglink);
+  debugfile = dir;
+  debugfile += DEBUG_SUBDIRECTORY;
+  debugfile += "/";
+  debugfile += debuglink;
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
     return debugfile;
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
     return debugfile;
@@ -1498,45 +1413,84 @@ find_separate_debug_file (const char *dir,
      Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
      cause "/..." lookups.  */
 
      Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
      cause "/..." lookups.  */
 
-  debugdir_vec = dirnames_to_char_ptr_vec (debug_file_directory);
-  back_to = make_cleanup_free_char_ptr_vec (debugdir_vec);
+  bool target_prefix = startswith (dir, "target:");
+  const char *dir_notarget = target_prefix ? dir + strlen ("target:") : dir;
+  std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
+    = dirnames_to_char_ptr_vec (debug_file_directory);
+  gdb::unique_xmalloc_ptr<char> canon_sysroot = gdb_realpath (gdb_sysroot);
+
+ /* MS-Windows/MS-DOS don't allow colons in file names; we must
+    convert the drive letter into a one-letter directory, so that the
+    file name resulting from splicing below will be valid.
+
+    FIXME: The below only works when GDB runs on MS-Windows/MS-DOS.
+    There are various remote-debugging scenarios where such a
+    transformation of the drive letter might be required when GDB runs
+    on a Posix host, see
+
+    https://sourceware.org/ml/gdb-patches/2019-04/msg00605.html
 
 
-  for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix)
+    If some of those scenarios need to be supported, we will need to
+    use a different condition for HAS_DRIVE_SPEC and a different macro
+    instead of STRIP_DRIVE_SPEC, which work on Posix systems as well.  */
+  std::string drive;
+  if (HAS_DRIVE_SPEC (dir_notarget))
     {
     {
-      strcpy (debugfile, debugdir);
-      strcat (debugfile, "/");
-      strcat (debugfile, dir);
-      strcat (debugfile, debuglink);
+      drive = dir_notarget[0];
+      dir_notarget = STRIP_DRIVE_SPEC (dir_notarget);
+    }
+
+  for (const gdb::unique_xmalloc_ptr<char> &debugdir : debugdir_vec)
+    {
+      debugfile = target_prefix ? "target:" : "";
+      debugfile += debugdir.get ();
+      debugfile += "/";
+      debugfile += drive;
+      debugfile += dir_notarget;
+      debugfile += debuglink;
 
       if (separate_debug_file_exists (debugfile, crc32, objfile))
 
       if (separate_debug_file_exists (debugfile, crc32, objfile))
+       return debugfile;
+
+      const char *base_path = NULL;
+      if (canon_dir != NULL)
        {
        {
-         do_cleanups (back_to);
-         return debugfile;
+         if (canon_sysroot.get () != NULL)
+           base_path = child_path (canon_sysroot.get (), canon_dir);
+         else
+           base_path = child_path (gdb_sysroot, canon_dir);
        }
        }
-
-      /* If the file is in the sysroot, try using its base path in the
-        global debugfile directory.  */
-      if (canon_dir != NULL
-         && filename_ncmp (canon_dir, gdb_sysroot,
-                           strlen (gdb_sysroot)) == 0
-         && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)]))
+      if (base_path != NULL)
        {
        {
-         strcpy (debugfile, debugdir);
-         strcat (debugfile, canon_dir + strlen (gdb_sysroot));
-         strcat (debugfile, "/");
-         strcat (debugfile, debuglink);
+         /* If the file is in the sysroot, try using its base path in
+            the global debugfile directory.  */
+         debugfile = target_prefix ? "target:" : "";
+         debugfile += debugdir.get ();
+         debugfile += "/";
+         debugfile += base_path;
+         debugfile += "/";
+         debugfile += debuglink;
 
          if (separate_debug_file_exists (debugfile, crc32, objfile))
 
          if (separate_debug_file_exists (debugfile, crc32, objfile))
-           {
-             do_cleanups (back_to);
-             return debugfile;
-           }
+           return debugfile;
+
+         /* If the file is in the sysroot, try using its base path in
+            the sysroot's global debugfile directory.  */
+         debugfile = target_prefix ? "target:" : "";
+         debugfile += gdb_sysroot;
+         debugfile += debugdir.get ();
+         debugfile += "/";
+         debugfile += base_path;
+         debugfile += "/";
+         debugfile += debuglink;
+
+         if (separate_debug_file_exists (debugfile, crc32, objfile))
+           return debugfile;
        }
        }
+
     }
 
     }
 
-  do_cleanups (back_to);
-  xfree (debugfile);
-  return NULL;
+  return std::string ();
 }
 
 /* Modify PATH to contain only "[/]directory/" part of PATH.
 }
 
 /* Modify PATH to contain only "[/]directory/" part of PATH.
@@ -1559,39 +1513,33 @@ terminate_after_last_dir_separator (char *path)
 }
 
 /* Find separate debuginfo for OBJFILE (using .gnu_debuglink section).
 }
 
 /* Find separate debuginfo for OBJFILE (using .gnu_debuglink section).
-   Returns pathname, or NULL.  */
+   Returns pathname, or an empty string.  */
 
 
-char *
+std::string
 find_separate_debug_file_by_debuglink (struct objfile *objfile)
 {
 find_separate_debug_file_by_debuglink (struct objfile *objfile)
 {
-  char *debuglink;
-  char *dir, *canon_dir;
-  char *debugfile;
   unsigned long crc32;
   unsigned long crc32;
-  struct cleanup *cleanups;
 
 
-  debuglink = bfd_get_debug_link_info (objfile->obfd, &crc32);
+  gdb::unique_xmalloc_ptr<char> debuglink
+    (bfd_get_debug_link_info (objfile->obfd, &crc32));
 
   if (debuglink == NULL)
     {
       /* There's no separate debug info, hence there's no way we could
         load it => no warning.  */
 
   if (debuglink == NULL)
     {
       /* There's no separate debug info, hence there's no way we could
         load it => no warning.  */
-      return NULL;
+      return std::string ();
     }
 
     }
 
-  cleanups = make_cleanup (xfree, debuglink);
-  dir = xstrdup (objfile_name (objfile));
-  make_cleanup (xfree, dir);
-  terminate_after_last_dir_separator (dir);
-  canon_dir = lrealpath (dir);
+  std::string dir = objfile_name (objfile);
+  terminate_after_last_dir_separator (&dir[0]);
+  gdb::unique_xmalloc_ptr<char> canon_dir (lrealpath (dir.c_str ()));
 
 
-  debugfile = find_separate_debug_file (dir, canon_dir, debuglink,
-                                       crc32, objfile);
-  xfree (canon_dir);
+  std::string debugfile
+    = find_separate_debug_file (dir.c_str (), canon_dir.get (),
+                               debuglink.get (), crc32, objfile);
 
 
-  if (debugfile == NULL)
+  if (debugfile.empty ())
     {
     {
-#ifdef HAVE_LSTAT
       /* For PR gdb/9538, try again with realpath (if different from the
         original).  */
 
       /* For PR gdb/9538, try again with realpath (if different from the
         original).  */
 
@@ -1600,31 +1548,37 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
       if (lstat (objfile_name (objfile), &st_buf) == 0
          && S_ISLNK (st_buf.st_mode))
        {
       if (lstat (objfile_name (objfile), &st_buf) == 0
          && S_ISLNK (st_buf.st_mode))
        {
-         char *symlink_dir;
-
-         symlink_dir = lrealpath (objfile_name (objfile));
+         gdb::unique_xmalloc_ptr<char> symlink_dir
+           (lrealpath (objfile_name (objfile)));
          if (symlink_dir != NULL)
            {
          if (symlink_dir != NULL)
            {
-             make_cleanup (xfree, symlink_dir);
-             terminate_after_last_dir_separator (symlink_dir);
-             if (strcmp (dir, symlink_dir) != 0)
+             terminate_after_last_dir_separator (symlink_dir.get ());
+             if (dir != symlink_dir.get ())
                {
                  /* Different directory, so try using it.  */
                {
                  /* Different directory, so try using it.  */
-                 debugfile = find_separate_debug_file (symlink_dir,
-                                                       symlink_dir,
-                                                       debuglink,
+                 debugfile = find_separate_debug_file (symlink_dir.get (),
+                                                       symlink_dir.get (),
+                                                       debuglink.get (),
                                                        crc32,
                                                        objfile);
                }
            }
        }
                                                        crc32,
                                                        objfile);
                }
            }
        }
-#endif  /* HAVE_LSTAT  */
     }
 
     }
 
-  do_cleanups (cleanups);
   return debugfile;
 }
 
   return debugfile;
 }
 
+/* Make sure that OBJF_{READNOW,READNEVER} are not set
+   simultaneously.  */
+
+static void
+validate_readnow_readnever (objfile_flags flags)
+{
+  if ((flags & OBJF_READNOW) && (flags & OBJF_READNEVER))
+    error (_("-readnow and -readnever cannot be used simultaneously"));
+}
+
 /* This is the symbol-file command.  Read the file, analyze its
    symbols, and add a struct symtab to a symtab list.  The syntax of
    the command is rather bizarre:
 /* This is the symbol-file command.  Read the file, analyze its
    symbols, and add a struct symtab to a symtab list.  The syntax of
    the command is rather bizarre:
@@ -1640,7 +1594,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
    conventions (because it is confusing and inconvenient).  */
 
 void
    conventions (because it is confusing and inconvenient).  */
 
 void
-symbol_file_command (char *args, int from_tty)
+symbol_file_command (const char *args, int from_tty)
 {
   dont_repeat ();
 
 {
   dont_repeat ();
 
@@ -1650,155 +1604,144 @@ symbol_file_command (char *args, int from_tty)
     }
   else
     {
     }
   else
     {
-      char **argv = gdb_buildargv (args);
-      int flags = OBJF_USERLOADED;
-      struct cleanup *cleanups;
+      objfile_flags flags = OBJF_USERLOADED;
+      symfile_add_flags add_flags = 0;
       char *name = NULL;
       char *name = NULL;
+      bool stop_processing_options = false;
+      CORE_ADDR offset = 0;
+      int idx;
+      char *arg;
+
+      if (from_tty)
+       add_flags |= SYMFILE_VERBOSE;
 
 
-      cleanups = make_cleanup_freeargv (argv);
-      while (*argv != NULL)
+      gdb_argv built_argv (args);
+      for (arg = built_argv[0], idx = 0; arg != NULL; arg = built_argv[++idx])
        {
        {
-         if (strcmp (*argv, "-readnow") == 0)
-           flags |= OBJF_READNOW;
-         else if (**argv == '-')
-           error (_("unknown option `%s'"), *argv);
-         else
+         if (stop_processing_options || *arg != '-')
            {
            {
-             symbol_file_add_main_1 (*argv, from_tty, flags);
-             name = *argv;
+             if (name == NULL)
+               name = arg;
+             else
+               error (_("Unrecognized argument \"%s\""), arg);
            }
            }
+         else if (strcmp (arg, "-readnow") == 0)
+           flags |= OBJF_READNOW;
+         else if (strcmp (arg, "-readnever") == 0)
+           flags |= OBJF_READNEVER;
+         else if (strcmp (arg, "-o") == 0)
+           {
+             arg = built_argv[++idx];
+             if (arg == NULL)
+               error (_("Missing argument to -o"));
 
 
-         argv++;
+             offset = parse_and_eval_address (arg);
+           }
+         else if (strcmp (arg, "--") == 0)
+           stop_processing_options = true;
+         else
+           error (_("Unrecognized argument \"%s\""), arg);
        }
 
       if (name == NULL)
        error (_("no symbol file name was specified"));
 
        }
 
       if (name == NULL)
        error (_("no symbol file name was specified"));
 
-      do_cleanups (cleanups);
+      validate_readnow_readnever (flags);
+
+      /* Set SYMFILE_DEFER_BP_RESET because the proper displacement for a PIE
+        (Position Independent Executable) main symbol file will only be
+        computed by the solib_create_inferior_hook below.  Without it,
+        breakpoint_re_set would fail to insert the breakpoints with the zero
+        displacement.  */
+      add_flags |= SYMFILE_DEFER_BP_RESET;
+
+      symbol_file_add_main_1 (name, add_flags, flags, offset);
+
+      solib_create_inferior_hook (from_tty);
+
+      /* Now it's safe to re-add the breakpoints.  */
+      breakpoint_re_set ();
     }
 }
 
     }
 }
 
-/* Set the initial language.
-
-   FIXME: A better solution would be to record the language in the
-   psymtab when reading partial symbols, and then use it (if known) to
-   set the language.  This would be a win for formats that encode the
-   language in an easily discoverable place, such as DWARF.  For
-   stabs, we can jump through hoops looking for specially named
-   symbols or try to intuit the language from the specific type of
-   stabs we find, but we can't do that until later when we read in
-   full symbols.  */
+/* Set the initial language.  */
 
 void
 set_initial_language (void)
 {
 
 void
 set_initial_language (void)
 {
+  if (language_mode == language_mode_manual)
+    return;
   enum language lang = main_language ();
   enum language lang = main_language ();
+  /* Make C the default language.  */
+  enum language default_lang = language_c;
 
   if (lang == language_unknown)
     {
 
   if (lang == language_unknown)
     {
-      char *name = main_name ();
-      struct symbol *sym = lookup_symbol (name, NULL, VAR_DOMAIN, NULL);
+      const char *name = main_name ();
+      struct symbol *sym
+       = lookup_symbol_in_language (name, NULL, VAR_DOMAIN, default_lang,
+                                    NULL).symbol;
 
       if (sym != NULL)
 
       if (sym != NULL)
-       lang = SYMBOL_LANGUAGE (sym);
+       lang = sym->language ();
     }
 
   if (lang == language_unknown)
     {
     }
 
   if (lang == language_unknown)
     {
-      /* Make C the default language */
-      lang = language_c;
+      lang = default_lang;
     }
 
   set_language (lang);
   expected_language = current_language; /* Don't warn the user.  */
 }
 
     }
 
   set_language (lang);
   expected_language = current_language; /* Don't warn the user.  */
 }
 
-/* If NAME is a remote name open the file using remote protocol, otherwise
-   open it normally.  Returns a new reference to the BFD.  On error,
-   returns NULL with the BFD error set.  */
-
-bfd *
-gdb_bfd_open_maybe_remote (const char *name)
-{
-  bfd *result;
-
-  if (remote_filename_p (name))
-    result = remote_bfd_open (name, gnutarget);
-  else
-    result = gdb_bfd_open (name, gnutarget, -1);
-
-  return result;
-}
-
 /* Open the file specified by NAME and hand it off to BFD for
    preliminary analysis.  Return a newly initialized bfd *, which
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
    absolute).  In case of trouble, error() is called.  */
 
 /* Open the file specified by NAME and hand it off to BFD for
    preliminary analysis.  Return a newly initialized bfd *, which
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
    absolute).  In case of trouble, error() is called.  */
 
-bfd *
-symfile_bfd_open (const char *cname)
+gdb_bfd_ref_ptr
+symfile_bfd_open (const char *name)
 {
 {
-  bfd *sym_bfd;
-  int desc;
-  char *name, *absolute_name;
-  struct cleanup *back_to;
+  int desc = -1;
 
 
-  if (remote_filename_p (cname))
+  gdb::unique_xmalloc_ptr<char> absolute_name;
+  if (!is_target_filename (name))
     {
     {
-      sym_bfd = remote_bfd_open (cname, gnutarget);
-      if (!sym_bfd)
-       error (_("`%s': can't open to read symbols: %s."), cname,
-              bfd_errmsg (bfd_get_error ()));
+      gdb::unique_xmalloc_ptr<char> expanded_name (tilde_expand (name));
 
 
-      if (!bfd_check_format (sym_bfd, bfd_object))
-       {
-         make_cleanup_bfd_unref (sym_bfd);
-         error (_("`%s': can't read symbols: %s."), cname,
-                bfd_errmsg (bfd_get_error ()));
-       }
-
-      return sym_bfd;
-    }
-
-  name = tilde_expand (cname); /* 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 | OPF_RETURN_REALPATH, name,
-               O_RDONLY | O_BINARY, &absolute_name);
+      /* Look down path for it, allocate 2nd new malloc'd copy.  */
+      desc = openp (getenv ("PATH"),
+                   OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+                   expanded_name.get (), O_RDONLY | O_BINARY, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
-  if (desc < 0)
-    {
-      char *exename = alloca (strlen (name) + 5);
+      if (desc < 0)
+       {
+         char *exename = (char *) alloca (strlen (expanded_name.get ()) + 5);
 
 
-      strcat (strcpy (exename, name), ".exe");
-      desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
-                   exename, O_RDONLY | O_BINARY, &absolute_name);
-    }
+         strcat (strcpy (exename, expanded_name.get ()), ".exe");
+         desc = openp (getenv ("PATH"),
+                       OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+                       exename, O_RDONLY | O_BINARY, &absolute_name);
+       }
 #endif
 #endif
-  if (desc < 0)
-    {
-      make_cleanup (xfree, name);
-      perror_with_name (name);
-    }
+      if (desc < 0)
+       perror_with_name (expanded_name.get ());
 
 
-  xfree (name);
-  name = absolute_name;
-  back_to = make_cleanup (xfree, name);
+      name = absolute_name.get ();
+    }
 
 
-  sym_bfd = gdb_bfd_open (name, gnutarget, desc);
-  if (!sym_bfd)
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (name, gnutarget, desc));
+  if (sym_bfd == NULL)
     error (_("`%s': can't open to read symbols: %s."), name,
           bfd_errmsg (bfd_get_error ()));
     error (_("`%s': can't open to read symbols: %s."), name,
           bfd_errmsg (bfd_get_error ()));
-  bfd_set_cacheable (sym_bfd, 1);
 
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      make_cleanup_bfd_unref (sym_bfd);
-      error (_("`%s': can't read symbols: %s."), name,
-            bfd_errmsg (bfd_get_error ()));
-    }
+  if (!gdb_bfd_has_target_filename (sym_bfd.get ()))
+    bfd_set_cacheable (sym_bfd.get (), 1);
 
 
-  do_cleanups (back_to);
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    error (_("`%s': can't read symbols: %s."), name,
+          bfd_errmsg (bfd_get_error ()));
 
   return sym_bfd;
 }
 
   return sym_bfd;
 }
@@ -1807,7 +1750,7 @@ symfile_bfd_open (const char *cname)
    the section was not found.  */
 
 int
    the section was not found.  */
 
 int
-get_section_index (struct objfile *objfile, char *section_name)
+get_section_index (struct objfile *objfile, const char *section_name)
 {
   asection *sect = bfd_get_section_by_name (objfile->obfd, section_name);
 
 {
   asection *sect = bfd_get_section_by_name (objfile->obfd, section_name);
 
@@ -1826,9 +1769,7 @@ get_section_index (struct objfile *objfile, char *section_name)
 void
 add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf)
 {
 void
 add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf)
 {
-  registered_sym_fns fns = { flavour, sf };
-
-  VEC_safe_push (registered_sym_fns, symtab_fns, &fns);
+  symtab_fns.emplace_back (flavour, sf);
 }
 
 /* Initialize OBJFILE to read symbols from its associated BFD.  It
 }
 
 /* Initialize OBJFILE to read symbols from its associated BFD.  It
@@ -1839,18 +1780,16 @@ add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf)
 static const struct sym_fns *
 find_sym_fns (bfd *abfd)
 {
 static const struct sym_fns *
 find_sym_fns (bfd *abfd)
 {
-  registered_sym_fns *rsf;
   enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
   enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
-  int i;
 
   if (our_flavour == bfd_target_srec_flavour
       || our_flavour == bfd_target_ihex_flavour
       || our_flavour == bfd_target_tekhex_flavour)
     return NULL;       /* No symbols.  */
 
 
   if (our_flavour == bfd_target_srec_flavour
       || our_flavour == bfd_target_ihex_flavour
       || our_flavour == bfd_target_tekhex_flavour)
     return NULL;       /* No symbols.  */
 
-  for (i = 0; VEC_iterate (registered_sym_fns, symtab_fns, i, rsf); ++i)
-    if (our_flavour == rsf->sym_flavour)
-      return rsf->sym_fns;
+  for (const registered_sym_fns &rsf : symtab_fns)
+    if (our_flavour == rsf.sym_flavour)
+      return rsf.sym_fns;
 
   error (_("I'm sorry, Dave, I can't do that.  Symbol format `%s' unknown."),
         bfd_get_target (abfd));
 
   error (_("I'm sorry, Dave, I can't do that.  Symbol format `%s' unknown."),
         bfd_get_target (abfd));
@@ -1860,10 +1799,8 @@ find_sym_fns (bfd *abfd)
 /* This function runs the load command of our current target.  */
 
 static void
 /* This function runs the load command of our current target.  */
 
 static void
-load_command (char *arg, int from_tty)
+load_command (const char *arg, int from_tty)
 {
 {
-  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
-
   dont_repeat ();
 
   /* The user might be reloading because the binary has changed.  Take
   dont_repeat ();
 
   /* The user might be reloading because the binary has changed.  Take
@@ -1871,40 +1808,28 @@ load_command (char *arg, int from_tty)
   reopen_exec_file ();
   reread_symbols ();
 
   reopen_exec_file ();
   reread_symbols ();
 
+  std::string temp;
   if (arg == NULL)
     {
   if (arg == NULL)
     {
-      char *parg;
-      int count = 0;
+      const char *parg, *prev;
 
 
-      parg = arg = get_exec_file (1);
+      arg = get_exec_file (1);
 
 
-      /* Count how many \ " ' tab space there are in the name.  */
+      /* We may need to quote this string so buildargv can pull it
+        apart.  */
+      prev = parg = arg;
       while ((parg = strpbrk (parg, "\\\"'\t ")))
        {
       while ((parg = strpbrk (parg, "\\\"'\t ")))
        {
-         parg++;
-         count++;
+         temp.append (prev, parg - prev);
+         prev = parg++;
+         temp.push_back ('\\');
        }
        }
-
-      if (count)
+      /* If we have not copied anything yet, then we didn't see a
+        character to quote, and we can just leave ARG unchanged.  */
+      if (!temp.empty ())
        {
        {
-         /* 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;
+         temp.append (prev);
+         arg = temp.c_str ();
        }
     }
 
        }
     }
 
@@ -1913,8 +1838,6 @@ load_command (char *arg, int from_tty)
   /* After re-loading the executable, we don't really know which
      overlays are mapped any more.  */
   overlay_cache_invalid = 1;
   /* After re-loading the executable, we don't really know which
      overlays are mapped any more.  */
   overlay_cache_invalid = 1;
-
-  do_cleanups (cleanup);
 }
 
 /* This version of "load" should be usable for any target.  Currently
 }
 
 /* This version of "load" should be usable for any target.  Currently
@@ -1933,44 +1856,68 @@ static int validate_download = 0;
 static void
 add_section_size_callback (bfd *abfd, asection *asec, void *data)
 {
 static void
 add_section_size_callback (bfd *abfd, asection *asec, void *data)
 {
-  bfd_size_type *sum = data;
+  bfd_size_type *sum = (bfd_size_type *) data;
 
 
-  *sum += bfd_get_section_size (asec);
+  *sum += bfd_section_size (asec);
 }
 
 }
 
-/* Opaque data for load_section_callback.  */
-struct load_section_data {
-  CORE_ADDR load_offset;
-  struct load_progress_data *progress_data;
-  VEC(memory_write_request_s) *requests;
-};
-
 /* Opaque data for load_progress.  */
 /* Opaque data for load_progress.  */
-struct load_progress_data {
+struct load_progress_data
+{
   /* Cumulative data.  */
   /* Cumulative data.  */
-  unsigned long write_count;
-  unsigned long data_count;
-  bfd_size_type total_size;
+  unsigned long write_count = 0;
+  unsigned long data_count = 0;
+  bfd_size_type total_size = 0;
 };
 
 /* Opaque data for load_progress for a single section.  */
 };
 
 /* Opaque data for load_progress for a single section.  */
-struct load_progress_section_data {
+struct load_progress_section_data
+{
+  load_progress_section_data (load_progress_data *cumulative_,
+                             const char *section_name_, ULONGEST section_size_,
+                             CORE_ADDR lma_, gdb_byte *buffer_)
+    : cumulative (cumulative_), section_name (section_name_),
+      section_size (section_size_), lma (lma_), buffer (buffer_)
+  {}
+
   struct load_progress_data *cumulative;
 
   /* Per-section data.  */
   const char *section_name;
   struct load_progress_data *cumulative;
 
   /* Per-section data.  */
   const char *section_name;
-  ULONGEST section_sent;
+  ULONGEST section_sent = 0;
   ULONGEST section_size;
   CORE_ADDR lma;
   gdb_byte *buffer;
 };
 
   ULONGEST section_size;
   CORE_ADDR lma;
   gdb_byte *buffer;
 };
 
+/* Opaque data for load_section_callback.  */
+struct load_section_data
+{
+  load_section_data (load_progress_data *progress_data_)
+    : progress_data (progress_data_)
+  {}
+
+  ~load_section_data ()
+  {
+    for (auto &&request : requests)
+      {
+       xfree (request.data);
+       delete ((load_progress_section_data *) request.baton);
+      }
+  }
+
+  CORE_ADDR load_offset = 0;
+  struct load_progress_data *progress_data;
+  std::vector<struct memory_write_request> requests;
+};
+
 /* Target write callback routine for progress reporting.  */
 
 static void
 load_progress (ULONGEST bytes, void *untyped_arg)
 {
 /* 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_section_data *args
+    = (struct load_progress_section_data *) untyped_arg;
   struct load_progress_data *totals;
 
   if (args == NULL)
   struct load_progress_data *totals;
 
   if (args == NULL)
@@ -1984,9 +1931,10 @@ load_progress (ULONGEST bytes, void *untyped_arg)
     {
       /* The write is just starting.  Let the user know we've started
         this section.  */
     {
       /* The write is just starting.  Let the user know we've started
         this section.  */
-      ui_out_message (current_uiout, 0, "Loading section %s, size %s lma %s\n",
-                     args->section_name, hex_string (args->section_size),
-                     paddress (target_gdbarch (), args->lma));
+      current_uiout->message ("Loading section %s, size %s lma %s\n",
+                             args->section_name,
+                             hex_string (args->section_size),
+                             paddress (target_gdbarch (), args->lma));
       return;
     }
 
       return;
     }
 
@@ -1999,16 +1947,14 @@ load_progress (ULONGEST bytes, void *untyped_arg)
         might add a verify_memory() method to the target vector and
         then use that.  remote.c could implement that method using
         the ``qCRC'' packet.  */
         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);
+      gdb::byte_vector check (bytes);
 
 
-      if (target_read_memory (args->lma, check, bytes) != 0)
+      if (target_read_memory (args->lma, check.data (), bytes) != 0)
        error (_("Download verify read failed at %s"),
               paddress (target_gdbarch (), args->lma));
        error (_("Download verify read failed at %s"),
               paddress (target_gdbarch (), args->lma));
-      if (memcmp (args->buffer, check, bytes) != 0)
+      if (memcmp (args->buffer, check.data (), bytes) != 0)
        error (_("Download verify compare failed at %s"),
               paddress (target_gdbarch (), args->lma));
        error (_("Download verify compare failed at %s"),
               paddress (target_gdbarch (), args->lma));
-      do_cleanups (verify_cleanups);
     }
   totals->data_count += bytes;
   args->lma += bytes;
     }
   totals->data_count += bytes;
   args->lma += bytes;
@@ -2034,87 +1980,48 @@ load_progress (ULONGEST bytes, void *untyped_arg)
 static void
 load_section_callback (bfd *abfd, asection *asec, void *data)
 {
 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);
+  struct load_section_data *args = (struct load_section_data *) data;
+  bfd_size_type size = bfd_section_size (asec);
+  const char *sect_name = bfd_section_name (asec);
 
 
-  if ((bfd_get_section_flags (abfd, asec) & SEC_LOAD) == 0)
+  if ((bfd_section_flags (asec) & SEC_LOAD) == 0)
     return;
 
   if (size == 0)
     return;
 
     return;
 
   if (size == 0)
     return;
 
-  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;
-
-  buffer = new_request->data;
+  ULONGEST begin = bfd_section_lma (asec) + args->load_offset;
+  ULONGEST end = begin + size;
+  gdb_byte *buffer = (gdb_byte *) xmalloc (size);
+  bfd_get_section_contents (abfd, asec, buffer, 0, 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;
+  load_progress_section_data *section_data
+    = new load_progress_section_data (args->progress_data, sect_name, size,
+                                     begin, buffer);
 
 
-  bfd_get_section_contents (abfd, asec, buffer, 0, size);
+  args->requests.emplace_back (begin, end, buffer, section_data);
 }
 
 }
 
-/* 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;
+static void print_transfer_performance (struct ui_file *stream,
+                                       unsigned long data_count,
+                                       unsigned long write_count,
+                                       std::chrono::steady_clock::duration d);
 
 
-  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);
-}
+/* See symfile.h.  */
 
 void
 generic_load (const char *args, int from_tty)
 {
 
 void
 generic_load (const char *args, int from_tty)
 {
-  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;
   struct load_progress_data total_progress;
+  struct load_section_data cbdata (&total_progress);
   struct ui_out *uiout = current_uiout;
 
   struct ui_out *uiout = current_uiout;
 
-  CORE_ADDR entry;
-  char **argv;
-
-  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);
-
   if (args == NULL)
     error_no_arg (_("file to load"));
 
   if (args == NULL)
     error_no_arg (_("file to load"));
 
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  gdb_argv argv (args);
 
 
-  filename = tilde_expand (argv[0]);
-  make_cleanup (xfree, filename);
+  gdb::unique_xmalloc_ptr<char> filename (tilde_expand (argv[0]));
 
   if (argv[1] != NULL)
     {
 
   if (argv[1] != NULL)
     {
@@ -2132,43 +2039,38 @@ generic_load (const char *args, int from_tty)
     }
 
   /* Open the file for loading.  */
     }
 
   /* Open the file for loading.  */
-  loadfile_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr loadfile_bfd (gdb_bfd_open (filename.get (), gnutarget));
   if (loadfile_bfd == NULL)
   if (loadfile_bfd == NULL)
-    {
-      perror_with_name (filename);
-      return;
-    }
-
-  make_cleanup_bfd_unref (loadfile_bfd);
+    perror_with_name (filename.get ());
 
 
-  if (!bfd_check_format (loadfile_bfd, bfd_object))
+  if (!bfd_check_format (loadfile_bfd.get (), bfd_object))
     {
     {
-      error (_("\"%s\" is not an object file: %s"), filename,
+      error (_("\"%s\" is not an object file: %s"), filename.get (),
             bfd_errmsg (bfd_get_error ()));
     }
 
             bfd_errmsg (bfd_get_error ()));
     }
 
-  bfd_map_over_sections (loadfile_bfd, add_section_size_callback,
+  bfd_map_over_sections (loadfile_bfd.get (), add_section_size_callback,
                         (void *) &total_progress.total_size);
 
                         (void *) &total_progress.total_size);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  bfd_map_over_sections (loadfile_bfd.get (), load_section_callback, &cbdata);
 
 
-  gettimeofday (&start_time, NULL);
+  using namespace std::chrono;
+
+  steady_clock::time_point start_time = steady_clock::now ();
 
   if (target_write_memory_blocks (cbdata.requests, flash_discard,
                                  load_progress) != 0)
     error (_("Load failed"));
 
 
   if (target_write_memory_blocks (cbdata.requests, flash_discard,
                                  load_progress) != 0)
     error (_("Load failed"));
 
-  gettimeofday (&end_time, NULL);
+  steady_clock::time_point end_time = steady_clock::now ();
 
 
-  entry = bfd_get_start_address (loadfile_bfd);
+  CORE_ADDR entry = bfd_get_start_address (loadfile_bfd.get ());
   entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
   entry = gdbarch_addr_bits_remove (target_gdbarch (), entry);
-  ui_out_text (uiout, "Start address ");
-  ui_out_field_fmt (uiout, "address", "%s", paddress (target_gdbarch (), entry));
-  ui_out_text (uiout, ", load size ");
-  ui_out_field_fmt (uiout, "load-size", "%lu", total_progress.data_count);
-  ui_out_text (uiout, "\n");
-  /* We were doing this in remote-mips.c, I suspect it is right
-     for other targets too.  */
+  uiout->text ("Start address ");
+  uiout->field_core_addr ("address", target_gdbarch (), entry);
+  uiout->text (", load size ");
+  uiout->field_unsigned ("load-size", total_progress.data_count);
+  uiout->text ("\n");
   regcache_write_pc (get_current_regcache (), entry);
 
   /* Reset breakpoints, now that we have changed the load image.  For
   regcache_write_pc (get_current_regcache (), entry);
 
   /* Reset breakpoints, now that we have changed the load image.  For
@@ -2181,184 +2083,207 @@ generic_load (const char *args, int from_tty)
 
   breakpoint_re_set ();
 
 
   breakpoint_re_set ();
 
-  /* FIXME: are we supposed to call symbol_file_add or not?  According
-     to a comment from remote-mips.c (where a call to symbol_file_add
-     was commented out), making the call confuses GDB if more than one
-     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, total_progress.data_count,
                              total_progress.write_count,
   print_transfer_performance (gdb_stdout, total_progress.data_count,
                              total_progress.write_count,
-                             &start_time, &end_time);
-
-  do_cleanups (old_cleanups);
+                             end_time - start_time);
 }
 
 }
 
-/* Report how fast the transfer went.  */
+/* Report on STREAM the performance of a memory transfer operation,
+   such as 'load'.  DATA_COUNT is the number of bytes transferred.
+   WRITE_COUNT is the number of separate write operations, or 0, if
+   that information is not available.  TIME is how long the operation
+   lasted.  */
 
 
-void
+static void
 print_transfer_performance (struct ui_file *stream,
                            unsigned long data_count,
                            unsigned long write_count,
 print_transfer_performance (struct ui_file *stream,
                            unsigned long data_count,
                            unsigned long write_count,
-                           const struct timeval *start_time,
-                           const struct timeval *end_time)
+                           std::chrono::steady_clock::duration time)
 {
 {
-  ULONGEST time_count;
+  using namespace std::chrono;
   struct ui_out *uiout = current_uiout;
 
   struct ui_out *uiout = current_uiout;
 
-  /* Compute the elapsed time in milliseconds, as a tradeoff between
-     accuracy and overflow.  */
-  time_count = (end_time->tv_sec - start_time->tv_sec) * 1000;
-  time_count += (end_time->tv_usec - start_time->tv_usec) / 1000;
+  milliseconds ms = duration_cast<milliseconds> (time);
 
 
-  ui_out_text (uiout, "Transfer rate: ");
-  if (time_count > 0)
+  uiout->text ("Transfer rate: ");
+  if (ms.count () > 0)
     {
     {
-      unsigned long rate = ((ULONGEST) data_count * 1000) / time_count;
+      unsigned long rate = ((ULONGEST) data_count * 1000) / ms.count ();
 
 
-      if (ui_out_is_mi_like_p (uiout))
+      if (uiout->is_mi_like_p ())
        {
        {
-         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate * 8);
-         ui_out_text (uiout, " bits/sec");
+         uiout->field_unsigned ("transfer-rate", rate * 8);
+         uiout->text (" bits/sec");
        }
       else if (rate < 1024)
        {
        }
       else if (rate < 1024)
        {
-         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate);
-         ui_out_text (uiout, " bytes/sec");
+         uiout->field_unsigned ("transfer-rate", rate);
+         uiout->text (" bytes/sec");
        }
       else
        {
        }
       else
        {
-         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024);
-         ui_out_text (uiout, " KB/sec");
+         uiout->field_unsigned ("transfer-rate", rate / 1024);
+         uiout->text (" KB/sec");
        }
     }
   else
     {
        }
     }
   else
     {
-      ui_out_field_fmt (uiout, "transferred-bits", "%lu", (data_count * 8));
-      ui_out_text (uiout, " bits in <1 sec");
+      uiout->field_unsigned ("transferred-bits", (data_count * 8));
+      uiout->text (" bits in <1 sec");
     }
   if (write_count > 0)
     {
     }
   if (write_count > 0)
     {
-      ui_out_text (uiout, ", ");
-      ui_out_field_fmt (uiout, "write-rate", "%lu", data_count / write_count);
-      ui_out_text (uiout, " bytes/write");
+      uiout->text (", ");
+      uiout->field_unsigned ("write-rate", data_count / write_count);
+      uiout->text (" bytes/write");
     }
     }
-  ui_out_text (uiout, ".\n");
+  uiout->text (".\n");
+}
+
+/* Add an OFFSET to the start address of each section in OBJF, except
+   sections that were specified in ADDRS.  */
+
+static void
+set_objfile_default_section_offset (struct objfile *objf,
+                                   const section_addr_info &addrs,
+                                   CORE_ADDR offset)
+{
+  /* Add OFFSET to all sections by default.  */
+  section_offsets offsets (objf->section_offsets.size (), offset);
+
+  /* Create sorted lists of all sections in ADDRS as well as all
+     sections in OBJF.  */
+
+  std::vector<const struct other_sections *> addrs_sorted
+    = addrs_section_sort (addrs);
+
+  section_addr_info objf_addrs
+    = build_section_addr_info_from_objfile (objf);
+  std::vector<const struct other_sections *> objf_addrs_sorted
+    = addrs_section_sort (objf_addrs);
+
+  /* Walk the BFD section list, and if a matching section is found in
+     ADDRS_SORTED_LIST, set its offset to zero to keep its address
+     unchanged.
+
+     Note that both lists may contain multiple sections with the same
+     name, and then the sections from ADDRS are matched in BFD order
+     (thanks to sectindex).  */
+
+  std::vector<const struct other_sections *>::iterator addrs_sorted_iter
+    = addrs_sorted.begin ();
+  for (const other_sections *objf_sect : objf_addrs_sorted)
+    {
+      const char *objf_name = addr_section_name (objf_sect->name.c_str ());
+      int cmp = -1;
+
+      while (cmp < 0 && addrs_sorted_iter != addrs_sorted.end ())
+       {
+         const struct other_sections *sect = *addrs_sorted_iter;
+         const char *sect_name = addr_section_name (sect->name.c_str ());
+         cmp = strcmp (sect_name, objf_name);
+         if (cmp <= 0)
+           ++addrs_sorted_iter;
+       }
+
+      if (cmp == 0)
+       offsets[objf_sect->sectindex] = 0;
+    }
+
+  /* Apply the new section offsets.  */
+  objfile_relocate (objf, offsets);
 }
 
 /* This function allows the addition of incrementally linked object files.
    It does not modify any state in the target, only in the debugger.  */
 }
 
 /* This function allows the addition of incrementally linked object files.
    It does not modify any state in the target, only in the debugger.  */
-/* Note: ezannoni 2000-04-13 This function/command used to have a
-   special case syntax for the rombug target (Rombug is the boot
-   monitor for Microware's OS-9 / OS-9000, see remote-os9k.c). In the
-   rombug case, the user doesn't need to supply a text address,
-   instead a call to target_link() (in target.c) would supply the
-   value to use.  We are now discontinuing this type of ad hoc syntax.  */
 
 static void
 
 static void
-add_symbol_file_command (char *args, int from_tty)
+add_symbol_file_command (const char *args, int from_tty)
 {
   struct gdbarch *gdbarch = get_current_arch ();
 {
   struct gdbarch *gdbarch = get_current_arch ();
-  char *filename = NULL;
-  int flags = OBJF_USERLOADED | OBJF_SHARED;
+  gdb::unique_xmalloc_ptr<char> filename;
   char *arg;
   char *arg;
-  int section_index = 0;
   int argcnt = 0;
   int argcnt = 0;
-  int sec_num = 0;
-  int i;
-  int expecting_sec_name = 0;
-  int expecting_sec_addr = 0;
-  char **argv;
   struct objfile *objf;
   struct objfile *objf;
+  objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED;
+  symfile_add_flags add_flags = 0;
+
+  if (from_tty)
+    add_flags |= SYMFILE_VERBOSE;
 
   struct sect_opt
   {
 
   struct sect_opt
   {
-    char *name;
-    char *value;
+    const char *name;
+    const char *value;
   };
 
   };
 
-  struct section_addr_info *section_addrs;
-  struct sect_opt *sect_opts = NULL;
-  size_t num_sect_opts = 0;
-  struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
-
-  num_sect_opts = 16;
-  sect_opts = (struct sect_opt *) xmalloc (num_sect_opts
-                                          * sizeof (struct sect_opt));
+  std::vector<sect_opt> sect_opts = { { ".text", NULL } };
+  bool stop_processing_options = false;
+  CORE_ADDR offset = 0;
 
   dont_repeat ();
 
   if (args == NULL)
     error (_("add-symbol-file takes a file name and an address"));
 
 
   dont_repeat ();
 
   if (args == NULL)
     error (_("add-symbol-file takes a file name and an address"));
 
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  bool seen_addr = false;
+  bool seen_offset = false;
+  gdb_argv argv (args);
 
   for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
     {
 
   for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
     {
-      /* Process the argument.  */
-      if (argcnt == 0)
-       {
-         /* The first argument is the file name.  */
-         filename = tilde_expand (arg);
-         make_cleanup (xfree, filename);
-       }
-      else if (argcnt == 1)
+      if (stop_processing_options || *arg != '-')
        {
        {
-         /* The second argument is always the text address at which
-            to load the program.  */
-         sect_opts[section_index].name = ".text";
-         sect_opts[section_index].value = arg;
-         if (++section_index >= num_sect_opts)
+         if (filename == NULL)
            {
            {
-             num_sect_opts *= 2;
-             sect_opts = ((struct sect_opt *)
-                          xrealloc (sect_opts,
-                                    num_sect_opts
-                                    * sizeof (struct sect_opt)));
+             /* First non-option argument is always the filename.  */
+             filename.reset (tilde_expand (arg));
            }
            }
-       }
-      else
-       {
-         /* It's an option (starting with '-') or it's an argument
-            to an option.  */
-         if (expecting_sec_name)
+         else if (!seen_addr)
            {
            {
-             sect_opts[section_index].name = arg;
-             expecting_sec_name = 0;
-           }
-         else if (expecting_sec_addr)
-           {
-             sect_opts[section_index].value = arg;
-             expecting_sec_addr = 0;
-             if (++section_index >= num_sect_opts)
-               {
-                 num_sect_opts *= 2;
-                 sect_opts = ((struct sect_opt *)
-                              xrealloc (sect_opts,
-                                        num_sect_opts
-                                        * sizeof (struct sect_opt)));
-               }
-           }
-         else if (strcmp (arg, "-readnow") == 0)
-           flags |= OBJF_READNOW;
-         else if (strcmp (arg, "-s") == 0)
-           {
-             expecting_sec_name = 1;
-             expecting_sec_addr = 1;
+             /* The second non-option argument is always the text
+                address at which to load the program.  */
+             sect_opts[0].value = arg;
+             seen_addr = true;
            }
          else
            }
          else
-           error (_("USAGE: add-symbol-file <filename> <textaddress>"
-                    " [-readnow] [-s <secname> <addr>]*"));
+           error (_("Unrecognized argument \"%s\""), arg);
+       }
+      else if (strcmp (arg, "-readnow") == 0)
+       flags |= OBJF_READNOW;
+      else if (strcmp (arg, "-readnever") == 0)
+       flags |= OBJF_READNEVER;
+      else if (strcmp (arg, "-s") == 0)
+       {
+         if (argv[argcnt + 1] == NULL)
+           error (_("Missing section name after \"-s\""));
+         else if (argv[argcnt + 2] == NULL)
+           error (_("Missing section address after \"-s\""));
+
+         sect_opt sect = { argv[argcnt + 1], argv[argcnt + 2] };
+
+         sect_opts.push_back (sect);
+         argcnt += 2;
+       }
+      else if (strcmp (arg, "-o") == 0)
+       {
+         arg = argv[++argcnt];
+         if (arg == NULL)
+           error (_("Missing argument to -o"));
+
+         offset = parse_and_eval_address (arg);
+         seen_offset = true;
        }
        }
+      else if (strcmp (arg, "--") == 0)
+       stop_processing_options = true;
+      else
+       error (_("Unrecognized argument \"%s\""), arg);
     }
 
     }
 
-  /* 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);
+  if (filename == NULL)
+    error (_("You must provide a filename to be loaded."));
+
+  validate_readnow_readnever (flags);
 
   /* Print the prompt for the query below.  And save the arguments into
      a sect_addr_info structure to be passed around to other
 
   /* Print the prompt for the query below.  And save the arguments into
      a sect_addr_info structure to be passed around to other
@@ -2366,24 +2291,31 @@ add_symbol_file_command (char *args, int from_tty)
      statements because hex_string returns a local static
      string.  */
 
      statements because hex_string returns a local static
      string.  */
 
-  printf_unfiltered (_("add symbol table from file \"%s\" at\n"), filename);
-  section_addrs = alloc_section_addr_info (section_index);
-  make_cleanup (xfree, section_addrs);
-  for (i = 0; i < section_index; i++)
+  printf_unfiltered (_("add symbol table from file \"%s\""),
+                    filename.get ());
+  section_addr_info section_addrs;
+  std::vector<sect_opt>::const_iterator it = sect_opts.begin ();
+  if (!seen_addr)
+    ++it;
+  for (; it != sect_opts.end (); ++it)
     {
       CORE_ADDR addr;
     {
       CORE_ADDR addr;
-      char *val = sect_opts[i].value;
-      char *sec = sect_opts[i].name;
+      const char *val = it->value;
+      const char *sec = it->name;
 
 
+      if (section_addrs.empty ())
+       printf_unfiltered (_(" at\n"));
       addr = parse_and_eval_address (val);
 
       /* Here we store the section offsets in the order they were
       addr = parse_and_eval_address (val);
 
       /* Here we store the section offsets in the order they were
-         entered on the command line.  */
-      section_addrs->other[sec_num].name = sec;
-      section_addrs->other[sec_num].addr = addr;
-      printf_unfiltered ("\t%s_addr = %s\n", sec,
-                        paddress (gdbarch, addr));
-      sec_num++;
+         entered on the command line.  Every array element is
+         assigned an ascending section index to preserve the above
+         order over an unstable sorting algorithm.  This dummy
+         index is not used for any other purpose.
+      */
+      section_addrs.emplace_back (addr, sec, section_addrs.size ());
+      printf_filtered ("\t%s_addr = %s\n", sec,
+                      paddress (gdbarch, addr));
 
       /* The object's sections are initialized when a
         call is made to build_objfile_section_table (objfile).
 
       /* The object's sections are initialized when a
         call is made to build_objfile_section_table (objfile).
@@ -2391,42 +2323,49 @@ add_symbol_file_command (char *args, int from_tty)
         At this point, we don't know what file type this is,
         so we can't determine what section names are valid.  */
     }
         At this point, we don't know what file type this is,
         so we can't determine what section names are valid.  */
     }
-  section_addrs->num_sections = sec_num;
+  if (seen_offset)
+      printf_unfiltered (_("%s offset by %s\n"),
+                        (section_addrs.empty ()
+                         ? _(" with all sections")
+                         : _("with other sections")),
+                        paddress (gdbarch, offset));
+  else if (section_addrs.empty ())
+    printf_unfiltered ("\n");
 
   if (from_tty && (!query ("%s", "")))
     error (_("Not confirmed."));
 
 
   if (from_tty && (!query ("%s", "")))
     error (_("Not confirmed."));
 
-  objf = symbol_file_add (filename, from_tty ? SYMFILE_VERBOSE : 0,
-                         section_addrs, flags);
+  objf = symbol_file_add (filename.get (), add_flags, &section_addrs,
+                         flags);
+  if (!objfile_has_symbols (objf) && objf->per_bfd->minimal_symbol_count <= 0)
+    warning (_("newly-added symbol file \"%s\" does not provide any symbols"),
+            filename.get ());
+
+  if (seen_offset)
+    set_objfile_default_section_offset (objf, section_addrs, offset);
 
   add_target_sections_of_objfile (objf);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
   reinit_frame_cache ();
 
   add_target_sections_of_objfile (objf);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
   reinit_frame_cache ();
-  do_cleanups (my_cleanups);
 }
 \f
 
 /* This function removes a symbol file that was added via add-symbol-file.  */
 
 static void
 }
 \f
 
 /* This function removes a symbol file that was added via add-symbol-file.  */
 
 static void
-remove_symbol_file_command (char *args, int from_tty)
+remove_symbol_file_command (const char *args, int from_tty)
 {
 {
-  char **argv;
   struct objfile *objf = NULL;
   struct objfile *objf = NULL;
-  struct cleanup *my_cleanups;
   struct program_space *pspace = current_program_space;
   struct program_space *pspace = current_program_space;
-  struct gdbarch *gdbarch = get_current_arch ();
 
   dont_repeat ();
 
   if (args == NULL)
     error (_("remove-symbol-file: no symbol file provided"));
 
 
   dont_repeat ();
 
   if (args == NULL)
     error (_("remove-symbol-file: no symbol file provided"));
 
-  my_cleanups = make_cleanup (null_cleanup, NULL);
-
-  argv = gdb_buildargv (args);
+  gdb_argv argv (args);
 
   if (strcmp (argv[0], "-a") == 0)
     {
 
   if (strcmp (argv[0], "-a") == 0)
     {
@@ -2441,32 +2380,37 @@ remove_symbol_file_command (char *args, int from_tty)
 
       addr = parse_and_eval_address (argv[1]);
 
 
       addr = parse_and_eval_address (argv[1]);
 
-      ALL_OBJFILES (objf)
+      for (objfile *objfile : current_program_space->objfiles ())
        {
        {
-         if ((objf->flags & OBJF_USERLOADED) != 0
-             && (objf->flags & OBJF_SHARED) != 0
-             && objf->pspace == pspace && is_addr_in_objfile (addr, objf))
-           break;
+         if ((objfile->flags & OBJF_USERLOADED) != 0
+             && (objfile->flags & OBJF_SHARED) != 0
+             && objfile->pspace == pspace
+             && is_addr_in_objfile (addr, objfile))
+           {
+             objf = objfile;
+             break;
+           }
        }
     }
   else if (argv[0] != NULL)
     {
       /* Interpret the current argument as a file name.  */
        }
     }
   else if (argv[0] != NULL)
     {
       /* Interpret the current argument as a file name.  */
-      char *filename;
 
       if (argv[1] != NULL)
        error (_("Junk after %s"), argv[0]);
 
 
       if (argv[1] != NULL)
        error (_("Junk after %s"), argv[0]);
 
-      filename = tilde_expand (argv[0]);
-      make_cleanup (xfree, filename);
+      gdb::unique_xmalloc_ptr<char> filename (tilde_expand (argv[0]));
 
 
-      ALL_OBJFILES (objf)
+      for (objfile *objfile : current_program_space->objfiles ())
        {
        {
-         if ((objf->flags & OBJF_USERLOADED) != 0
-             && (objf->flags & OBJF_SHARED) != 0
-             && objf->pspace == pspace
-             && filename_cmp (filename, objfile_name (objf)) == 0)
-           break;
+         if ((objfile->flags & OBJF_USERLOADED) != 0
+             && (objfile->flags & OBJF_SHARED) != 0
+             && objfile->pspace == pspace
+             && filename_cmp (filename.get (), objfile_name (objfile)) == 0)
+           {
+             objf = objfile;
+             break;
+           }
        }
     }
 
        }
     }
 
@@ -2478,37 +2422,21 @@ remove_symbol_file_command (char *args, int from_tty)
                 objfile_name (objf)))
     error (_("Not confirmed."));
 
                 objfile_name (objf)))
     error (_("Not confirmed."));
 
-  free_objfile (objf);
+  objf->unlink ();
   clear_symtab_users (0);
   clear_symtab_users (0);
-
-  do_cleanups (my_cleanups);
 }
 
 }
 
-typedef struct objfile *objfilep;
-
-DEF_VEC_P (objfilep);
-
 /* Re-read symbols if a symbol-file has changed.  */
 
 void
 reread_symbols (void)
 {
 /* Re-read symbols if a symbol-file has changed.  */
 
 void
 reread_symbols (void)
 {
-  struct objfile *objfile;
   long new_modtime;
   struct stat new_statbuf;
   int res;
   long new_modtime;
   struct stat new_statbuf;
   int res;
-  VEC (objfilep) *new_objfiles = NULL;
-  struct cleanup *all_cleanups;
-
-  all_cleanups = make_cleanup (VEC_cleanup (objfilep), &new_objfiles);
-
-  /* With the addition of shared libraries, this should be modified,
-     the load time should be saved in the partial symbol tables, since
-     different tables may come from different source files.  FIXME.
-     This routine should then walk down each partial symbol table
-     and see if the symbol table that it originates from has been changed.  */
+  std::vector<struct objfile *> new_objfiles;
 
 
-  for (objfile = object_files; objfile; objfile = objfile->next)
+  for (objfile *objfile : current_program_space->objfiles ())
     {
       if (objfile->obfd == NULL)
        continue;
     {
       if (objfile->obfd == NULL)
        continue;
@@ -2522,26 +2450,21 @@ reread_symbols (void)
         a `shared library' on AIX is also an archive), then you should
         stat on the archive name, not member name.  */
       if (objfile->obfd->my_archive)
         a `shared library' on AIX is also an archive), then you should
         stat on the archive name, not member name.  */
       if (objfile->obfd->my_archive)
-       res = stat (objfile->obfd->my_archive->filename, &new_statbuf);
+       res = stat (bfd_get_filename (objfile->obfd->my_archive), &new_statbuf);
       else
        res = stat (objfile_name (objfile), &new_statbuf);
       if (res != 0)
        {
          /* FIXME, should use print_sys_errmsg but it's not filtered.  */
       else
        res = stat (objfile_name (objfile), &new_statbuf);
       if (res != 0)
        {
          /* FIXME, should use print_sys_errmsg but it's not filtered.  */
-         printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"),
-                            objfile_name (objfile));
+         printf_filtered (_("`%s' has disappeared; keeping its symbols.\n"),
+                          objfile_name (objfile));
          continue;
        }
       new_modtime = new_statbuf.st_mtime;
       if (new_modtime != objfile->mtime)
        {
          continue;
        }
       new_modtime = new_statbuf.st_mtime;
       if (new_modtime != objfile->mtime)
        {
-         struct cleanup *old_cleanups;
-         struct section_offsets *offsets;
-         int num_offsets;
-         char *original_name;
-
-         printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"),
-                            objfile_name (objfile));
+         printf_filtered (_("`%s' has changed; re-reading symbols.\n"),
+                          objfile_name (objfile));
 
          /* There are various functions like symbol_file_add,
             symfile_bfd_open, syms_from_objfile, etc., which might
 
          /* There are various functions like symbol_file_add,
             symfile_bfd_open, syms_from_objfile, etc., which might
@@ -2553,9 +2476,10 @@ reread_symbols (void)
          /* If we get an error, blow away this objfile (not sure if
             that is the correct response for things like shared
             libraries).  */
          /* If we get an error, blow away this objfile (not sure if
             that is the correct response for things like shared
             libraries).  */
-         old_cleanups = make_cleanup_free_objfile (objfile);
+         objfile_up objfile_holder (objfile);
+
          /* We need to do this whenever any symbols go away.  */
          /* We need to do this whenever any symbols go away.  */
-         make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
+         clear_symtab_users_cleanup defer_clear_users (0);
 
          if (exec_bfd != NULL
              && filename_cmp (bfd_get_filename (objfile->obfd),
 
          if (exec_bfd != NULL
              && filename_cmp (bfd_get_filename (objfile->obfd),
@@ -2572,6 +2496,9 @@ reread_symbols (void)
             automatically recreated by sym_read.  */
          free_objfile_separate_debug (objfile);
 
             automatically recreated by sym_read.  */
          free_objfile_separate_debug (objfile);
 
+         /* Clear the stale source cache.  */
+         forget_cached_source_info ();
+
          /* Remove any references to this objfile in the global
             value lists.  */
          preserve_values (objfile);
          /* Remove any references to this objfile in the global
             value lists.  */
          preserve_values (objfile);
@@ -2591,61 +2518,39 @@ reread_symbols (void)
 
          /* Clean up any state BFD has sitting around.  */
          {
 
          /* Clean up any state BFD has sitting around.  */
          {
-           struct bfd *obfd = objfile->obfd;
-           char *obfd_filename;
+           gdb_bfd_ref_ptr obfd (objfile->obfd);
+           const char *obfd_filename;
 
            obfd_filename = bfd_get_filename (objfile->obfd);
            /* Open the new BFD before freeing the old one, so that
               the filename remains live.  */
 
            obfd_filename = bfd_get_filename (objfile->obfd);
            /* Open the new BFD before freeing the old one, so that
               the filename remains live.  */
-           objfile->obfd = gdb_bfd_open_maybe_remote (obfd_filename);
+           gdb_bfd_ref_ptr temp (gdb_bfd_open (obfd_filename, gnutarget));
+           objfile->obfd = temp.release ();
            if (objfile->obfd == NULL)
            if (objfile->obfd == NULL)
-             {
-               /* We have to make a cleanup and error here, rather
-                  than erroring later, because once we unref OBFD,
-                  OBFD_FILENAME will be freed.  */
-               make_cleanup_bfd_unref (obfd);
-               error (_("Can't open %s to read symbols."), obfd_filename);
-             }
-           gdb_bfd_unref (obfd);
+             error (_("Can't open %s to read symbols."), obfd_filename);
          }
 
          }
 
-         original_name = xstrdup (objfile->original_name);
-         make_cleanup (xfree, original_name);
+         std::string original_name = objfile->original_name;
 
          /* bfd_openr sets cacheable to true, which is what we want.  */
          if (!bfd_check_format (objfile->obfd, bfd_object))
            error (_("Can't read symbols from %s: %s."), objfile_name (objfile),
                   bfd_errmsg (bfd_get_error ()));
 
 
          /* bfd_openr sets cacheable to true, which is what we want.  */
          if (!bfd_check_format (objfile->obfd, bfd_object))
            error (_("Can't read symbols from %s: %s."), objfile_name (objfile),
                   bfd_errmsg (bfd_get_error ()));
 
-         /* Save the offsets, we will nuke them with the rest of the
-            objfile_obstack.  */
-         num_offsets = objfile->num_sections;
-         offsets = ((struct section_offsets *)
-                    alloca (SIZEOF_N_SECTION_OFFSETS (num_offsets)));
-         memcpy (offsets, objfile->section_offsets,
-                 SIZEOF_N_SECTION_OFFSETS (num_offsets));
-
-         /* FIXME: Do we have to free a whole linked list, or is this
-            enough?  */
-         if (objfile->global_psymbols.list)
-           xfree (objfile->global_psymbols.list);
-         memset (&objfile->global_psymbols, 0,
-                 sizeof (objfile->global_psymbols));
-         if (objfile->static_psymbols.list)
-           xfree (objfile->static_psymbols.list);
-         memset (&objfile->static_psymbols, 0,
-                 sizeof (objfile->static_psymbols));
-
-         /* Free the obstacks for non-reusable objfiles.  */
-         psymbol_bcache_free (objfile->psymbol_cache);
-         objfile->psymbol_cache = psymbol_bcache_init ();
+         objfile->reset_psymtabs ();
+
+         /* NB: after this call to obstack_free, objfiles_changed
+            will need to be called (see discussion below).  */
          obstack_free (&objfile->objfile_obstack, 0);
          objfile->sections = NULL;
          obstack_free (&objfile->objfile_obstack, 0);
          objfile->sections = NULL;
-         objfile->symtabs = NULL;
-         objfile->psymtabs = NULL;
-         objfile->psymtabs_addrmap = NULL;
-         objfile->free_psymtabs = NULL;
+         objfile->section_offsets.clear ();
+         objfile->sect_index_bss = -1;
+         objfile->sect_index_data = -1;
+         objfile->sect_index_rodata = -1;
+         objfile->sect_index_text = -1;
+         objfile->compunit_symtabs = NULL;
          objfile->template_symbols = NULL;
          objfile->template_symbols = NULL;
+         objfile->static_links.reset (nullptr);
 
          /* obstack_init also initializes the obstack so it is
             empty.  We could use obstack_specify_allocation but
 
          /* obstack_init also initializes the obstack so it is
             empty.  We could use obstack_specify_allocation but
@@ -2658,9 +2563,8 @@ reread_symbols (void)
             do it *after* the obstack has been initialized.  */
          set_objfile_per_bfd (objfile);
 
             do it *after* the obstack has been initialized.  */
          set_objfile_per_bfd (objfile);
 
-         objfile->original_name = obstack_copy0 (&objfile->objfile_obstack,
-                                                 original_name,
-                                                 strlen (original_name));
+         objfile->original_name
+           = obstack_strdup (&objfile->objfile_obstack, original_name);
 
          /* Reset the sym_fns pointer.  The ELF reader can change it
             based on whether .gdb_index is present, and we need it to
 
          /* Reset the sym_fns pointer.  The ELF reader can change it
             based on whether .gdb_index is present, and we need it to
@@ -2668,16 +2572,6 @@ reread_symbols (void)
          objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
 
          build_objfile_section_table (objfile);
          objfile_set_sym_fns (objfile, find_sym_fns (objfile->obfd));
 
          build_objfile_section_table (objfile);
-         terminate_minimal_symbol_table (objfile);
-
-         /* We use the same section offsets as from last time.  I'm not
-            sure whether that is always correct for shared libraries.  */
-         objfile->section_offsets = (struct section_offsets *)
-           obstack_alloc (&objfile->objfile_obstack,
-                          SIZEOF_N_SECTION_OFFSETS (num_offsets));
-         memcpy (objfile->section_offsets, offsets,
-                 SIZEOF_N_SECTION_OFFSETS (num_offsets));
-         objfile->num_sections = num_offsets;
 
          /* What the hell is sym_new_init for, anyway?  The concept of
             distinguishing between the main file and additional files
 
          /* What the hell is sym_new_init for, anyway?  The concept of
             distinguishing between the main file and additional files
@@ -2688,20 +2582,40 @@ reread_symbols (void)
            }
 
          (*objfile->sf->sym_init) (objfile);
            }
 
          (*objfile->sf->sym_init) (objfile);
-         clear_complaints (&symfile_complaints, 1, 1);
+         clear_complaints ();
 
          objfile->flags &= ~OBJF_PSYMTABS_READ;
 
          objfile->flags &= ~OBJF_PSYMTABS_READ;
+
+         /* We are about to read new symbols and potentially also
+            DWARF information.  Some targets may want to pass addresses
+            read from DWARF DIE's through an adjustment function before
+            saving them, like MIPS, which may call into
+            "find_pc_section".  When called, that function will make
+            use of per-objfile program space data.
+
+            Since we discarded our section information above, we have
+            dangling pointers in the per-objfile program space data
+            structure.  Force GDB to update the section mapping
+            information by letting it know the objfile has changed,
+            making the dangling pointers point to correct data
+            again.  */
+
+         objfiles_changed ();
+
+         /* Recompute section offsets and section indices.  */
+         objfile->sf->sym_offsets (objfile, {});
+
          read_symbols (objfile, 0);
 
          if (!objfile_has_symbols (objfile))
            {
              wrap_here ("");
          read_symbols (objfile, 0);
 
          if (!objfile_has_symbols (objfile))
            {
              wrap_here ("");
-             printf_unfiltered (_("(no debugging symbols found)\n"));
+             printf_filtered (_("(no debugging symbols found)\n"));
              wrap_here ("");
            }
 
          /* We're done reading the symbol file; finish off complaints.  */
              wrap_here ("");
            }
 
          /* We're done reading the symbol file; finish off complaints.  */
-         clear_complaints (&symfile_complaints, 0, 1);
+         clear_complaints ();
 
          /* Getting new symbols may change our opinion about what is
             frameless.  */
 
          /* Getting new symbols may change our opinion about what is
             frameless.  */
@@ -2709,7 +2623,8 @@ reread_symbols (void)
          reinit_frame_cache ();
 
          /* Discard cleanups as symbol reading was successful.  */
          reinit_frame_cache ();
 
          /* Discard cleanups as symbol reading was successful.  */
-         discard_cleanups (old_cleanups);
+         objfile_holder.release ();
+         defer_clear_users.release ();
 
          /* If the mtime has changed between the time we set new_modtime
             and now, we *want* this to be out of date, so don't call stat
 
          /* If the mtime has changed between the time we set new_modtime
             and now, we *want* this to be out of date, so don't call stat
@@ -2717,58 +2632,45 @@ reread_symbols (void)
          objfile->mtime = new_modtime;
          init_entry_point_info (objfile);
 
          objfile->mtime = new_modtime;
          init_entry_point_info (objfile);
 
-         VEC_safe_push (objfilep, new_objfiles, objfile);
+         new_objfiles.push_back (objfile);
        }
     }
 
        }
     }
 
-  if (new_objfiles)
+  if (!new_objfiles.empty ())
     {
     {
-      int ix;
-
-      /* Notify objfiles that we've modified objfile sections.  */
-      objfiles_changed ();
-
       clear_symtab_users (0);
 
       /* clear_objfile_data for each objfile was called before freeing it and
       clear_symtab_users (0);
 
       /* clear_objfile_data for each objfile was called before freeing it and
-        observer_notify_new_objfile (NULL) has been called by
+        gdb::observers::new_objfile.notify (NULL) has been called by
         clear_symtab_users above.  Notify the new files now.  */
         clear_symtab_users above.  Notify the new files now.  */
-      for (ix = 0; VEC_iterate (objfilep, new_objfiles, ix, objfile); ix++)
-       observer_notify_new_objfile (objfile);
+      for (auto iter : new_objfiles)
+       gdb::observers::new_objfile.notify (iter);
 
       /* At least one objfile has changed, so we can consider that
          the executable we're debugging has changed too.  */
 
       /* At least one objfile has changed, so we can consider that
          the executable we're debugging has changed too.  */
-      observer_notify_executable_changed ();
+      gdb::observers::executable_changed.notify ();
     }
     }
-
-  do_cleanups (all_cleanups);
 }
 \f
 
 }
 \f
 
-typedef struct
+struct filename_language
 {
 {
-  char *ext;
+  filename_language (const std::string &ext_, enum language lang_)
+  : ext (ext_), lang (lang_)
+  {}
+
+  std::string ext;
   enum language lang;
   enum language lang;
-}
-filename_language;
+};
 
 
-static filename_language *filename_language_table;
-static int fl_table_size, fl_table_next;
+static std::vector<filename_language> filename_language_table;
 
 
-static void
-add_filename_language (char *ext, enum language lang)
-{
-  if (fl_table_next >= fl_table_size)
-    {
-      fl_table_size += 10;
-      filename_language_table =
-       xrealloc (filename_language_table,
-                 fl_table_size * sizeof (*filename_language_table));
-    }
+/* See symfile.h.  */
 
 
-  filename_language_table[fl_table_next].ext = xstrdup (ext);
-  filename_language_table[fl_table_next].lang = lang;
-  fl_table_next++;
+void
+add_filename_language (const char *ext, enum language lang)
+{
+  filename_language_table.emplace_back (ext, lang);
 }
 
 static char *ext_args;
 }
 
 static char *ext_args;
@@ -2783,9 +2685,9 @@ show_ext_args (struct ui_file *file, int from_tty,
 }
 
 static void
 }
 
 static void
-set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
+set_ext_lang_command (const char *args,
+                     int from_tty, struct cmd_list_element *e)
 {
 {
-  int i;
   char *cp = ext_args;
   enum language lang;
 
   char *cp = ext_args;
   enum language lang;
 
@@ -2816,12 +2718,15 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
   /* Lookup the language from among those we know.  */
   lang = language_enum (cp);
 
   /* Lookup the language from among those we know.  */
   lang = language_enum (cp);
 
+  auto it = filename_language_table.begin ();
   /* Now lookup the filename extension: do we already know it?  */
   /* Now lookup the filename extension: do we already know it?  */
-  for (i = 0; i < fl_table_next; i++)
-    if (0 == strcmp (ext_args, filename_language_table[i].ext))
-      break;
+  for (; it != filename_language_table.end (); it++)
+    {
+      if (it->ext == ext_args)
+       break;
+    }
 
 
-  if (i >= fl_table_next)
+  if (it == filename_language_table.end ())
     {
       /* New file extension.  */
       add_filename_language (ext_args, lang);
     {
       /* New file extension.  */
       add_filename_language (ext_args, lang);
@@ -2834,122 +2739,49 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
       /*   query ("Really make files of type %s '%s'?", */
       /*          ext_args, language_str (lang));           */
 
       /*   query ("Really make files of type %s '%s'?", */
       /*          ext_args, language_str (lang));           */
 
-      xfree (filename_language_table[i].ext);
-      filename_language_table[i].ext = xstrdup (ext_args);
-      filename_language_table[i].lang = lang;
+      it->lang = lang;
     }
 }
 
 static void
     }
 }
 
 static void
-info_ext_lang_command (char *args, int from_tty)
+info_ext_lang_command (const char *args, int from_tty)
 {
 {
-  int i;
-
   printf_filtered (_("Filename extensions and the languages they represent:"));
   printf_filtered ("\n\n");
   printf_filtered (_("Filename extensions and the languages they represent:"));
   printf_filtered ("\n\n");
-  for (i = 0; i < fl_table_next; i++)
-    printf_filtered ("\t%s\t- %s\n",
-                    filename_language_table[i].ext,
-                    language_str (filename_language_table[i].lang));
-}
-
-static void
-init_filename_language_table (void)
-{
-  if (fl_table_size == 0)      /* Protect against repetition.  */
-    {
-      fl_table_size = 20;
-      fl_table_next = 0;
-      filename_language_table =
-       xmalloc (fl_table_size * sizeof (*filename_language_table));
-      add_filename_language (".c", language_c);
-      add_filename_language (".d", language_d);
-      add_filename_language (".C", language_cplus);
-      add_filename_language (".cc", language_cplus);
-      add_filename_language (".cp", language_cplus);
-      add_filename_language (".cpp", language_cplus);
-      add_filename_language (".cxx", language_cplus);
-      add_filename_language (".c++", language_cplus);
-      add_filename_language (".java", language_java);
-      add_filename_language (".class", language_java);
-      add_filename_language (".m", language_objc);
-      add_filename_language (".f", language_fortran);
-      add_filename_language (".F", language_fortran);
-      add_filename_language (".for", language_fortran);
-      add_filename_language (".FOR", language_fortran);
-      add_filename_language (".ftn", language_fortran);
-      add_filename_language (".FTN", language_fortran);
-      add_filename_language (".fpp", language_fortran);
-      add_filename_language (".FPP", language_fortran);
-      add_filename_language (".f90", language_fortran);
-      add_filename_language (".F90", language_fortran);
-      add_filename_language (".f95", language_fortran);
-      add_filename_language (".F95", language_fortran);
-      add_filename_language (".f03", language_fortran);
-      add_filename_language (".F03", language_fortran);
-      add_filename_language (".f08", language_fortran);
-      add_filename_language (".F08", 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);
-      add_filename_language (".pp", language_pascal);
-      add_filename_language (".adb", language_ada);
-      add_filename_language (".ads", language_ada);
-      add_filename_language (".a", language_ada);
-      add_filename_language (".ada", language_ada);
-      add_filename_language (".dg", language_ada);
-    }
+  for (const filename_language &entry : filename_language_table)
+    printf_filtered ("\t%s\t- %s\n", entry.ext.c_str (),
+                    language_str (entry.lang));
 }
 
 enum language
 deduce_language_from_filename (const char *filename)
 {
 }
 
 enum language
 deduce_language_from_filename (const char *filename)
 {
-  int i;
-  char *cp;
+  const char *cp;
 
   if (filename != NULL)
     if ((cp = strrchr (filename, '.')) != NULL)
 
   if (filename != NULL)
     if ((cp = strrchr (filename, '.')) != NULL)
-      for (i = 0; i < fl_table_next; i++)
-       if (strcmp (cp, filename_language_table[i].ext) == 0)
-         return filename_language_table[i].lang;
+      {
+       for (const filename_language &entry : filename_language_table)
+         if (entry.ext == cp)
+           return entry.lang;
+      }
 
   return language_unknown;
 }
 \f
 
   return language_unknown;
 }
 \f
-/* allocate_symtab:
-
-   Allocate and partly initialize a new symbol table.  Return a pointer
-   to it.  error() if no space.
-
-   Caller must set these fields:
-   LINETABLE(symtab)
-   symtab->blockvector
-   symtab->dirname
-   symtab->free_code
-   symtab->free_ptr
- */
+/* Allocate and initialize a new symbol table.
+   CUST is from the result of allocate_compunit_symtab.  */
 
 struct symtab *
 
 struct symtab *
-allocate_symtab (const char *filename, struct objfile *objfile)
+allocate_symtab (struct compunit_symtab *cust, const char *filename)
 {
 {
-  struct symtab *symtab;
+  struct objfile *objfile = cust->objfile;
+  struct symtab *symtab
+    = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symtab);
 
 
-  symtab = (struct symtab *)
-    obstack_alloc (&objfile->objfile_obstack, sizeof (struct symtab));
-  memset (symtab, 0, sizeof (*symtab));
-  symtab->filename = bcache (filename, strlen (filename) + 1,
-                            objfile->per_bfd->filename_cache);
+  symtab->filename = objfile->intern (filename);
   symtab->fullname = NULL;
   symtab->language = deduce_language_from_filename (filename);
   symtab->fullname = NULL;
   symtab->language = deduce_language_from_filename (filename);
-  symtab->debugformat = "unknown";
-
-  /* Hook it to the objfile it comes from.  */
-
-  SYMTAB_OBJFILE (symtab) = objfile;
-  symtab->next = objfile->symtabs;
-  objfile->symtabs = symtab;
 
   /* This can be very verbose with lots of headers.
      Only print at higher debug levels.  */
 
   /* This can be very verbose with lots of headers.
      Only print at higher debug levels.  */
@@ -2964,24 +2796,80 @@ allocate_symtab (const char *filename, struct objfile *objfile)
        {
          xfree (last_objfile_name);
          last_objfile_name = xstrdup (objfile_name (objfile));
        {
          xfree (last_objfile_name);
          last_objfile_name = xstrdup (objfile_name (objfile));
-         fprintf_unfiltered (gdb_stdlog,
-                             "Creating one or more symtabs for objfile %s ...\n",
-                             last_objfile_name);
+         fprintf_filtered (gdb_stdlog,
+                           "Creating one or more symtabs for objfile %s ...\n",
+                           last_objfile_name);
        }
        }
-      fprintf_unfiltered (gdb_stdlog,
-                         "Created symtab %s for module %s.\n",
-                         host_address_to_string (symtab), filename);
+      fprintf_filtered (gdb_stdlog,
+                       "Created symtab %s for module %s.\n",
+                       host_address_to_string (symtab), filename);
     }
 
     }
 
-  return (symtab);
+  /* Add it to CUST's list of symtabs.  */
+  if (cust->filetabs == NULL)
+    {
+      cust->filetabs = symtab;
+      cust->last_filetab = symtab;
+    }
+  else
+    {
+      cust->last_filetab->next = symtab;
+      cust->last_filetab = symtab;
+    }
+
+  /* Backlink to the containing compunit symtab.  */
+  symtab->compunit_symtab = cust;
+
+  return symtab;
+}
+
+/* Allocate and initialize a new compunit.
+   NAME is the name of the main source file, if there is one, or some
+   descriptive text if there are no source files.  */
+
+struct compunit_symtab *
+allocate_compunit_symtab (struct objfile *objfile, const char *name)
+{
+  struct compunit_symtab *cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                              struct compunit_symtab);
+  const char *saved_name;
+
+  cu->objfile = objfile;
+
+  /* The name we record here is only for display/debugging purposes.
+     Just save the basename to avoid path issues (too long for display,
+     relative vs absolute, etc.).  */
+  saved_name = lbasename (name);
+  cu->name = obstack_strdup (&objfile->objfile_obstack, saved_name);
+
+  COMPUNIT_DEBUGFORMAT (cu) = "unknown";
+
+  if (symtab_create_debug)
+    {
+      fprintf_filtered (gdb_stdlog,
+                       "Created compunit symtab %s for %s.\n",
+                       host_address_to_string (cu),
+                       cu->name);
+    }
+
+  return cu;
+}
+
+/* Hook CU to the objfile it comes from.  */
+
+void
+add_compunit_symtab_to_objfile (struct compunit_symtab *cu)
+{
+  cu->next = cu->objfile->compunit_symtabs;
+  cu->objfile->compunit_symtabs = cu;
 }
 \f
 
 }
 \f
 
-/* Reset all data structures in gdb which may contain references to symbol
-   table data.  ADD_FLAGS is a bitmask of enum symfile_add_flags.  */
+/* Reset all data structures in gdb which may contain references to
+   symbol table data.  */
 
 void
 
 void
-clear_symtab_users (int add_flags)
+clear_symtab_users (symfile_add_flags add_flags)
 {
   /* Someday, we should do better than this, by only blowing away
      the things that really need to be blown.  */
 {
   /* Someday, we should do better than this, by only blowing away
      the things that really need to be blown.  */
@@ -2991,27 +2879,17 @@ clear_symtab_users (int add_flags)
   clear_current_source_symtab_and_line ();
 
   clear_displays ();
   clear_current_source_symtab_and_line ();
 
   clear_displays ();
-  if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
-    breakpoint_re_set ();
   clear_last_displayed_sal ();
   clear_pc_function_cache ();
   clear_last_displayed_sal ();
   clear_pc_function_cache ();
-  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;
+  gdb::observers::new_objfile.notify (NULL);
 
   /* Varobj may refer to old symbols, perform a cleanup.  */
   varobj_invalidate ();
 
 
   /* Varobj may refer to old symbols, perform a cleanup.  */
   varobj_invalidate ();
 
-}
-
-static void
-clear_symtab_users_cleanup (void *ignore)
-{
-  clear_symtab_users (0);
+  /* Now that the various caches have been cleared, we can re_set
+     our breakpoints without risking it using stale data.  */
+  if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0)
+    breakpoint_re_set ();
 }
 \f
 /* OVERLAYS:
 }
 \f
 /* OVERLAYS:
@@ -3076,12 +2954,10 @@ section_is_overlay (struct obj_section *section)
 {
   if (overlay_debugging && section)
     {
 {
   if (overlay_debugging && section)
     {
-      bfd *abfd = section->objfile->obfd;
       asection *bfd_section = section->the_bfd_section;
 
       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))
+      if (bfd_section_lma (bfd_section) != 0
+         && bfd_section_lma (bfd_section) != bfd_section_vma (bfd_section))
        return 1;
     }
 
        return 1;
     }
 
@@ -3094,12 +2970,12 @@ section_is_overlay (struct obj_section *section)
 static void
 overlay_invalidate_all (void)
 {
 static void
 overlay_invalidate_all (void)
 {
-  struct objfile *objfile;
   struct obj_section *sect;
 
   struct obj_section *sect;
 
-  ALL_OBJSECTIONS (objfile, sect)
-    if (section_is_overlay (sect))
-      sect->ovly_mapped = -1;
+  for (objfile *objfile : current_program_space->objfiles ())
+    ALL_OBJFILE_OSECTIONS (objfile, sect)
+      if (section_is_overlay (sect))
+       sect->ovly_mapped = -1;
 }
 
 /* Function: section_is_mapped (SECTION)
 }
 
 /* Function: section_is_mapped (SECTION)
@@ -3127,7 +3003,7 @@ section_is_mapped (struct obj_section *osect)
     case ovly_auto:            /* overlay debugging automatic */
       /* Unles there is a gdbarch_overlay_update function,
          there's really nothing useful to do here (can't really go auto).  */
     case ovly_auto:            /* overlay debugging automatic */
       /* Unles there is a gdbarch_overlay_update function,
          there's really nothing useful to do here (can't really go auto).  */
-      gdbarch = get_objfile_arch (osect->objfile);
+      gdbarch = osect->objfile->arch ();
       if (gdbarch_overlay_update_p (gdbarch))
        {
          if (overlay_cache_invalid)
       if (gdbarch_overlay_update_p (gdbarch))
        {
          if (overlay_cache_invalid)
@@ -3138,7 +3014,7 @@ section_is_mapped (struct obj_section *osect)
          if (osect->ovly_mapped == -1)
            gdbarch_overlay_update (gdbarch, osect);
        }
          if (osect->ovly_mapped == -1)
            gdbarch_overlay_update (gdbarch, osect);
        }
-      /* fall thru to manual case */
+      /* fall thru */
     case ovly_on:              /* overlay debugging manual */
       return osect->ovly_mapped == 1;
     }
     case ovly_on:              /* overlay debugging manual */
       return osect->ovly_mapped == 1;
     }
@@ -3152,15 +3028,14 @@ pc_in_unmapped_range (CORE_ADDR pc, struct obj_section *section)
 {
   if (section_is_overlay (section))
     {
 {
   if (section_is_overlay (section))
     {
-      bfd *abfd = section->objfile->obfd;
       asection *bfd_section = section->the_bfd_section;
 
       /* We assume the LMA is relocated by the same offset as the VMA.  */
       asection *bfd_section = section->the_bfd_section;
 
       /* We assume the LMA is relocated by the same offset as the VMA.  */
-      bfd_vma size = bfd_get_section_size (bfd_section);
+      bfd_vma size = bfd_section_size (bfd_section);
       CORE_ADDR offset = obj_section_offset (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)
+      if (bfd_section_lma (bfd_section) + offset <= pc
+         && pc < bfd_section_lma (bfd_section) + offset + size)
        return 1;
     }
 
        return 1;
     }
 
@@ -3206,11 +3081,10 @@ overlay_unmapped_address (CORE_ADDR pc, struct obj_section *section)
 {
   if (section_is_overlay (section) && pc_in_mapped_range (pc, section))
     {
 {
   if (section_is_overlay (section) && pc_in_mapped_range (pc, section))
     {
-      bfd *abfd = section->objfile->obfd;
       asection *bfd_section = section->the_bfd_section;
 
       asection *bfd_section = section->the_bfd_section;
 
-      return pc + bfd_section_lma (abfd, bfd_section)
-               - bfd_section_vma (abfd, bfd_section);
+      return (pc + bfd_section_lma (bfd_section)
+             - bfd_section_vma (bfd_section));
     }
 
   return pc;
     }
 
   return pc;
@@ -3225,11 +3099,10 @@ overlay_mapped_address (CORE_ADDR pc, struct obj_section *section)
 {
   if (section_is_overlay (section) && pc_in_unmapped_range (pc, section))
     {
 {
   if (section_is_overlay (section) && pc_in_unmapped_range (pc, section))
     {
-      bfd *abfd = section->objfile->obfd;
       asection *bfd_section = section->the_bfd_section;
 
       asection *bfd_section = section->the_bfd_section;
 
-      return pc + bfd_section_vma (abfd, bfd_section)
-               - bfd_section_lma (abfd, bfd_section);
+      return (pc + bfd_section_vma (bfd_section)
+             - bfd_section_lma (bfd_section));
     }
 
   return pc;
     }
 
   return pc;
@@ -3272,23 +3145,25 @@ symbol_overlayed_address (CORE_ADDR address, struct obj_section *section)
 struct obj_section *
 find_pc_overlay (CORE_ADDR pc)
 {
 struct obj_section *
 find_pc_overlay (CORE_ADDR pc)
 {
-  struct objfile *objfile;
   struct obj_section *osect, *best_match = NULL;
 
   if (overlay_debugging)
   struct obj_section *osect, *best_match = NULL;
 
   if (overlay_debugging)
-    ALL_OBJSECTIONS (objfile, osect)
-      if (section_is_overlay (osect))
-      {
-       if (pc_in_mapped_range (pc, osect))
-         {
-           if (section_is_mapped (osect))
-             return osect;
-           else
-             best_match = osect;
-         }
-       else if (pc_in_unmapped_range (pc, osect))
-         best_match = osect;
-      }
+    {
+      for (objfile *objfile : current_program_space->objfiles ())
+       ALL_OBJFILE_OSECTIONS (objfile, osect)
+         if (section_is_overlay (osect))
+           {
+             if (pc_in_mapped_range (pc, osect))
+               {
+                 if (section_is_mapped (osect))
+                   return osect;
+                 else
+                   best_match = osect;
+               }
+             else if (pc_in_unmapped_range (pc, osect))
+               best_match = osect;
+           }
+    }
   return best_match;
 }
 
   return best_match;
 }
 
@@ -3299,13 +3174,15 @@ find_pc_overlay (CORE_ADDR pc)
 struct obj_section *
 find_pc_mapped_section (CORE_ADDR pc)
 {
 struct obj_section *
 find_pc_mapped_section (CORE_ADDR pc)
 {
-  struct objfile *objfile;
   struct obj_section *osect;
 
   if (overlay_debugging)
   struct obj_section *osect;
 
   if (overlay_debugging)
-    ALL_OBJSECTIONS (objfile, osect)
-      if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
-       return osect;
+    {
+      for (objfile *objfile : current_program_space->objfiles ())
+       ALL_OBJFILE_OSECTIONS (objfile, osect)
+         if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
+           return osect;
+    }
 
   return NULL;
 }
 
   return NULL;
 }
@@ -3314,38 +3191,40 @@ find_pc_mapped_section (CORE_ADDR pc)
    Print a list of mapped sections and their PC ranges.  */
 
 static void
    Print a list of mapped sections and their PC ranges.  */
 
 static void
-list_overlays_command (char *args, int from_tty)
+list_overlays_command (const char *args, int from_tty)
 {
   int nmapped = 0;
 {
   int nmapped = 0;
-  struct objfile *objfile;
   struct obj_section *osect;
 
   if (overlay_debugging)
   struct obj_section *osect;
 
   if (overlay_debugging)
-    ALL_OBJSECTIONS (objfile, osect)
-      if (section_is_mapped (osect))
-      {
-       struct gdbarch *gdbarch = get_objfile_arch (objfile);
-       const char *name;
-       bfd_vma lma, vma;
-       int size;
-
-       vma = bfd_section_vma (objfile->obfd, osect->the_bfd_section);
-       lma = bfd_section_lma (objfile->obfd, osect->the_bfd_section);
-       size = bfd_get_section_size (osect->the_bfd_section);
-       name = bfd_section_name (objfile->obfd, osect->the_bfd_section);
-
-       printf_filtered ("Section %s, loaded at ", name);
-       fputs_filtered (paddress (gdbarch, lma), gdb_stdout);
-       puts_filtered (" - ");
-       fputs_filtered (paddress (gdbarch, lma + size), gdb_stdout);
-       printf_filtered (", mapped at ");
-       fputs_filtered (paddress (gdbarch, vma), gdb_stdout);
-       puts_filtered (" - ");
-       fputs_filtered (paddress (gdbarch, vma + size), gdb_stdout);
-       puts_filtered ("\n");
-
-       nmapped++;
-      }
+    {
+      for (objfile *objfile : current_program_space->objfiles ())
+       ALL_OBJFILE_OSECTIONS (objfile, osect)
+         if (section_is_mapped (osect))
+           {
+             struct gdbarch *gdbarch = objfile->arch ();
+             const char *name;
+             bfd_vma lma, vma;
+             int size;
+
+             vma = bfd_section_vma (osect->the_bfd_section);
+             lma = bfd_section_lma (osect->the_bfd_section);
+             size = bfd_section_size (osect->the_bfd_section);
+             name = bfd_section_name (osect->the_bfd_section);
+
+             printf_filtered ("Section %s, loaded at ", name);
+             fputs_filtered (paddress (gdbarch, lma), gdb_stdout);
+             puts_filtered (" - ");
+             fputs_filtered (paddress (gdbarch, lma + size), gdb_stdout);
+             printf_filtered (", mapped at ");
+             fputs_filtered (paddress (gdbarch, vma), gdb_stdout);
+             puts_filtered (" - ");
+             fputs_filtered (paddress (gdbarch, vma + size), gdb_stdout);
+             puts_filtered ("\n");
+
+             nmapped++;
+           }
+    }
   if (nmapped == 0)
     printf_filtered (_("No sections are mapped.\n"));
 }
   if (nmapped == 0)
     printf_filtered (_("No sections are mapped.\n"));
 }
@@ -3354,9 +3233,8 @@ list_overlays_command (char *args, int from_tty)
    Mark the named section as mapped (ie. residing at its VMA address).  */
 
 static void
    Mark the named section as mapped (ie. residing at its VMA address).  */
 
 static void
-map_overlay_command (char *args, int from_tty)
+map_overlay_command (const char *args, int from_tty)
 {
 {
-  struct objfile *objfile, *objfile2;
   struct obj_section *sec, *sec2;
 
   if (!overlay_debugging)
   struct obj_section *sec, *sec2;
 
   if (!overlay_debugging)
@@ -3368,29 +3246,31 @@ map_overlay_command (char *args, int from_tty)
     error (_("Argument required: name of an overlay section"));
 
   /* First, find a section matching the user supplied argument.  */
     error (_("Argument required: name of an overlay section"));
 
   /* First, find a section matching the user supplied argument.  */
-  ALL_OBJSECTIONS (objfile, sec)
-    if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args))
-    {
-      /* Now, check to see if the section is an overlay.  */
-      if (!section_is_overlay (sec))
-       continue;               /* not an overlay section */
-
-      /* Mark the overlay as "mapped".  */
-      sec->ovly_mapped = 1;
-
-      /* 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 && sections_overlap (sec, sec2))
+  for (objfile *obj_file : current_program_space->objfiles ())
+    ALL_OBJFILE_OSECTIONS (obj_file, sec)
+      if (!strcmp (bfd_section_name (sec->the_bfd_section), args))
        {
        {
-         if (info_verbose)
-           printf_unfiltered (_("Note: section %s unmapped by overlap\n"),
-                            bfd_section_name (objfile->obfd,
-                                              sec2->the_bfd_section));
-         sec2->ovly_mapped = 0;        /* sec2 overlaps sec: unmap sec2.  */
+         /* Now, check to see if the section is an overlay.  */
+         if (!section_is_overlay (sec))
+           continue;           /* not an overlay section */
+
+         /* Mark the overlay as "mapped".  */
+         sec->ovly_mapped = 1;
+
+         /* Next, make a pass and unmap any sections that are
+            overlapped by this new section: */
+         for (objfile *objfile2 : current_program_space->objfiles ())
+           ALL_OBJFILE_OSECTIONS (objfile2, sec2)
+             if (sec2->ovly_mapped && sec != sec2 && sections_overlap (sec,
+                                                                       sec2))
+               {
+                 if (info_verbose)
+                   printf_unfiltered (_("Note: section %s unmapped by overlap\n"),
+                                      bfd_section_name (sec2->the_bfd_section));
+                 sec2->ovly_mapped = 0; /* sec2 overlaps sec: unmap sec2.  */
+               }
+         return;
        }
        }
-      return;
-    }
   error (_("No overlay section called %s"), args);
 }
 
   error (_("No overlay section called %s"), args);
 }
 
@@ -3399,10 +3279,9 @@ map_overlay_command (char *args, int from_tty)
    (ie. resident in its LMA address range, rather than the VMA range).  */
 
 static void
    (ie. resident in its LMA address range, rather than the VMA range).  */
 
 static void
-unmap_overlay_command (char *args, int from_tty)
+unmap_overlay_command (const char *args, int from_tty)
 {
 {
-  struct objfile *objfile;
-  struct obj_section *sec;
+  struct obj_section *sec = NULL;
 
   if (!overlay_debugging)
     error (_("Overlay debugging not enabled.  "
 
   if (!overlay_debugging)
     error (_("Overlay debugging not enabled.  "
@@ -3413,14 +3292,15 @@ unmap_overlay_command (char *args, int from_tty)
     error (_("Argument required: name of an overlay section"));
 
   /* First, find a section matching the user supplied argument.  */
     error (_("Argument required: name of an overlay section"));
 
   /* First, find a section matching the user supplied argument.  */
-  ALL_OBJSECTIONS (objfile, sec)
-    if (!strcmp (bfd_section_name (objfile->obfd, sec->the_bfd_section), args))
-    {
-      if (!sec->ovly_mapped)
-       error (_("Section %s is not mapped"), args);
-      sec->ovly_mapped = 0;
-      return;
-    }
+  for (objfile *objfile : current_program_space->objfiles ())
+    ALL_OBJFILE_OSECTIONS (objfile, sec)
+      if (!strcmp (bfd_section_name (sec->the_bfd_section), args))
+       {
+         if (!sec->ovly_mapped)
+           error (_("Section %s is not mapped"), args);
+         sec->ovly_mapped = 0;
+         return;
+       }
   error (_("No overlay section called %s"), args);
 }
 
   error (_("No overlay section called %s"), args);
 }
 
@@ -3429,7 +3309,7 @@ unmap_overlay_command (char *args, int from_tty)
    Possibly this should be done via a set/show command.  */
 
 static void
    Possibly this should be done via a set/show command.  */
 
 static void
-overlay_auto_command (char *args, int from_tty)
+overlay_auto_command (const char *args, int from_tty)
 {
   overlay_debugging = ovly_auto;
   enable_overlay_breakpoints ();
 {
   overlay_debugging = ovly_auto;
   enable_overlay_breakpoints ();
@@ -3442,7 +3322,7 @@ overlay_auto_command (char *args, int from_tty)
    Possibly this should be done via a set/show command.  */
 
 static void
    Possibly this should be done via a set/show command.  */
 
 static void
-overlay_manual_command (char *args, int from_tty)
+overlay_manual_command (const char *args, int from_tty)
 {
   overlay_debugging = ovly_on;
   disable_overlay_breakpoints ();
 {
   overlay_debugging = ovly_on;
   disable_overlay_breakpoints ();
@@ -3455,7 +3335,7 @@ overlay_manual_command (char *args, int from_tty)
    Possibly this should be done via a set/show command.  */
 
 static void
    Possibly this should be done via a set/show command.  */
 
 static void
-overlay_off_command (char *args, int from_tty)
+overlay_off_command (const char *args, int from_tty)
 {
   overlay_debugging = ovly_off;
   disable_overlay_breakpoints ();
 {
   overlay_debugging = ovly_off;
   disable_overlay_breakpoints ();
@@ -3464,7 +3344,7 @@ overlay_off_command (char *args, int from_tty)
 }
 
 static void
 }
 
 static void
-overlay_load_command (char *args, int from_tty)
+overlay_load_command (const char *args, int from_tty)
 {
   struct gdbarch *gdbarch = get_current_arch ();
 
 {
   struct gdbarch *gdbarch = get_current_arch ();
 
@@ -3474,20 +3354,9 @@ overlay_load_command (char *args, int from_tty)
     error (_("This target does not know how to read its overlay state."));
 }
 
     error (_("This target does not know how to read its overlay state."));
 }
 
-/* Function: overlay_command
-   A place-holder for a mis-typed command.  */
-
 /* Command list chain containing all defined "overlay" subcommands.  */
 static struct cmd_list_element *overlaylist;
 
 /* Command list chain containing all defined "overlay" subcommands.  */
 static struct cmd_list_element *overlaylist;
 
-static void
-overlay_command (char *args, int from_tty)
-{
-  printf_unfiltered
-    ("\"overlay\" must be followed by the name of an overlay command.\n");
-  help_list (overlaylist, "overlay ", all_commands, gdb_stdout);
-}
-
 /* Target Overlays for the "Simplest" overlay manager:
 
    This is GDB's default target overlay layer.  It works with the
 /* Target Overlays for the "Simplest" overlay manager:
 
    This is GDB's default target overlay layer.  It works with the
@@ -3504,12 +3373,12 @@ overlay_command (char *args, int from_tty)
    In this simple implementation, the target data structures are as follows:
    unsigned _novlys;            /# number of overlay sections #/
    unsigned _ovly_table[_novlys][4] = {
    In this simple implementation, the target data structures are as follows:
    unsigned _novlys;            /# number of overlay sections #/
    unsigned _ovly_table[_novlys][4] = {
-   {VMA, SIZE, LMA, MAPPED},    /# one entry per overlay section #/
+   {VMA, OSIZE, LMA, MAPPED},    /# one entry per overlay section #/
    {..., ...,  ..., ...},
    }
    unsigned _novly_regions;     /# number of overlay regions #/
    unsigned _ovly_region_table[_novly_regions][3] = {
    {..., ...,  ..., ...},
    }
    unsigned _novly_regions;     /# number of overlay regions #/
    unsigned _ovly_region_table[_novly_regions][3] = {
-   {VMA, SIZE, MAPPED_TO_LMA},  /# one entry per overlay region #/
+   {VMA, OSIZE, MAPPED_TO_LMA},  /# one entry per overlay region #/
    {..., ...,  ...},
    }
    These functions will attempt to update GDB's mappedness state in the
    {..., ...,  ...},
    }
    These functions will attempt to update GDB's mappedness state in the
@@ -3527,7 +3396,7 @@ static unsigned cache_novlys = 0;
 static CORE_ADDR cache_ovly_table_base = 0;
 enum ovly_index
   {
 static CORE_ADDR cache_ovly_table_base = 0;
 enum ovly_index
   {
-    VMA, SIZE, LMA, MAPPED
+    VMA, OSIZE, LMA, MAPPED
   };
 
 /* Throw away the cached copy of _ovly_table.  */
   };
 
 /* Throw away the cached copy of _ovly_table.  */
@@ -3535,8 +3404,7 @@ enum ovly_index
 static void
 simple_free_overlay_table (void)
 {
 static void
 simple_free_overlay_table (void)
 {
-  if (cache_ovly_table)
-    xfree (cache_ovly_table);
+  xfree (cache_ovly_table);
   cache_novlys = 0;
   cache_ovly_table = NULL;
   cache_ovly_table_base = 0;
   cache_novlys = 0;
   cache_ovly_table = NULL;
   cache_ovly_table_base = 0;
@@ -3550,7 +3418,7 @@ read_target_long_array (CORE_ADDR memaddr, unsigned int *myaddr,
                        int len, int size, enum bfd_endian byte_order)
 {
   /* FIXME (alloca): Not safe if array is very large.  */
                        int len, int size, enum bfd_endian byte_order)
 {
   /* FIXME (alloca): Not safe if array is very large.  */
-  gdb_byte *buf = alloca (len * size);
+  gdb_byte *buf = (gdb_byte *) alloca (len * size);
   int i;
 
   read_memory (memaddr, buf, len * size);
   int i;
 
   read_memory (memaddr, buf, len * size);
@@ -3589,14 +3457,14 @@ simple_read_overlay_table (void)
       return 0;
     }
 
       return 0;
     }
 
-  gdbarch = get_objfile_arch (ovly_table_msym.objfile);
+  gdbarch = ovly_table_msym.objfile->arch ();
   word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
   byte_order = gdbarch_byte_order (gdbarch);
 
   cache_novlys = read_memory_integer (BMSYMBOL_VALUE_ADDRESS (novlys_msym),
                                      4, byte_order);
   cache_ovly_table
   word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
   byte_order = gdbarch_byte_order (gdbarch);
 
   cache_novlys = read_memory_integer (BMSYMBOL_VALUE_ADDRESS (novlys_msym),
                                      4, byte_order);
   cache_ovly_table
-    = (void *) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
+    = (unsigned int (*)[4]) xmalloc (cache_novlys * sizeof (*cache_ovly_table));
   cache_ovly_table_base = BMSYMBOL_VALUE_ADDRESS (ovly_table_msym);
   read_target_long_array (cache_ovly_table_base,
                           (unsigned int *) cache_ovly_table,
   cache_ovly_table_base = BMSYMBOL_VALUE_ADDRESS (ovly_table_msym);
   read_target_long_array (cache_ovly_table_base,
                           (unsigned int *) cache_ovly_table,
@@ -3616,25 +3484,21 @@ simple_read_overlay_table (void)
 static int
 simple_overlay_update_1 (struct obj_section *osect)
 {
 static int
 simple_overlay_update_1 (struct obj_section *osect)
 {
-  int i, size;
-  bfd *obfd = osect->objfile->obfd;
+  int i;
   asection *bsect = osect->the_bfd_section;
   asection *bsect = osect->the_bfd_section;
-  struct gdbarch *gdbarch = get_objfile_arch (osect->objfile);
+  struct gdbarch *gdbarch = osect->objfile->arch ();
   int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
-  size = bfd_get_section_size (osect->the_bfd_section);
   for (i = 0; i < cache_novlys; i++)
   for (i = 0; i < cache_novlys; i++)
-    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 */ )
+    if (cache_ovly_table[i][VMA] == bfd_section_vma (bsect)
+       && cache_ovly_table[i][LMA] == bfd_section_lma (bsect))
       {
        read_target_long_array (cache_ovly_table_base + i * word_size,
                                (unsigned int *) cache_ovly_table[i],
                                4, word_size, byte_order);
       {
        read_target_long_array (cache_ovly_table_base + i * word_size,
                                (unsigned int *) cache_ovly_table[i],
                                4, word_size, byte_order);
-       if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
-           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
-           /* && cache_ovly_table[i][SIZE] == size */ )
+       if (cache_ovly_table[i][VMA] == bfd_section_vma (bsect)
+           && cache_ovly_table[i][LMA] == bfd_section_lma (bsect))
          {
            osect->ovly_mapped = cache_ovly_table[i][MAPPED];
            return 1;
          {
            osect->ovly_mapped = cache_ovly_table[i][MAPPED];
            return 1;
@@ -3656,8 +3520,6 @@ simple_overlay_update_1 (struct obj_section *osect)
 void
 simple_overlay_update (struct obj_section *osect)
 {
 void
 simple_overlay_update (struct obj_section *osect)
 {
-  struct objfile *objfile;
-
   /* Were we given an osect to look up?  NULL means do all of them.  */
   if (osect)
     /* Have we got a cached copy of the target's overlay table?  */
   /* Were we given an osect to look up?  NULL means do all of them.  */
   if (osect)
     /* Have we got a cached copy of the target's overlay table?  */
@@ -3689,23 +3551,21 @@ simple_overlay_update (struct obj_section *osect)
     return;
 
   /* Now may as well update all sections, even if only one was requested.  */
     return;
 
   /* Now may as well update all sections, even if only one was requested.  */
-  ALL_OBJSECTIONS (objfile, osect)
-    if (section_is_overlay (osect))
-    {
-      int i, size;
-      bfd *obfd = osect->objfile->obfd;
-      asection *bsect = osect->the_bfd_section;
-
-      size = bfd_get_section_size (bsect);
-      for (i = 0; i < cache_novlys; i++)
-       if (cache_ovly_table[i][VMA] == bfd_section_vma (obfd, bsect)
-           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect)
-           /* && cache_ovly_table[i][SIZE] == size */ )
-         { /* obj_section matches i'th entry in ovly_table.  */
-           osect->ovly_mapped = cache_ovly_table[i][MAPPED];
-           break;              /* finished with inner for loop: break out.  */
-         }
-    }
+  for (objfile *objfile : current_program_space->objfiles ())
+    ALL_OBJFILE_OSECTIONS (objfile, osect)
+      if (section_is_overlay (osect))
+       {
+         int i;
+         asection *bsect = osect->the_bfd_section;
+
+         for (i = 0; i < cache_novlys; i++)
+           if (cache_ovly_table[i][VMA] == bfd_section_vma (bsect)
+               && cache_ovly_table[i][LMA] == bfd_section_lma (bsect))
+             { /* obj_section matches i'th entry in ovly_table.  */
+               osect->ovly_mapped = cache_ovly_table[i][MAPPED];
+               break;          /* finished with inner for loop: break out.  */
+             }
+       }
 }
 
 /* Set the output sections and output offsets for section SECTP in
 }
 
 /* Set the output sections and output offsets for section SECTP in
@@ -3765,7 +3625,7 @@ symfile_relocate_debug_section (struct objfile *objfile,
   return (*objfile->sf->sym_relocate) (objfile, sectp, buf);
 }
 
   return (*objfile->sf->sym_relocate) (objfile, sectp, buf);
 }
 
-struct symfile_segment_data *
+symfile_segment_data_up
 get_symfile_segment_data (bfd *abfd)
 {
   const struct sym_fns *sf = find_sym_fns (abfd);
 get_symfile_segment_data (bfd *abfd)
 {
   const struct sym_fns *sf = find_sym_fns (abfd);
@@ -3776,15 +3636,6 @@ get_symfile_segment_data (bfd *abfd)
   return sf->sym_segments (abfd);
 }
 
   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,
 /* Given:
    - DATA, containing segment addresses from the object file ABFD, and
      the mapping from ABFD's sections onto the segments that own them,
@@ -3803,7 +3654,7 @@ free_symfile_segment_data (struct symfile_segment_data *data)
 int
 symfile_map_offsets_to_segments (bfd *abfd,
                                 const struct symfile_segment_data *data,
 int
 symfile_map_offsets_to_segments (bfd *abfd,
                                 const struct symfile_segment_data *data,
-                                struct section_offsets *offsets,
+                                section_offsets &offsets,
                                 int num_segment_bases,
                                 const CORE_ADDR *segment_bases)
 {
                                 int num_segment_bases,
                                 const CORE_ADDR *segment_bases)
 {
@@ -3817,13 +3668,13 @@ symfile_map_offsets_to_segments (bfd *abfd,
   /* If we do not have segment mappings for the object file, we
      can not relocate it by segments.  */
   gdb_assert (data != NULL);
   /* 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);
+  gdb_assert (data->segments.size () > 0);
 
   for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
     {
       int which = data->segment_info[i];
 
 
   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);
+      gdb_assert (0 <= which && which <= data->segments.size ());
 
       /* Don't bother computing offsets for sections that aren't
          loaded as part of any segment.  */
 
       /* Don't bother computing offsets for sections that aren't
          loaded as part of any segment.  */
@@ -3835,8 +3686,7 @@ symfile_map_offsets_to_segments (bfd *abfd,
       if (which > num_segment_bases)
         which = num_segment_bases;
 
       if (which > num_segment_bases)
         which = num_segment_bases;
 
-      offsets->offsets[i] = (segment_bases[which - 1]
-                             - data->segment_bases[which - 1]);
+      offsets[i] = segment_bases[which - 1] - data->segments[which - 1].base;
     }
 
   return 1;
     }
 
   return 1;
@@ -3848,17 +3698,14 @@ symfile_find_segment_sections (struct objfile *objfile)
   bfd *abfd = objfile->obfd;
   int i;
   asection *sect;
   bfd *abfd = objfile->obfd;
   int i;
   asection *sect;
-  struct symfile_segment_data *data;
 
 
-  data = get_symfile_segment_data (objfile->obfd);
+  symfile_segment_data_up data
+    = get_symfile_segment_data (objfile->obfd);
   if (data == NULL)
     return;
 
   if (data == NULL)
     return;
 
-  if (data->num_segments != 1 && data->num_segments != 2)
-    {
-      free_symfile_segment_data (data);
-      return;
-    }
+  if (data->segments.size () != 1 && data->segments.size () != 2)
+    return;
 
   for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
     {
 
   for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
     {
@@ -3881,8 +3728,6 @@ symfile_find_segment_sections (struct objfile *objfile)
            objfile->sect_index_bss = sect->index;
        }
     }
            objfile->sect_index_bss = sect->index;
        }
     }
-
-  free_symfile_segment_data (data);
 }
 
 /* Listen for free_objfile events.  */
 }
 
 /* Listen for free_objfile events.  */
@@ -3900,20 +3745,21 @@ symfile_free_objfile (struct objfile *objfile)
    See quick_symbol_functions.expand_symtabs_matching for details.  */
 
 void
    See quick_symbol_functions.expand_symtabs_matching for details.  */
 
 void
-expand_symtabs_matching (expand_symtabs_file_matcher_ftype *file_matcher,
-                        expand_symtabs_symbol_matcher_ftype *symbol_matcher,
-                        enum search_domain kind,
-                        void *data)
+expand_symtabs_matching
+  (gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   const lookup_name_info &lookup_name,
+   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   enum search_domain kind)
 {
 {
-  struct objfile *objfile;
-
-  ALL_OBJFILES (objfile)
-  {
-    if (objfile->sf)
-      objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
-                                               symbol_matcher, kind,
-                                               data);
-  }
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      if (objfile->sf)
+       objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
+                                                 &lookup_name,
+                                                 symbol_matcher,
+                                                 expansion_notify, kind);
+    }
 }
 
 /* Wrapper around the quick_symbol_functions map_symbol_filenames "method".
 }
 
 /* Wrapper around the quick_symbol_functions map_symbol_filenames "method".
@@ -3924,36 +3770,107 @@ void
 map_symbol_filenames (symbol_filename_ftype *fun, void *data,
                      int need_fullname)
 {
 map_symbol_filenames (symbol_filename_ftype *fun, void *data,
                      int need_fullname)
 {
-  struct objfile *objfile;
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      if (objfile->sf)
+       objfile->sf->qf->map_symbol_filenames (objfile, fun, data,
+                                              need_fullname);
+    }
+}
 
 
-  ALL_OBJFILES (objfile)
-  {
-    if (objfile->sf)
-      objfile->sf->qf->map_symbol_filenames (objfile, fun, data,
-                                            need_fullname);
-  }
+#if GDB_SELF_TEST
+
+namespace selftests {
+namespace filename_language {
+
+static void test_filename_language ()
+{
+  /* This test messes up the filename_language_table global.  */
+  scoped_restore restore_flt = make_scoped_restore (&filename_language_table);
+
+  /* Test deducing an unknown extension.  */
+  language lang = deduce_language_from_filename ("myfile.blah");
+  SELF_CHECK (lang == language_unknown);
+
+  /* Test deducing a known extension.  */
+  lang = deduce_language_from_filename ("myfile.c");
+  SELF_CHECK (lang == language_c);
+
+  /* Test adding a new extension using the internal API.  */
+  add_filename_language (".blah", language_pascal);
+  lang = deduce_language_from_filename ("myfile.blah");
+  SELF_CHECK (lang == language_pascal);
+}
+
+static void
+test_set_ext_lang_command ()
+{
+  /* This test messes up the filename_language_table global.  */
+  scoped_restore restore_flt = make_scoped_restore (&filename_language_table);
+
+  /* Confirm that the .hello extension is not known.  */
+  language lang = deduce_language_from_filename ("cake.hello");
+  SELF_CHECK (lang == language_unknown);
+
+  /* Test adding a new extension using the CLI command.  */
+  auto args_holder = make_unique_xstrdup (".hello rust");
+  ext_args = args_holder.get ();
+  set_ext_lang_command (NULL, 1, NULL);
+
+  lang = deduce_language_from_filename ("cake.hello");
+  SELF_CHECK (lang == language_rust);
+
+  /* Test overriding an existing extension using the CLI command.  */
+  int size_before = filename_language_table.size ();
+  args_holder.reset (xstrdup (".hello pascal"));
+  ext_args = args_holder.get ();
+  set_ext_lang_command (NULL, 1, NULL);
+  int size_after = filename_language_table.size ();
+
+  lang = deduce_language_from_filename ("cake.hello");
+  SELF_CHECK (lang == language_pascal);
+  SELF_CHECK (size_before == size_after);
 }
 
 }
 
+} /* namespace filename_language */
+} /* namespace selftests */
+
+#endif /* GDB_SELF_TEST */
+
+void _initialize_symfile ();
 void
 void
-_initialize_symfile (void)
+_initialize_symfile ()
 {
   struct cmd_list_element *c;
 
 {
   struct cmd_list_element *c;
 
-  observer_attach_free_objfile (symfile_free_objfile);
+  gdb::observers::free_objfile.attach (symfile_free_objfile);
+
+#define READNOW_READNEVER_HELP \
+  "The '-readnow' option will cause GDB to read the entire symbol file\n\
+immediately.  This makes the command slower, but may make future operations\n\
+faster.\n\
+The '-readnever' option will prevent GDB from reading the symbol file's\n\
+symbolic debug information."
 
   c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\
 Load symbol table from executable file FILE.\n\
 
   c = add_cmd ("symbol-file", class_files, symbol_file_command, _("\
 Load symbol table from executable file FILE.\n\
+Usage: symbol-file [-readnow | -readnever] [-o OFF] FILE\n\
+OFF is an optional offset which is added to each section address.\n\
 The `file' command can also load symbol tables, as well as setting the file\n\
 The `file' command can also load symbol tables, as well as setting the file\n\
-to execute."), &cmdlist);
+to execute.\n" READNOW_READNEVER_HELP), &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\
   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>\
- ...]\nADDR is the starting address of the file's text.\n\
-The optional arguments are section-name section-address pairs and\n\
+Usage: add-symbol-file FILE [-readnow | -readnever] [-o OFF] [ADDR] \
+[-s SECT-NAME SECT-ADDR]...\n\
+ADDR is the starting address of the file's text.\n\
+Each '-s' argument provides a section name and address, and\n\
 should be specified if the data and bss segments are not contiguous\n\
 should be specified if the data and bss segments are not contiguous\n\
-with the text.  SECT is a section name to be loaded at SECT_ADDR."),
+with the text.  SECT-NAME is a section name to be loaded at SECT-ADDR.\n\
+OFF is an optional offset which is added to the default load addresses\n\
+of all sections for which no other address was specified.\n"
+READNOW_READNEVER_HELP),
               &cmdlist);
   set_cmd_completer (c, filename_completer);
 
               &cmdlist);
   set_cmd_completer (c, filename_completer);
 
@@ -3967,17 +3884,20 @@ that lies within the boundaries of this symbol file in memory."),
               &cmdlist);
 
   c = add_cmd ("load", class_files, load_command, _("\
               &cmdlist);
 
   c = add_cmd ("load", class_files, load_command, _("\
-Dynamically load FILE into the running program, and record its symbols\n\
-for access from GDB.\n\
-A load OFFSET may also be given."), &cmdlist);
+Dynamically load FILE into the running program.\n\
+FILE symbols are recorded for access from GDB.\n\
+Usage: load [FILE] [OFFSET]\n\
+An optional load OFFSET may also be given as a literal address.\n\
+When OFFSET is provided, FILE must also be provided.  FILE can be provided\n\
+on its own."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   set_cmd_completer (c, filename_completer);
 
-  add_prefix_cmd ("overlay", class_support, overlay_command,
-                 _("Commands for debugging overlays."), &overlaylist,
-                 "overlay ", 0, &cmdlist);
+  add_basic_prefix_cmd ("overlay", class_support,
+                       _("Commands for debugging overlays."), &overlaylist,
+                       "overlay ", 0, &cmdlist);
 
 
-  add_com_alias ("ovly", "overlay", class_alias, 1);
-  add_com_alias ("ov", "overlay", class_alias, 1);
+  add_com_alias ("ovly", "overlay", class_support, 1);
+  add_com_alias ("ov", "overlay", class_support, 1);
 
   add_cmd ("map-overlay", class_support, map_overlay_command,
           _("Assert that an overlay section is mapped."), &overlaylist);
 
   add_cmd ("map-overlay", class_support, map_overlay_command,
           _("Assert that an overlay section is mapped."), &overlaylist);
@@ -3998,7 +3918,6 @@ A load OFFSET may also be given."), &cmdlist);
           _("Read the overlay mapping state from the target."), &overlaylist);
 
   /* Filename extension to source language lookup table: */
           _("Read the overlay mapping state from the target."), &overlaylist);
 
   /* Filename extension to source language lookup table: */
-  init_filename_language_table ();
   add_setshow_string_noescape_cmd ("extension-language", class_files,
                                   &ext_args, _("\
 Set mapping between filename extension and source language."), _("\
   add_setshow_string_noescape_cmd ("extension-language", class_files,
                                   &ext_args, _("\
 Set mapping between filename extension and source language."), _("\
@@ -4036,4 +3955,19 @@ full  == print messages for the executable,\n\
                        NULL,
                        NULL,
                        &setprintlist, &showprintlist);
                        NULL,
                        NULL,
                        &setprintlist, &showprintlist);
+
+  add_setshow_boolean_cmd ("separate-debug-file", no_class,
+                          &separate_debug_file_debug, _("\
+Set printing of separate debug info file search debug."), _("\
+Show printing of separate debug info file search debug."), _("\
+When on, GDB prints the searched locations while looking for separate debug \
+info files."), NULL, NULL, &setdebuglist, &showdebuglist);
+
+#if GDB_SELF_TEST
+  selftests::register_test
+    ("filename_language", selftests::filename_language::test_filename_language);
+  selftests::register_test
+    ("set_ext_lang_command",
+     selftests::filename_language::test_set_ext_lang_command);
+#endif
 }
 }
This page took 0.076449 seconds and 4 git commands to generate.