diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a62255fb03..c1157010a3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,42 @@
+2018-03-15  Tom Tromey  <tom@tromey.com>
+
+	* xcoffread.c (xcoff_symfile_offsets): Change type of "addrs".
+	* utils.h (make_cleanup_free_section_addr_info): Don't declare.
+	* utils.c (do_free_section_addr_info)
+	(make_cleanup_free_section_addr_info): Remove.
+	* symfile.h (struct other_sections): Add member initializers.
+	(struct section_addr_info): Remove.
+	(section_addr_info): New typedef.
+	(struct sym_fns) <sym_offsets>: Change type of parameter.
+	(build_section_addr_info_from_objfile)
+	(relative_addr_info_to_section_offsets, addr_info_make_relative)
+	(default_symfile_offsets, symbol_file_add)
+	(symbol_file_add_from_bfd)
+	(build_section_addr_info_from_section_table): Update.
+	(alloc_section_addr_info, free_section_addr_info): Don't declare.
+	* symfile.c (alloc_section_addr_info): Remove.
+	(build_section_addr_info_from_section_table): Change return type.
+	Update.
+	(build_section_addr_info_from_bfd)
+	(build_section_addr_info_from_objfile): Likewise.
+	(free_section_addr_info): Remove.
+	(relative_addr_info_to_section_offsets): Change type of "addrs".
+	(addrs_section_compar): Now a std::sort comparator.
+	(addrs_section_sort): Change return type.
+	(addr_info_make_relative): Change type of "addrs".  Update.
+	(default_symfile_offsets, syms_from_objfile_1)
+	(syms_from_objfile, symbol_file_add_with_addrs): Likewise.
+	(symbol_file_add_separate): Update.
+	(symbol_file_add): Change type of "addrs".  Update.
+	(add_symbol_file_command): Update.  Remove cleanups.
+	* symfile-mem.c (symbol_file_add_from_memory): Update.  Remove
+	cleanups.
+	* symfile-debug.c (debug_sym_offsets): Change type of "info".
+	* solib.c (solib_read_symbols): Update.
+	* objfiles.c (objfile_relocate): Update.  Remove cleanups.
+	* machoread.c (macho_symfile_offsets): Update.
+	* jit.c (jit_bfd_try_read_symtab): Update.
+
 2018-03-14  Tom Tromey  <tom@tromey.com>
 
 	PR cli/14977:
diff --git a/gdb/jit.c b/gdb/jit.c
index 62d6634541..54682cc8f4 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -888,11 +888,8 @@ jit_bfd_try_read_symtab (struct jit_code_entry *code_entry,
                          CORE_ADDR entry_addr,
                          struct gdbarch *gdbarch)
 {
-  struct section_addr_info *sai;
   struct bfd_section *sec;
   struct objfile *objfile;
-  struct cleanup *old_cleanups;
-  int i;
   const struct bfd_arch_info *b;
 
   if (jit_debug)
@@ -931,27 +928,24 @@ JITed symbol file is not an object file, ignoring it.\n"));
   /* Read the section address information out of the symbol file.  Since the
      file is generated by the JIT at runtime, it should all of the absolute
      addresses that we care about.  */
-  sai = alloc_section_addr_info (bfd_count_sections (nbfd.get ()));
-  old_cleanups = make_cleanup_free_section_addr_info (sai);
-  i = 0;
+  section_addr_info sai;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
         /* We assume that these virtual addresses are absolute, and do not
            treat them as offsets.  */
-        sai->other[i].addr = bfd_get_section_vma (nbfd.get (), sec);
-        sai->other[i].name = xstrdup (bfd_get_section_name (nbfd.get (), sec));
-        sai->other[i].sectindex = sec->index;
-        ++i;
+	sai.emplace_back ();
+	sai.back ().addr = bfd_get_section_vma (nbfd.get (), sec);
+	sai.back ().name = bfd_get_section_name (nbfd.get (), sec);
+	sai.back ().sectindex = sec->index;
       }
-  sai->num_sections = i;
 
   /* This call does not take ownership of SAI.  */
   objfile = symbol_file_add_from_bfd (nbfd.get (),
-				      bfd_get_filename (nbfd.get ()), 0, sai,
+				      bfd_get_filename (nbfd.get ()), 0,
+				      &sai,
 				      OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
 
-  do_cleanups (old_cleanups);
   add_objfile_entry (objfile, entry_addr);
 }
 
diff --git a/gdb/machoread.c b/gdb/machoread.c
index ab4410c925..8babba197c 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -927,7 +927,7 @@ macho_symfile_finish (struct objfile *objfile)
 
 static void
 macho_symfile_offsets (struct objfile *objfile,
-                       const struct section_addr_info *addrs)
+                       const section_addr_info &addrs)
 {
   unsigned int i;
   struct obj_section *osect;
@@ -949,15 +949,15 @@ macho_symfile_offsets (struct objfile *objfile,
      N.B. if an objfile slides after we've already created it, then it
      goes through objfile_relocate.  */
 
-  for (i = 0; i < addrs->num_sections; i++)
+  for (i = 0; i < addrs.size (); i++)
     {
       ALL_OBJFILE_OSECTIONS (objfile, osect)
 	{
 	  const char *bfd_sect_name = osect->the_bfd_section->name;
 
-	  if (strcmp (bfd_sect_name, addrs->other[i].name) == 0)
+	  if (bfd_sect_name == addrs[i].name)
 	    {
-	      obj_section_offset (osect) = addrs->other[i].addr;
+	      obj_section_offset (osect) = addrs[i].addr;
 	      break;
 	    }
 	}
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index a9aaf89540..3a577359b7 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -906,16 +906,13 @@ objfile_relocate (struct objfile *objfile,
        debug_objfile;
        debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile))
     {
-      struct section_addr_info *objfile_addrs;
-      struct cleanup *my_cleanups;
-
-      objfile_addrs = build_section_addr_info_from_objfile (objfile);
-      my_cleanups = make_cleanup (xfree, objfile_addrs);
+      section_addr_info objfile_addrs
+	= build_section_addr_info_from_objfile (objfile);
 
       /* Here OBJFILE_ADDRS contain the correct absolute addresses, the
 	 relative ones must be already created according to debug_objfile.  */
 
-      addr_info_make_relative (objfile_addrs, debug_objfile->obfd);
+      addr_info_make_relative (&objfile_addrs, debug_objfile->obfd);
 
       gdb_assert (debug_objfile->num_sections
 		  == gdb_bfd_count_sections (debug_objfile->obfd));
@@ -926,8 +923,6 @@ objfile_relocate (struct objfile *objfile,
 					     objfile_addrs);
 
       changed |= objfile_relocate1 (debug_objfile, new_debug_offsets.data ());
-
-      do_cleanups (my_cleanups);
     }
 
   /* Relocate breakpoints as necessary, after things are relocated.  */
diff --git a/gdb/solib.c b/gdb/solib.c
index 1c78845938..f9a31bca19 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -676,8 +676,6 @@ solib_read_symbols (struct so_list *so, symfile_add_flags flags)
 
       TRY
 	{
-	  struct section_addr_info *sap;
-
 	  /* Have we already loaded this shared object?  */
 	  ALL_OBJFILES (so->objfile)
 	    {
@@ -687,13 +685,13 @@ solib_read_symbols (struct so_list *so, symfile_add_flags flags)
 	    }
 	  if (so->objfile == NULL)
 	    {
-	      sap = build_section_addr_info_from_section_table (so->sections,
-								so->sections_end);
+	      section_addr_info sap
+		= build_section_addr_info_from_section_table (so->sections,
+							      so->sections_end);
 	      so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
-						      flags, sap, OBJF_SHARED,
-						      NULL);
+						      flags, &sap,
+						      OBJF_SHARED, NULL);
 	      so->objfile->addr_low = so->addr_low;
-	      free_section_addr_info (sap);
 	    }
 
 	  so->symbols_loaded = 1;
diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c
index 8b2df55031..358b2f8273 100644
--- a/gdb/symfile-debug.c
+++ b/gdb/symfile-debug.c
@@ -506,7 +506,7 @@ debug_sym_finish (struct objfile *objfile)
 
 static void
 debug_sym_offsets (struct objfile *objfile,
-		   const struct section_addr_info *info)
+		   const section_addr_info &info)
 {
   const struct debug_sym_fns_data *debug_data
     = ((const struct debug_sym_fns_data *)
@@ -514,7 +514,7 @@ debug_sym_offsets (struct objfile *objfile,
 
   fprintf_filtered (gdb_stdlog, "sf->sym_offsets (%s, %s)\n",
 		    objfile_debug_name (objfile),
-		    host_address_to_string (info));
+		    host_address_to_string (&info));
 
   debug_data->real_sf->sym_offsets (objfile, info);
 }
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 8d91c729a5..01883c2ca1 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -88,9 +88,6 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
   struct bfd *nbfd;
   struct bfd_section *sec;
   bfd_vma loadbase;
-  struct section_addr_info *sai;
-  unsigned int i;
-  struct cleanup *cleanup;
   symfile_add_flags add_flags = 0;
 
   if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
@@ -114,31 +111,27 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
     error (_("Got object file from memory but can't read symbols: %s."),
 	   bfd_errmsg (bfd_get_error ()));
 
-  sai = alloc_section_addr_info (bfd_count_sections (nbfd));
-  cleanup = make_cleanup (xfree, sai);
-  i = 0;
+  section_addr_info sai;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
       {
-	sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
-	sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
-	sai->other[i].sectindex = sec->index;
-	++i;
+	sai.emplace_back ();
+	sai.back ().addr = bfd_get_section_vma (nbfd, sec) + loadbase;
+	sai.back ().name = bfd_get_section_name (nbfd, sec);
+	sai.back ().sectindex = sec->index;
       }
-  sai->num_sections = i;
 
   if (from_tty)
     add_flags |= SYMFILE_VERBOSE;
 
   objf = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd),
-				   add_flags, sai, OBJF_SHARED, NULL);
+				   add_flags, &sai, OBJF_SHARED, NULL);
 
   add_target_sections_of_objfile (objf);
 
   /* This might change our ideas about frames already looked at.  */
   reinit_frame_cache ();
 
-  do_cleanups (cleanup);
   return objf;
 }
 
diff --git a/gdb/symfile.c b/gdb/symfile.c
index f714845a6e..32f8336f9a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -64,6 +64,7 @@
 #include <sys/stat.h>
 #include <ctype.h>
 #include <chrono>
+#include <algorithm>
 
 #include "psymtab.h"
 
@@ -215,114 +216,75 @@ find_lowest_section (bfd *abfd, asection *sect, void *obj)
     *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.  */
 
-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)
 {
-  struct section_addr_info *sap;
   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;
 
       if (bfd_get_section_flags (abfd, asect) & (SEC_ALLOC | SEC_LOAD)
-	  && oidx < end - start)
+	  && sap.size () < 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++;
+	  sap.emplace_back ();
+	  sap.back ().addr = stp->addr;
+	  sap.back ().name = bfd_section_name (abfd, asect);
+	  sap.back ().sectindex = gdb_bfd_section_index (abfd, asect);
 	}
     }
 
-  sap->num_sections = oidx;
-
   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)
 {
-  struct section_addr_info *sap;
-  int i;
   struct bfd_section *sec;
 
-  sap = alloc_section_addr_info (bfd_count_sections (abfd));
-  for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next)
+  section_addr_info sap;
+  for (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.emplace_back ();
+	sap.back ().addr = bfd_get_section_vma (abfd, sec);
+	sap.back ().name = bfd_get_section_name (abfd, sec);
+	sap.back ().sectindex = gdb_bfd_section_index (abfd, sec);
       }
 
-  sap->num_sections = i;
-
   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)
 {
-  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));
      */
-  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->offsets[sectindex];
     }
   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
@@ -463,18 +425,18 @@ place_section (bfd *abfd, asection *sect, void *obj)
 void
 relative_addr_info_to_section_offsets (struct section_offsets *section_offsets,
 				       int num_sections,
-				       const struct section_addr_info *addrs)
+				       const section_addr_info &addrs)
 {
   int i;
 
   memset (section_offsets, 0, SIZEOF_N_SECTION_OFFSETS (num_sections));
 
   /* 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;
 
-      osp = &addrs->other[i];
+      osp = &addrs[i];
       if (osp->sectindex == -1)
   	continue;
 
@@ -502,39 +464,36 @@ addr_section_name (const char *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;
 
-  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;
 
-  /* `+ 1' for the NULL terminator.  */
-  array = XNEWVEC (struct other_sections *, 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;
 }
@@ -544,15 +503,11 @@ addrs_section_sort (struct section_addr_info *addrs)
    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;
-  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
      continguous sections.  */
@@ -577,45 +532,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.  */
 
-  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.  */
 
-  addrs_to_abfd_addrs = XCNEWVEC (struct other_sections *, 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 struct 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)
-	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.  */
-	  index_in_addrs = *addrs_sorted - addrs->other;
+	  index_in_addrs = sect - addrs->data ();
 	  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.  */
-	  abfd_addrs_sorted++;
+	  abfd_sorted_iter++;
 	}
-
-      addrs_sorted++;
     }
 
   /* Calculate offsets for the loadable sections.
@@ -628,27 +582,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 */
 
-  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.  */
-	  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
-	    addrs->other[i].addr = lower_offset;
+	    (*addrs)[i].addr = lower_offset;
 	}
       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.
@@ -664,25 +618,23 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 
 	     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
-		    && strcmp (addrs->other[i - 1].name, ".dynbss") == 0
+		    && (*addrs)[i - 1].name == ".dynbss"
 		    && addrs_to_abfd_addrs[i - 1] != NULL)
-		|| (strcmp (sect_name, ".sbss") == 0
+		|| (sect_name == ".sbss"
 		    && i > 0
-		    && strcmp (addrs->other[i - 1].name, ".sdynbss") == 0
+		    && (*addrs)[i - 1].name == ".sdynbss"
 		    && 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));
 
-	  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
@@ -693,7 +645,7 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 
 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 *)
@@ -968,10 +920,10 @@ init_entry_point_info (struct objfile *objfile)
 
 static void
 syms_from_objfile_1 (struct objfile *objfile,
-		     struct section_addr_info *addrs,
+		     section_addr_info *addrs,
 		     symfile_add_flags add_flags)
 {
-  struct section_addr_info *local_addr = NULL;
+  section_addr_info local_addr;
   struct cleanup *old_chain;
   const int mainline = add_flags & SYMFILE_MAINLINE;
 
@@ -1001,11 +953,7 @@ syms_from_objfile_1 (struct objfile *objfile,
      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)
     {
@@ -1035,7 +983,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.  */
-  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
@@ -1045,7 +993,7 @@ syms_from_objfile_1 (struct objfile *objfile,
   (*objfile->sf->sym_init) (objfile);
   clear_complaints (&symfile_complaints, 1, add_flags & SYMFILE_VERBOSE);
 
-  (*objfile->sf->sym_offsets) (objfile, addrs);
+  (*objfile->sf->sym_offsets) (objfile, *addrs);
 
   read_symbols (objfile, add_flags);
 
@@ -1053,7 +1001,6 @@ syms_from_objfile_1 (struct objfile *objfile,
 
   objfile_holder.release ();
   discard_cleanups (old_chain);
-  xfree (local_addr);
 }
 
 /* Same as syms_from_objfile_1, but also initializes the objfile
@@ -1061,7 +1008,7 @@ syms_from_objfile_1 (struct objfile *objfile,
 
 static void
 syms_from_objfile (struct objfile *objfile,
-		   struct section_addr_info *addrs,
+		   section_addr_info *addrs,
 		   symfile_add_flags add_flags)
 {
   syms_from_objfile_1 (objfile, addrs, add_flags);
@@ -1117,7 +1064,7 @@ finish_new_objfile (struct objfile *objfile, symfile_add_flags add_flags)
 static struct objfile *
 symbol_file_add_with_addrs (bfd *abfd, const char *name,
 			    symfile_add_flags add_flags,
-			    struct section_addr_info *addrs,
+			    section_addr_info *addrs,
 			    objfile_flags flags, struct objfile *parent)
 {
   struct objfile *objfile;
@@ -1231,22 +1178,16 @@ symbol_file_add_separate (bfd *bfd, const char *name,
 			  symfile_add_flags symfile_flags,
 			  struct objfile *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.  */
-  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);
 
   symbol_file_add_with_addrs
-    (bfd, name, symfile_flags, sap,
+    (bfd, name, symfile_flags, &sap,
      objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW
 		       | OBJF_USERLOADED),
      objfile);
-
-  do_cleanups (my_cleanup);
 }
 
 /* Process the symbol file ABFD, as either the main file or as a
@@ -1256,7 +1197,7 @@ symbol_file_add_separate (bfd *bfd, const char *name,
 struct objfile *
 symbol_file_add_from_bfd (bfd *abfd, const char *name,
 			  symfile_add_flags add_flags,
-                          struct section_addr_info *addrs,
+			  section_addr_info *addrs,
                           objfile_flags flags, struct objfile *parent)
 {
   return symbol_file_add_with_addrs (abfd, name, add_flags, addrs, flags,
@@ -1268,7 +1209,7 @@ symbol_file_add_from_bfd (bfd *abfd, const char *name,
 
 struct objfile *
 symbol_file_add (const char *name, symfile_add_flags add_flags,
-		 struct section_addr_info *addrs, objfile_flags flags)
+		 section_addr_info *addrs, objfile_flags flags)
 {
   gdb_bfd_ref_ptr bfd (symfile_bfd_open (name));
 
@@ -2142,7 +2083,6 @@ add_symbol_file_command (const char *args, int from_tty)
   gdb::unique_xmalloc_ptr<char> filename;
   char *arg;
   int argcnt = 0;
-  int sec_num = 0;
   struct objfile *objf;
   objfile_flags flags = OBJF_USERLOADED | OBJF_SHARED;
   symfile_add_flags add_flags = 0;
@@ -2156,10 +2096,8 @@ add_symbol_file_command (const char *args, int from_tty)
     const char *value;
   };
 
-  struct section_addr_info *section_addrs;
   std::vector<sect_opt> sect_opts = { { ".text", NULL } };
   bool stop_processing_options = false;
-  struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
 
   dont_repeat ();
 
@@ -2231,8 +2169,7 @@ add_symbol_file_command (const char *args, int from_tty)
 
   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);
+  section_addr_info section_addrs;
   for (sect_opt &sect : sect_opts)
     {
       CORE_ADDR addr;
@@ -2243,11 +2180,11 @@ add_symbol_file_command (const char *args, int from_tty)
 
       /* Here we store the section offsets in the order they were
          entered on the command line.  */
-      section_addrs->other[sec_num].name = (char *) sec;
-      section_addrs->other[sec_num].addr = addr;
+      section_addrs.emplace_back ();
+      section_addrs.back ().name = sec;
+      section_addrs.back ().addr = addr;
       printf_unfiltered ("\t%s_addr = %s\n", sec,
 			 paddress (gdbarch, addr));
-      sec_num++;
 
       /* The object's sections are initialized when a
 	 call is made to build_objfile_section_table (objfile).
@@ -2255,19 +2192,18 @@ add_symbol_file_command (const 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.  */
     }
-  section_addrs->num_sections = sec_num;
 
   if (from_tty && (!query ("%s", "")))
     error (_("Not confirmed."));
 
-  objf = symbol_file_add (filename.get (), add_flags, section_addrs, flags);
+  objf = symbol_file_add (filename.get (), add_flags, &section_addrs,
+			  flags);
 
   add_target_sections_of_objfile (objf);
 
   /* Getting new symbols may change our opinion about what is
      frameless.  */
   reinit_frame_cache ();
-  do_cleanups (my_cleanups);
 }
 
 
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 8cd47d8811..dc4843df9b 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -47,11 +47,11 @@ typedef int (symbol_compare_ftype) (const char *string1,
 
 struct other_sections
 {
-  CORE_ADDR addr;
-  char *name;
+  CORE_ADDR addr = 0;
+  std::string name;
 
   /* SECTINDEX must be valid for associated BFD or set to -1.  */
-  int sectindex;
+  int sectindex = 0;
 };
 
 /* Define an array of addresses to accommodate non-contiguous dynamic
@@ -61,15 +61,7 @@ struct other_sections
    to communicate the section addresses in shared objects to
    symbol_file_add ().  */
 
-struct section_addr_info
-{
-  /* The number of sections for which address information is
-     available.  */
-  size_t num_sections;
-  /* Sections whose names are file format dependent.  */
-  struct other_sections other[1];
-};
-
+typedef std::vector<other_sections> section_addr_info;
 
 /* A table listing the load segments in a symfile, and which segment
    each BFD section belongs to.  */
@@ -340,7 +332,7 @@ struct sym_fns
      The section_addr_info structure contains the offset of loadable and
      allocated sections, relative to the absolute offsets found in the BFD.  */
 
-  void (*sym_offsets) (struct objfile *, const struct section_addr_info *);
+  void (*sym_offsets) (struct objfile *, const section_addr_info &);
 
   /* This function produces a format-independent description of
      the segments of ABFD.  Each segment is a unit of the file
@@ -369,21 +361,21 @@ struct sym_fns
   const struct quick_symbol_functions *qf;
 };
 
-extern struct section_addr_info *
+extern section_addr_info
   build_section_addr_info_from_objfile (const struct objfile *objfile);
 
 extern void relative_addr_info_to_section_offsets
   (struct section_offsets *section_offsets, int num_sections,
-   const struct section_addr_info *addrs);
+   const section_addr_info &addrs);
 
-extern void addr_info_make_relative (struct section_addr_info *addrs,
+extern void addr_info_make_relative (section_addr_info *addrs,
 				     bfd *abfd);
 
 /* The default version of sym_fns.sym_offsets for readers that don't
    do anything special.  */
 
 extern void default_symfile_offsets (struct objfile *objfile,
-				     const struct section_addr_info *);
+				     const section_addr_info &);
 
 /* The default version of sym_fns.sym_segments for readers that don't
    do anything special.  */
@@ -417,10 +409,10 @@ extern enum language deduce_language_from_filename (const char *);
 extern void add_filename_language (const char *ext, enum language lang);
 
 extern struct objfile *symbol_file_add (const char *, symfile_add_flags,
-					struct section_addr_info *, objfile_flags);
+					section_addr_info *, objfile_flags);
 
 extern struct objfile *symbol_file_add_from_bfd (bfd *, const char *, symfile_add_flags,
-                                                 struct section_addr_info *,
+						 section_addr_info *,
                                                  objfile_flags, struct objfile *parent);
 
 extern void symbol_file_add_separate (bfd *, const char *, symfile_add_flags,
@@ -428,26 +420,15 @@ extern void symbol_file_add_separate (bfd *, const char *, symfile_add_flags,
 
 extern std::string find_separate_debug_file_by_debuglink (struct objfile *);
 
-/* Create a new section_addr_info, with room for NUM_SECTIONS.  */
-
-extern struct section_addr_info *alloc_section_addr_info (size_t
-							  num_sections);
-
 /* Build (allocate and populate) a section_addr_info struct from an
    existing section table.  */
 
-extern struct section_addr_info
-  *build_section_addr_info_from_section_table (const struct target_section
+extern section_addr_info
+   build_section_addr_info_from_section_table (const struct target_section
 					       *start,
 					       const struct target_section
 					       *end);
 
-/* Free all memory allocated by
-   build_section_addr_info_from_section_table.  */
-
-extern void free_section_addr_info (struct section_addr_info *);
-
-
 			/*   Variables   */
 
 /* If non-zero, shared library symbols will be added automatically
diff --git a/gdb/utils.c b/gdb/utils.c
index b99d444a6e..3886efd840 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -141,18 +141,6 @@ show_pagination_enabled (struct ui_file *file, int from_tty,
    because while they use the "cleanup API" they are not part of the
    "cleanup API".  */
 
-static void
-do_free_section_addr_info (void *arg)
-{
-  free_section_addr_info ((struct section_addr_info *) arg);
-}
-
-struct cleanup *
-make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
-{
-  return make_cleanup (do_free_section_addr_info, addrs);
-}
-
 /* Helper for make_cleanup_unpush_target.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index 8ca3eb0369..6ff18568fe 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -242,10 +242,6 @@ private:
 
 /* Cleanup utilities.  */
 
-struct section_addr_info;
-extern struct cleanup *make_cleanup_free_section_addr_info
-                       (struct section_addr_info *);
-
 /* For make_cleanup_close see common/filestuff.h.  */
 
 struct target_ops;
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 4f399642bd..8c707aa8fe 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3054,7 +3054,7 @@ xcoff_initial_scan (struct objfile *objfile, symfile_add_flags symfile_flags)
 
 static void
 xcoff_symfile_offsets (struct objfile *objfile,
-		       const struct section_addr_info *addrs)
+		       const section_addr_info &addrs)
 {
   const char *first_section_name;
 
