Remove make_cleanup_free_objfile
[deliverable/binutils-gdb.git] / gdb / symfile.c
index 229f9b430b90ce0827eab231d61dd09bdfb0b39e..9afd9943d9cb9ca9cdb7bc7cb33922b1bd2c8f86 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic symbol file reading for the GNU debugger, GDB.
 
-   Copyright (C) 1990-2015 Free Software Foundation, Inc.
+   Copyright (C) 1990-2017 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
 #include "stack.h"
 #include "gdb_bfd.h"
 #include "cli/cli-utils.h"
+#include "common/byte-vector.h"
+#include "selftest.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <ctype.h>
-#include <time.h>
-#include "gdb_sys_time.h"
+#include <chrono>
 
 #include "psymtab.h"
 
@@ -85,26 +86,13 @@ int readnow_symbol_files;   /* Read full symbols immediately.  */
 
 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);
 
 static const struct sym_fns *find_sym_fns (bfd *);
 
-static void decrement_reading_symtab (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,
@@ -114,32 +102,28 @@ static int simple_read_overlay_table (void);
 
 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);
 
-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.  */
 
-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;
-} 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".  */
 
@@ -197,22 +181,15 @@ print_symbol_loading_p (int from_tty, int exec, int full)
 
 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.  */
 
-struct cleanup *
+scoped_restore_tmpl<int>
 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.
@@ -424,7 +401,7 @@ struct place_section_arg
 static void
 place_section (bfd *abfd, asection *sect, void *obj)
 {
-  struct place_section_arg *arg = obj;
+  struct place_section_arg *arg = (struct place_section_arg *) obj;
   CORE_ADDR *offsets = arg->offsets->offsets, start_addr;
   int done;
   ULONGEST align = ((ULONGEST) 1) << bfd_get_section_alignment (abfd, sect);
@@ -869,10 +846,10 @@ default_symfile_segments (bfd *abfd)
    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->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.  */
@@ -880,8 +857,7 @@ read_symbols (struct objfile *objfile, int add_flags)
       && 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)
        {
@@ -889,11 +865,9 @@ 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.  */
-         symbol_file_add_separate (abfd, objfile->original_name, add_flags,
-                                   objfile);
+         symbol_file_add_separate (abfd.get (), objfile->original_name,
+                                   add_flags, objfile);
        }
-
-      do_cleanups (cleanup);
     }
   if ((add_flags & SYMFILE_NO_READ) == 0)
     require_partial_symbols (objfile, 0);
@@ -998,7 +972,7 @@ init_entry_point_info (struct objfile *objfile)
 static void
 syms_from_objfile_1 (struct objfile *objfile,
                     struct section_addr_info *addrs,
-                    int add_flags)
+                    symfile_add_flags add_flags)
 {
   struct section_addr_info *local_addr = NULL;
   struct cleanup *old_chain;
@@ -1023,7 +997,8 @@ syms_from_objfile_1 (struct objfile *objfile,
 
   /* 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);
+  old_chain = make_cleanup (null_cleanup, NULL);
+  std::unique_ptr<struct objfile> objfile_holder (objfile);
 
   /* If ADDRS is NULL, put together a dummy address list.
      We now establish the convention that an addr of zero means
@@ -1045,7 +1020,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 
       if (symfile_objfile != NULL)
        {
-         free_objfile (symfile_objfile);
+         delete symfile_objfile;
          gdb_assert (symfile_objfile == NULL);
        }
 
@@ -1079,6 +1054,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 
   /* Discard cleanups as symbol reading was successful.  */
 
+  objfile_holder.release ();
   discard_cleanups (old_chain);
   xfree (local_addr);
 }
@@ -1089,7 +1065,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 static void
 syms_from_objfile (struct objfile *objfile,
                   struct section_addr_info *addrs,
-                  int add_flags)
+                  symfile_add_flags add_flags)
 {
   syms_from_objfile_1 (objfile, addrs, add_flags);
   init_entry_point_info (objfile);
@@ -1100,7 +1076,7 @@ syms_from_objfile (struct objfile *objfile,
    objfile.  ADD_FLAGS is a bitmask of enum symfile_add_flags.  */
 
 static void
-finish_new_objfile (struct objfile *objfile, int add_flags)
+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
@@ -1127,7 +1103,7 @@ finish_new_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.
 
-   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
    extra, such as dynamically loaded code, and what to do with breakpoins.
@@ -1142,9 +1118,10 @@ finish_new_objfile (struct objfile *objfile, int add_flags)
    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,
+symbol_file_add_with_addrs (bfd *abfd, const char *name,
+                           symfile_add_flags add_flags,
                            struct section_addr_info *addrs,
-                           int flags, struct objfile *parent)
+                           objfile_flags flags, struct objfile *parent)
 {
   struct objfile *objfile;
   const int from_tty = add_flags & SYMFILE_VERBOSE;
@@ -1168,8 +1145,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."));
 
-  objfile = allocate_objfile (abfd, name,
-                             flags | (mainline ? OBJF_MAINLINE : 0));
+  if (mainline)
+    flags |= OBJF_MAINLINE;
+  objfile = new struct objfile (abfd, name, flags);
 
   if (parent)
     add_separate_debug_objfile (objfile, parent);
@@ -1243,13 +1221,13 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name, int add_flags,
 }
 
 /* Add BFD as a separate debug file for OBJFILE.  For NAME description
-   see allocate_objfile's definition.  */
+   see the objfile constructor.  */
 
 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 *new_objfile;
   struct section_addr_info *sap;
   struct cleanup *my_cleanup;
 
@@ -1259,7 +1237,7 @@ symbol_file_add_separate (bfd *bfd, const char *name, int symfile_flags,
   sap = build_section_addr_info_from_objfile (objfile);
   my_cleanup = make_cleanup_free_section_addr_info (sap);
 
-  new_objfile = symbol_file_add_with_addrs
+  symbol_file_add_with_addrs
     (bfd, name, symfile_flags, sap,
      objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
                       | OBJF_USERLOADED),
@@ -1273,9 +1251,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 *
-symbol_file_add_from_bfd (bfd *abfd, const char *name, int add_flags,
+symbol_file_add_from_bfd (bfd *abfd, const char *name,
+                         symfile_add_flags add_flags,
                           struct section_addr_info *addrs,
-                          int flags, struct objfile *parent)
+                          objfile_flags flags, struct objfile *parent)
 {
   return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
                                     parent);
@@ -1285,16 +1264,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 *
-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,
+                struct 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
@@ -1306,16 +1282,16 @@ symbol_file_add (const char *name, int add_flags,
    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);
 }
 
 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)
 {
-  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);
 
@@ -1323,7 +1299,7 @@ symbol_file_add_main_1 (const char *args, int from_tty, int flags)
      what is frameless.  */
   reinit_frame_cache ();
 
-  if ((flags & SYMFILE_NO_READ) == 0)
+  if ((add_flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
 }
 
@@ -1349,13 +1325,16 @@ symbol_file_clear (int from_tty)
     printf_unfiltered (_("No symbol file now.\n"));
 }
 
+/* See symfile.h.  */
+
+int separate_debug_file_debug = 0;
+
 static int
 separate_debug_file_exists (const char *name, unsigned long crc,
                            struct objfile *parent_objfile)
 {
   unsigned long file_crc;
   int file_crc_p;
-  bfd *abfd;
   struct stat parent_stat, abfd_stat;
   int verified_as_different;
 
@@ -1368,9 +1347,12 @@ separate_debug_file_exists (const char *name, unsigned long crc,
   if (filename_cmp (name, objfile_name (parent_objfile)) == 0)
     return 0;
 
-  abfd = gdb_bfd_open (name, gnutarget, -1);
+  if (separate_debug_file_debug)
+    printf_unfiltered (_("  Trying %s\n"), name);
+
+  gdb_bfd_ref_ptr abfd (gdb_bfd_open (name, gnutarget, -1));
 
-  if (!abfd)
+  if (abfd == NULL)
     return 0;
 
   /* Verify symlinks were not the cause of filename_cmp name difference above.
@@ -1384,24 +1366,19 @@ separate_debug_file_exists (const char *name, unsigned long crc,
      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
+  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)
-       {
-         gdb_bfd_unref (abfd);
-         return 0;
-       }
+       return 0;
       verified_as_different = 1;
     }
   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)
     return 0;
@@ -1466,7 +1443,11 @@ find_separate_debug_file (const char *dir,
   struct cleanup *back_to;
   int ix;
 
-  /* Set I to max (strlen (canon_dir), strlen (dir)).  */
+  if (separate_debug_file_debug)
+    printf_unfiltered (_("\nLooking for separate debug info (debug link) for "
+                        "%s\n"), objfile_name (objfile));
+
+  /* Set I to std::max (strlen (canon_dir), strlen (dir)).  */
   i = strlen (dir);
   if (canon_dir != NULL && strlen (canon_dir) > i)
     i = strlen (canon_dir);
@@ -1566,13 +1547,11 @@ terminate_after_last_dir_separator (char *path)
 char *
 find_separate_debug_file_by_debuglink (struct objfile *objfile)
 {
-  char *debuglink;
-  char *dir, *canon_dir;
   char *debugfile;
   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)
     {
@@ -1581,15 +1560,12 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
       return NULL;
     }
 
-  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);
+  debugfile = find_separate_debug_file (dir.c_str (), canon_dir.get (),
+                                       debuglink.get (), crc32, objfile);
 
   if (debugfile == NULL)
     {
@@ -1601,19 +1577,17 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
       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)
            {
-             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.  */
-                 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);
                }
@@ -1621,7 +1595,6 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
        }
     }
 
-  do_cleanups (cleanups);
   return debugfile;
 }
 
@@ -1640,7 +1613,7 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
    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 ();
 
@@ -1650,31 +1623,29 @@ symbol_file_command (char *args, int from_tty)
     }
   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;
 
-      cleanups = make_cleanup_freeargv (argv);
-      while (*argv != NULL)
+      if (from_tty)
+       add_flags |= SYMFILE_VERBOSE;
+
+      gdb_argv built_argv (args);
+      for (char *arg : built_argv)
        {
-         if (strcmp (*argv, "-readnow") == 0)
+         if (strcmp (arg, "-readnow") == 0)
            flags |= OBJF_READNOW;
-         else if (**argv == '-')
-           error (_("unknown option `%s'"), *argv);
+         else if (*arg == '-')
+           error (_("unknown option `%s'"), arg);
          else
            {
-             symbol_file_add_main_1 (*argv, from_tty, flags);
-             name = *argv;
+             symbol_file_add_main_1 (arg, add_flags, flags);
+             name = arg;
            }
-
-         argv++;
        }
 
       if (name == NULL)
        error (_("no symbol file name was specified"));
-
-      do_cleanups (cleanups);
     }
 }
 
@@ -1718,59 +1689,51 @@ set_initial_language (void)
    includes a newly malloc'd` copy of NAME (tilde-expanded and made
    absolute).  In case of trouble, error() is called.  */
 
-bfd *
+gdb_bfd_ref_ptr
 symfile_bfd_open (const char *name)
 {
-  bfd *sym_bfd;
   int desc = -1;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
   if (!is_target_filename (name))
     {
-      char *expanded_name, *absolute_name;
+      char *absolute_name;
 
-      expanded_name = tilde_expand (name); /* Returns 1st new malloc'd copy.  */
+      gdb::unique_xmalloc_ptr<char> expanded_name (tilde_expand (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, O_RDONLY | O_BINARY, &absolute_name);
+                   expanded_name.get (), O_RDONLY | O_BINARY, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
       if (desc < 0)
        {
-         char *exename = alloca (strlen (expanded_name) + 5);
+         char *exename = (char *) alloca (strlen (expanded_name.get ()) + 5);
 
-         strcat (strcpy (exename, expanded_name), ".exe");
+         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
       if (desc < 0)
-       {
-         make_cleanup (xfree, expanded_name);
-         perror_with_name (expanded_name);
-       }
+       perror_with_name (expanded_name.get ());
 
-      xfree (expanded_name);
       make_cleanup (xfree, absolute_name);
       name = absolute_name;
     }
 
-  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 ()));
 
-  if (!gdb_bfd_has_target_filename (sym_bfd))
-    bfd_set_cacheable (sym_bfd, 1);
+  if (!gdb_bfd_has_target_filename (sym_bfd.get ()))
+    bfd_set_cacheable (sym_bfd.get (), 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 (!bfd_check_format (sym_bfd.get (), bfd_object))
+    error (_("`%s': can't read symbols: %s."), name,
+          bfd_errmsg (bfd_get_error ()));
 
   do_cleanups (back_to);
 
@@ -1781,7 +1744,7 @@ symfile_bfd_open (const char *name)
    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);
 
@@ -1800,9 +1763,7 @@ get_section_index (struct objfile *objfile, char *section_name)
 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
@@ -1813,18 +1774,16 @@ add_symtab_fns (enum bfd_flavour flavour, const struct sym_fns *sf)
 static const struct sym_fns *
 find_sym_fns (bfd *abfd)
 {
-  registered_sym_fns *rsf;
   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.  */
 
-  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));
@@ -1907,7 +1866,7 @@ static int validate_download = 0;
 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);
 }
@@ -1944,7 +1903,8 @@ struct load_progress_section_data {
 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)
@@ -1958,9 +1918,10 @@ load_progress (ULONGEST bytes, void *untyped_arg)
     {
       /* 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;
     }
 
@@ -1973,16 +1934,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.  */
-      gdb_byte *check = (gdb_byte *) 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));
-      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));
-      do_cleanups (verify_cleanups);
     }
   totals->data_count += bytes;
   args->lma += bytes;
@@ -2009,7 +1968,7 @@ 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_section_data *args = (struct load_section_data *) data;
   struct load_progress_section_data *section_data;
   bfd_size_type size = bfd_get_section_size (asec);
   gdb_byte *buffer;
@@ -2048,7 +2007,7 @@ load_section_callback (bfd *abfd, asection *asec, void *data)
 static void
 clear_memory_write_data (void *arg)
 {
-  VEC(memory_write_request_s) **vec_p = arg;
+  VEC(memory_write_request_s) **vec_p = (VEC(memory_write_request_s) **) arg;
   VEC(memory_write_request_s) *vec = *vec_p;
   int i;
   struct memory_write_request *mr;
@@ -2061,34 +2020,33 @@ clear_memory_write_data (void *arg)
   VEC_free (memory_write_request_s, vec);
 }
 
+static void print_transfer_performance (struct ui_file *stream,
+                                       unsigned long data_count,
+                                       unsigned long write_count,
+                                       std::chrono::steady_clock::duration d);
+
 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 cleanup *old_cleanups;
   struct load_section_data cbdata;
   struct load_progress_data total_progress;
   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);
+  old_cleanups = make_cleanup (clear_memory_write_data, &cbdata.requests);
 
   if (args == NULL)
     error_no_arg (_("file to load"));
 
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  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)
     {
@@ -2106,43 +2064,38 @@ generic_load (const char *args, int from_tty)
     }
 
   /* 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, -1));
   if (loadfile_bfd == NULL)
-    {
-      perror_with_name (filename);
-      return;
-    }
+    perror_with_name (filename.get ());
 
-  make_cleanup_bfd_unref (loadfile_bfd);
-
-  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_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);
 
-  bfd_map_over_sections (loadfile_bfd, load_section_callback, &cbdata);
+  bfd_map_over_sections (loadfile_bfd.get (), load_section_callback, &cbdata);
+
+  using namespace std::chrono;
 
-  gettimeofday (&start_time, NULL);
+  steady_clock::time_point start_time = steady_clock::now ();
 
   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);
+  entry = bfd_get_start_address (loadfile_bfd.get ());
   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_fmt ("address", "%s", paddress (target_gdbarch (), entry));
+  uiout->text (", load size ");
+  uiout->field_fmt ("load-size", "%lu", 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
@@ -2155,69 +2108,63 @@ generic_load (const char *args, int from_tty)
 
   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,
-                             &start_time, &end_time);
+                             end_time - start_time);
 
   do_cleanups (old_cleanups);
 }
 
-/* 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,
-                           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;
 
-  /* 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_fmt ("transfer-rate", "%lu", rate * 8);
+         uiout->text (" bits/sec");
        }
       else if (rate < 1024)
        {
-         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate);
-         ui_out_text (uiout, " bytes/sec");
+         uiout->field_fmt ("transfer-rate", "%lu", rate);
+         uiout->text (" bytes/sec");
        }
       else
        {
-         ui_out_field_fmt (uiout, "transfer-rate", "%lu", rate / 1024);
-         ui_out_text (uiout, " KB/sec");
+         uiout->field_fmt ("transfer-rate", "%lu", rate / 1024);
+         uiout->text (" KB/sec");
        }
     }
   else
     {
-      ui_out_field_fmt (uiout, "transferred-bits", "%lu", (data_count * 8));
-      ui_out_text (uiout, " bits in <1 sec");
+      uiout->field_fmt ("transferred-bits", "%lu", (data_count * 8));
+      uiout->text (" bits in <1 sec");
     }
   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_fmt ("write-rate", "%lu", data_count / write_count);
+      uiout->text (" bytes/write");
     }
-  ui_out_text (uiout, ".\n");
+  uiout->text (".\n");
 }
 
 /* This function allows the addition of incrementally linked object files.
@@ -2230,42 +2177,38 @@ print_transfer_performance (struct ui_file *stream,
    value to use.  We are now discontinuing this type of ad hoc syntax.  */
 
 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 ();
-  char *filename = NULL;
-  int flags = OBJF_USERLOADED | OBJF_SHARED;
+  gdb::unique_xmalloc_ptr<char> filename;
   char *arg;
-  int section_index = 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;
+  objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED;
+  symfile_add_flags add_flags = 0;
+
+  if (from_tty)
+    add_flags |= SYMFILE_VERBOSE;
 
   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;
+  std::vector<sect_opt> sect_opts;
   struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
 
-  num_sect_opts = 16;
-  sect_opts = XNEWVEC (struct sect_opt, num_sect_opts);
-
   dont_repeat ();
 
   if (args == NULL)
     error (_("add-symbol-file takes a file name and an address"));
 
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  gdb_argv argv (args);
 
   for (arg = argv[0], argcnt = 0; arg != NULL; arg = argv[++argcnt])
     {
@@ -2273,23 +2216,14 @@ add_symbol_file_command (char *args, int from_tty)
       if (argcnt == 0)
        {
          /* The first argument is the file name.  */
-         filename = tilde_expand (arg);
-         make_cleanup (xfree, filename);
+         filename.reset (tilde_expand (arg));
        }
       else if (argcnt == 1)
        {
          /* 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)
-           {
-             num_sect_opts *= 2;
-             sect_opts = ((struct sect_opt *)
-                          xrealloc (sect_opts,
-                                    num_sect_opts
-                                    * sizeof (struct sect_opt)));
-           }
+         sect_opt sect = { ".text", arg };
+         sect_opts.push_back (sect);
        }
       else
        {
@@ -2297,21 +2231,14 @@ add_symbol_file_command (char *args, int from_tty)
             to an option.  */
          if (expecting_sec_name)
            {
-             sect_opts[section_index].name = arg;
+             sect_opt sect = { arg, NULL };
+             sect_opts.push_back (sect);
              expecting_sec_name = 0;
            }
          else if (expecting_sec_addr)
            {
-             sect_opts[section_index].value = arg;
+             sect_opts.back ().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;
@@ -2330,8 +2257,9 @@ add_symbol_file_command (char *args, int from_tty)
      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 (sect_opts.empty ())
+    error (_("The address where %s has been loaded is missing"),
+          filename.get ());
 
   /* Print the prompt for the query below.  And save the arguments into
      a sect_addr_info structure to be passed around to other
@@ -2339,20 +2267,21 @@ add_symbol_file_command (char *args, int from_tty)
      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);
+  printf_unfiltered (_("add symbol table from file \"%s\" at\n"),
+                    filename.get ());
+  section_addrs = alloc_section_addr_info (sect_opts.size ());
   make_cleanup (xfree, section_addrs);
-  for (i = 0; i < section_index; i++)
+  for (sect_opt &sect : sect_opts)
     {
       CORE_ADDR addr;
-      char *val = sect_opts[i].value;
-      char *sec = sect_opts[i].name;
+      const char *val = sect.value;
+      const char *sec = sect.name;
 
       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].name = (char *) sec;
       section_addrs->other[sec_num].addr = addr;
       printf_unfiltered ("\t%s_addr = %s\n", sec,
                         paddress (gdbarch, addr));
@@ -2369,8 +2298,7 @@ add_symbol_file_command (char *args, int from_tty)
   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);
 
   add_target_sections_of_objfile (objf);
 
@@ -2384,22 +2312,17 @@ add_symbol_file_command (char *args, int from_tty)
 /* 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 cleanup *my_cleanups;
   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"));
 
-  my_cleanups = make_cleanup (null_cleanup, NULL);
-
-  argv = gdb_buildargv (args);
+  gdb_argv argv (args);
 
   if (strcmp (argv[0], "-a") == 0)
     {
@@ -2425,20 +2348,18 @@ remove_symbol_file_command (char *args, int from_tty)
   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]);
 
-      filename = tilde_expand (argv[0]);
-      make_cleanup (xfree, filename);
+      gdb::unique_xmalloc_ptr<char> filename (tilde_expand (argv[0]));
 
       ALL_OBJFILES (objf)
        {
          if ((objf->flags & OBJF_USERLOADED) != 0
              && (objf->flags & OBJF_SHARED) != 0
              && objf->pspace == pspace
-             && filename_cmp (filename, objfile_name (objf)) == 0)
+             && filename_cmp (filename.get (), objfile_name (objf)) == 0)
            break;
        }
     }
@@ -2451,16 +2372,10 @@ remove_symbol_file_command (char *args, int from_tty)
                 objfile_name (objf)))
     error (_("Not confirmed."));
 
-  free_objfile (objf);
+  delete objf;
   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
@@ -2470,10 +2385,7 @@ reread_symbols (void)
   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);
+  std::vector<struct objfile *> new_objfiles;
 
   /* With the addition of shared libraries, this should be modified,
      the load time should be saved in the partial symbol tables, since
@@ -2526,9 +2438,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).  */
-         old_cleanups = make_cleanup_free_objfile (objfile);
+         std::unique_ptr<struct objfile> objfile_holder (objfile);
+
          /* We need to do this whenever any symbols go away.  */
-         make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
+         old_cleanups = make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
 
          if (exec_bfd != NULL
              && filename_cmp (bfd_get_filename (objfile->obfd),
@@ -2564,22 +2477,16 @@ reread_symbols (void)
 
          /* Clean up any state BFD has sitting around.  */
          {
-           struct bfd *obfd = objfile->obfd;
+           gdb_bfd_ref_ptr obfd (objfile->obfd);
            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.  */
-           objfile->obfd = gdb_bfd_open (obfd_filename, gnutarget, -1);
+           gdb_bfd_ref_ptr temp (gdb_bfd_open (obfd_filename, gnutarget, -1));
+           objfile->obfd = temp.release ();
            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);
@@ -2600,18 +2507,15 @@ reread_symbols (void)
 
          /* 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));
+         objfile->global_psymbols.clear ();
+         objfile->static_psymbols.clear ();
 
          /* Free the obstacks for non-reusable objfiles.  */
          psymbol_bcache_free (objfile->psymbol_cache);
          objfile->psymbol_cache = psymbol_bcache_init ();
+
+         /* 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;
          objfile->compunit_symtabs = NULL;
@@ -2664,6 +2568,23 @@ reread_symbols (void)
          clear_complaints (&symfile_complaints, 1, 1);
 
          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 ();
+
          read_symbols (objfile, 0);
 
          if (!objfile_has_symbols (objfile))
@@ -2682,6 +2603,7 @@ reread_symbols (void)
          reinit_frame_cache ();
 
          /* Discard cleanups as symbol reading was successful.  */
+         objfile_holder.release ();
          discard_cleanups (old_cleanups);
 
          /* If the mtime has changed between the time we set new_modtime
@@ -2690,58 +2612,45 @@ reread_symbols (void)
          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
         observer_notify_new_objfile (NULL) has been called by
         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)
+       observer_notify_new_objfile (iter);
 
       /* At least one objfile has changed, so we can consider that
          the executable we're debugging has changed too.  */
       observer_notify_executable_changed ();
     }
-
-  do_cleanups (all_cleanups);
 }
 \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;
-}
-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 = XRESIZEVEC (filename_language,
-                                           filename_language_table,
-                                           fl_table_size);
-    }
+/* 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;
@@ -2758,7 +2667,6 @@ show_ext_args (struct ui_file *file, int from_tty,
 static void
 set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
 {
-  int i;
   char *cp = ext_args;
   enum language lang;
 
@@ -2789,12 +2697,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);
 
+  auto it = filename_language_table.begin ();
   /* 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);
@@ -2807,86 +2718,32 @@ 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));           */
 
-      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
 info_ext_lang_command (char *args, int from_tty)
 {
-  int i;
-
   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 = XNEWVEC (filename_language, fl_table_size);
-
-      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)
 {
-  int i;
-  char *cp;
+  const char *cp;
 
   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;
 }
@@ -2901,7 +2758,8 @@ allocate_symtab (struct compunit_symtab *cust, const char *filename)
   struct symtab *symtab
     = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symtab);
 
-  symtab->filename = bcache (filename, strlen (filename) + 1,
+  symtab->filename
+    = (const char *) bcache (filename, strlen (filename) + 1,
                             objfile->per_bfd->filename_cache);
   symtab->fullname = NULL;
   symtab->language = deduce_language_from_filename (filename);
@@ -2990,11 +2848,11 @@ add_compunit_symtab_to_objfile (struct compunit_symtab *cu)
 }
 \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
-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.  */
@@ -3291,19 +3149,21 @@ find_pc_overlay (CORE_ADDR pc)
   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))
+    {
+      ALL_OBJSECTIONS (objfile, osect)
+       if (section_is_overlay (osect))
          {
-           if (section_is_mapped (osect))
-             return osect;
-           else
+           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;
          }
-       else if (pc_in_unmapped_range (pc, osect))
-         best_match = osect;
-      }
+    }
   return best_match;
 }
 
@@ -3318,9 +3178,11 @@ find_pc_mapped_section (CORE_ADDR pc)
   struct obj_section *osect;
 
   if (overlay_debugging)
-    ALL_OBJSECTIONS (objfile, osect)
-      if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
-       return osect;
+    {
+      ALL_OBJSECTIONS (objfile, osect)
+       if (pc_in_mapped_range (pc, osect) && section_is_mapped (osect))
+         return osect;
+    }
 
   return NULL;
 }
@@ -3329,38 +3191,40 @@ find_pc_mapped_section (CORE_ADDR pc)
    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;
   struct objfile *objfile;
   struct obj_section *osect;
 
   if (overlay_debugging)
-    ALL_OBJSECTIONS (objfile, osect)
+    {
+      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++;
-      }
+       {
+         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++;
+       }
+    }
   if (nmapped == 0)
     printf_filtered (_("No sections are mapped.\n"));
 }
@@ -3369,7 +3233,7 @@ list_overlays_command (char *args, int from_tty)
    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;
@@ -3414,7 +3278,7 @@ map_overlay_command (char *args, int from_tty)
    (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 = NULL;
@@ -3444,7 +3308,7 @@ unmap_overlay_command (char *args, int from_tty)
    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 ();
@@ -3457,7 +3321,7 @@ overlay_auto_command (char *args, int from_tty)
    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 ();
@@ -3470,7 +3334,7 @@ overlay_manual_command (char *args, int from_tty)
    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 ();
@@ -3479,7 +3343,7 @@ overlay_off_command (char *args, int from_tty)
 }
 
 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 ();
 
@@ -3496,7 +3360,7 @@ overlay_load_command (char *args, int from_tty)
 static struct cmd_list_element *overlaylist;
 
 static void
-overlay_command (char *args, int from_tty)
+overlay_command (const char *args, int from_tty)
 {
   printf_unfiltered
     ("\"overlay\" must be followed by the name of an overlay command.\n");
@@ -3631,25 +3495,22 @@ simple_read_overlay_table (void)
 static int
 simple_overlay_update_1 (struct obj_section *osect)
 {
-  int i, size;
+  int i;
   bfd *obfd = osect->objfile->obfd;
   asection *bsect = osect->the_bfd_section;
   struct gdbarch *gdbarch = get_objfile_arch (osect->objfile);
   int word_size = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
-  size = bfd_get_section_size (osect->the_bfd_section);
   for (i = 0; i < cache_novlys; i++)
     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][OSIZE] == size */ )
+       && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect))
       {
        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][OSIZE] == size */ )
+           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, bsect))
          {
            osect->ovly_mapped = cache_ovly_table[i][MAPPED];
            return 1;
@@ -3707,15 +3568,13 @@ simple_overlay_update (struct obj_section *osect)
   ALL_OBJSECTIONS (objfile, osect)
     if (section_is_overlay (osect))
     {
-      int i, size;
+      int i;
       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][OSIZE] == size */ )
+           && cache_ovly_table[i][LMA] == bfd_section_lma (obfd, 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.  */
@@ -3915,11 +3774,11 @@ symfile_free_objfile (struct objfile *objfile)
    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,
-                        expand_symtabs_exp_notify_ftype *expansion_notify,
-                        enum search_domain kind,
-                        void *data)
+expand_symtabs_matching
+  (gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   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;
 
@@ -3928,8 +3787,7 @@ expand_symtabs_matching (expand_symtabs_file_matcher_ftype *file_matcher,
     if (objfile->sf)
       objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher,
                                                symbol_matcher,
-                                               expansion_notify, kind,
-                                               data);
+                                               expansion_notify, kind);
   }
 }
 
@@ -3951,6 +3809,65 @@ map_symbol_filenames (symbol_filename_ftype *fun, void *data,
   }
 }
 
+#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.  */
+  gdb::unique_xmalloc_ptr<char> args_holder (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)
 {
@@ -3986,7 +3903,10 @@ that lies within the boundaries of this symbol file in memory."),
   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);
+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.\n\
+Usage: load [FILE] [OFFSET]"), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
   add_prefix_cmd ("overlay", class_support, overlay_command,
@@ -4015,7 +3935,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: */
-  init_filename_language_table ();
   add_setshow_string_noescape_cmd ("extension-language", class_files,
                                   &ext_args, _("\
 Set mapping between filename extension and source language."), _("\
@@ -4053,4 +3972,19 @@ full  == print messages for the executable,\n\
                        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.049635 seconds and 4 git commands to generate.