Use unique_xmalloc_ptr in find_separate_debug_file_by_debuglink
[external/binutils.git] / gdb / symfile.c
index a741654..dae750e 100644 (file)
@@ -57,6 +57,7 @@
 #include "gdb_bfd.h"
 #include "cli/cli-utils.h"
 #include "common/byte-vector.h"
+#include "selftest.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -92,8 +93,6 @@ static const struct sym_fns *find_sym_fns (bfd *);
 
 static void overlay_invalidate_all (void);
 
-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,
@@ -111,18 +110,20 @@ static void symfile_find_segment_sections (struct objfile *objfile);
    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".  */
 
@@ -1018,7 +1019,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 
       if (symfile_objfile != NULL)
        {
-         free_objfile (symfile_objfile);
+         delete symfile_objfile;
          gdb_assert (symfile_objfile == NULL);
        }
 
@@ -1100,7 +1101,7 @@ finish_new_objfile (struct objfile *objfile, symfile_add_flags 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.
@@ -1144,7 +1145,7 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name,
 
   if (mainline)
     flags |= OBJF_MAINLINE;
-  objfile = allocate_objfile (abfd, name, flags);
+  objfile = new struct objfile (abfd, name, flags);
 
   if (parent)
     add_separate_debug_objfile (objfile, parent);
@@ -1218,7 +1219,7 @@ symbol_file_add_with_addrs (bfd *abfd, const char *name,
 }
 
 /* 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,
@@ -1544,13 +1545,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)
     {
@@ -1559,15 +1558,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)
     {
@@ -1579,19 +1575,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);
                }
@@ -1599,7 +1593,6 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
        }
     }
 
-  do_cleanups (cleanups);
   return debugfile;
 }
 
@@ -1768,9 +1761,7 @@ get_section_index (struct objfile *objfile, const 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
@@ -1781,18 +1772,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));
@@ -2381,7 +2370,7 @@ remove_symbol_file_command (const char *args, int from_tty)
                 objfile_name (objf)))
     error (_("Not confirmed."));
 
-  free_objfile (objf);
+  delete objf;
   clear_symtab_users (0);
 }
 
@@ -2515,14 +2504,8 @@ 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);
@@ -2646,27 +2629,24 @@ reread_symbols (void)
 }
 \f
 
-typedef struct
+struct filename_language
 {
-  char *ext;
-  enum language lang;
-} filename_language;
+  filename_language (const std::string &ext_, enum language lang_)
+  : ext (ext_), lang (lang_)
+  {}
 
-DEF_VEC_O (filename_language);
+  std::string ext;
+  enum language lang;
+};
 
-static VEC (filename_language) *filename_language_table;
+static std::vector<filename_language> filename_language_table;
 
 /* See symfile.h.  */
 
 void
 add_filename_language (const char *ext, enum language lang)
 {
-  filename_language entry;
-
-  entry.ext = xstrdup (ext);
-  entry.lang = lang;
-
-  VEC_safe_push (filename_language, filename_language_table, &entry);
+  filename_language_table.emplace_back (ext, lang);
 }
 
 static char *ext_args;
@@ -2683,10 +2663,8 @@ 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;
-  filename_language *entry;
 
   /* First arg is filename extension, starting with '.'  */
   if (*cp != '.')
@@ -2715,16 +2693,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;
-       VEC_iterate (filename_language, filename_language_table, i, entry);
-       ++i)
+  for (; it != filename_language_table.end (); it++)
     {
-      if (0 == strcmp (ext_args, entry->ext))
+      if (it->ext == ext_args)
        break;
     }
 
-  if (entry == NULL)
+  if (it == filename_language_table.end ())
     {
       /* New file extension.  */
       add_filename_language (ext_args, lang);
@@ -2737,42 +2714,31 @@ 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 (entry->ext);
-      entry->ext = xstrdup (ext_args);
-      entry->lang = lang;
+      it->lang = lang;
     }
 }
 
 static void
 info_ext_lang_command (char *args, int from_tty)
 {
-  int i;
-  filename_language *entry;
-
   printf_filtered (_("Filename extensions and the languages they represent:"));
   printf_filtered ("\n\n");
-  for (i = 0;
-       VEC_iterate (filename_language, filename_language_table, i, entry);
-       ++i)
-    printf_filtered ("\t%s\t- %s\n", entry->ext, language_str (entry->lang));
+  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;
   const char *cp;
 
   if (filename != NULL)
     if ((cp = strrchr (filename, '.')) != NULL)
       {
-       filename_language *entry;
-
-       for (i = 0;
-            VEC_iterate (filename_language, filename_language_table, i, entry);
-            ++i)
-         if (strcmp (cp, entry->ext) == 0)
-           return entry->lang;
+       for (const filename_language &entry : filename_language_table)
+         if (entry.ext == cp)
+           return entry.lang;
       }
 
   return language_unknown;
@@ -3390,7 +3356,7 @@ overlay_load_command (const 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");
@@ -3839,6 +3805,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)
 {
@@ -3950,4 +3975,12 @@ 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
 }