[RFA] Remove make_cleanup_free_section_addr_info

Message ID 20180313165529.23237-1-tom@tromey.com
State New
Headers show
Series
  • [RFA] Remove make_cleanup_free_section_addr_info
Related show

Commit Message

Tom Tromey March 13, 2018, 4:55 p.m.
This removes make_cleanup_free_section_addr_info, instead introducing
a new section_addr_info_up type and changing all the uses.  While
doing this, I noticed that addrs_section_sort could be changed to
return a std::vector, allowing the removal of even more cleanups.

Regression tested by the buildbot.

gdb/ChangeLog
2018-03-13  Tom Tromey  <tom@tromey.com>

	* 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 section_addr_info_deleter): New.
	(section_addr_info_up): New typedef.
	(build_section_addr_info_from_objfile, alloc_section_addr_info)
	(build_section_addr_info_from_section_table): Return
	section_addr_info_up.
	(free_section_addr_info): Don't declare.
	* symfile.c (alloc_section_addr_info)
	(build_section_addr_info_from_section_table)
	(build_section_addr_info_from_bfd)
	(build_section_addr_info_from_objfile): Return a
	section_addr_info_up.
	(section_addr_info_deleter::operator ()): Rename from
	free_section_addr_info.
	(addrs_section_compar): Change type; now usable by std::sort.
	(addrs_section_sort): Return a std::vector.  Don't add a final
	NULL.
	(addr_info_make_relative, syms_from_objfile_1)
	(symbol_file_add_separate, add_symbol_file_command): Update.
	* symfile-mem.c (symbol_file_add_from_memory): Update.
	* solib.c (solib_read_symbols): Update.
	* objfiles.c (objfile_relocate): Update.
	* jit.c (jit_bfd_try_read_symtab): Update.
---
 gdb/ChangeLog     |  28 ++++++++++++
 gdb/jit.c         |  10 ++---
 gdb/objfiles.c    |  13 ++----
 gdb/solib.c       |  10 ++---
 gdb/symfile-mem.c |   8 +---
 gdb/symfile.c     | 126 ++++++++++++++++++++++--------------------------------
 gdb/symfile.h     |  27 +++++++-----
 gdb/utils.c       |  12 ------
 gdb/utils.h       |   4 --
 9 files changed, 111 insertions(+), 127 deletions(-)

-- 
2.13.6

Comments

Simon Marchi March 14, 2018, 9:20 p.m. | #1
On 2018-03-13 12:55, Tom Tromey wrote:
> This removes make_cleanup_free_section_addr_info, instead introducing

> a new section_addr_info_up type and changing all the uses.  While

> doing this, I noticed that addrs_section_sort could be changed to

> return a std::vector, allowing the removal of even more cleanups.

> 

> Regression tested by the buildbot.


Hi Tom,

Did you consider changing the section_addr_info struct to use entirely 
by an std::vector<other_sections>?  Functions that return a 
section_addr_info could return a vector directly (by value? is that how 
we say it?), so we shouldn't need any custom unique pointer.  Then, 
other_sections::name can be made into a string, removing the need to 
free it by hand.

Simon
Tom Tromey March 16, 2018, 2:44 a.m. | #2
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:


Simon> Did you consider changing the section_addr_info struct to use entirely
Simon> by an std::vector<other_sections>?  Functions that return a
Simon> section_addr_info could return a vector directly (by value? is that
Simon> how we say it?), so we shouldn't need any custom unique pointer.
Simon> Then, other_sections::name can be made into a string, removing the
Simon> need to free it by hand.

I didn't really consider it, but thanks for the idea.  It turned out to
be more invasive, but it did remove one weirdness from
syms_from_objfile_1.  Previously that function did:

      local_addr = alloc_section_addr_info (1);

... however, it doesn't actually need 1 entry -- the way this is set up,
the minimum that can be requested is 1, but the returned
section_addr_info actually has num_sections set to 0.  Obscure!

In the new code this is replaced by an empty vector.

Let me know what you think.  I did re-run this through the buildbot.

One idea I had is that maybe other_sections should have a constructor.
That would simplify some of the code.

Tom

commit 015829baf05751fdc87430d9fca581092924776b
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Mar 12 21:50:33 2018 -0600

    Remove make_cleanup_free_section_addr_info
    
    This removes make_cleanup_free_section_addr_info.  Instead -- per
    Simon's suggestion -- this changes section_addr_info to be a
    std::vector.
    
    Regression tested by the buildbot.
    
    gdb/ChangeLog
    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.

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;
Simon Marchi March 16, 2018, 3:29 a.m. | #3
On 2018-03-15 10:44 PM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

> 

> Simon> Did you consider changing the section_addr_info struct to use entirely

> Simon> by an std::vector<other_sections>?  Functions that return a

> Simon> section_addr_info could return a vector directly (by value? is that

> Simon> how we say it?), so we shouldn't need any custom unique pointer.

> Simon> Then, other_sections::name can be made into a string, removing the

> Simon> need to free it by hand.

> 

> I didn't really consider it, but thanks for the idea.  It turned out to

> be more invasive, but it did remove one weirdness from

> syms_from_objfile_1.  Previously that function did:

> 

>       local_addr = alloc_section_addr_info (1);

> 

> ... however, it doesn't actually need 1 entry -- the way this is set up,

> the minimum that can be requested is 1, but the returned

> section_addr_info actually has num_sections set to 0.  Obscure!

> 

> In the new code this is replaced by an empty vector.

> 

> Let me know what you think.  I did re-run this through the buildbot.

> 

> One idea I had is that maybe other_sections should have a constructor.

> That would simplify some of the code.


Hi Tom,

I took a quick look, it LGTM, but indeed having a constructor in other_sections
would make it nicer IMO.

Simon
Tom Tromey March 16, 2018, 7:04 p.m. | #4
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:


Simon> I took a quick look, it LGTM, but indeed having a constructor in
Simon> other_sections would make it nicer IMO.

Yeah, it's a lot better.

Tom

commit 8ee2520d15819865f6d1322e28858b5c46610a0b
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Mar 12 21:50:33 2018 -0600

    Remove make_cleanup_free_section_addr_info
    
    This removes make_cleanup_free_section_addr_info.  Instead -- per
    Simon's suggestion -- this changes section_addr_info to be a
    std::vector.
    
    Regression tested by the buildbot.
    
    gdb/ChangeLog
    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 constructor.
            (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.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4510a28cd8..3cc00765e4 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 constructor.
+	(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-15  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
diff --git a/gdb/jit.c b/gdb/jit.c
index 62d6634541..0b5b06fb7c 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,23 @@ 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 (bfd_get_section_vma (nbfd.get (), sec),
+			  bfd_get_section_name (nbfd.get (), sec),
+			  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..1653628e68 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,24 @@ 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->num_sections = i;
+      sai.emplace_back (bfd_get_section_vma (nbfd, sec) + loadbase,
+			bfd_get_section_name (nbfd, sec),
+			sec->index);
 
   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..e202ca2e8d 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,69 @@ 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->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.size () < end - start)
+	sap.emplace_back (stp->addr,
+			  bfd_section_name (abfd, asect),
+			  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->num_sections = i;
+      sap.emplace_back (bfd_get_section_vma (abfd, sec),
+			bfd_get_section_name (abfd, sec),
+			gdb_bfd_section_index (abfd, sec));
 
   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 +419,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 +458,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 +497,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 +526,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 +576,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 +612,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 +639,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 +914,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 +947,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 +977,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 +987,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 +995,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 +1002,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 +1058,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 +1172,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 +1191,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 +1203,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 +2077,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 +2090,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 +2163,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 +2174,9 @@ 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 (addr, sec, 0);
       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 +2184,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..d9185092ee 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -47,8 +47,19 @@ typedef int (symbol_compare_ftype) (const char *string1,
 
 struct other_sections
 {
+  other_sections (CORE_ADDR addr_, std::string &&name_, int sectindex_)
+    : addr (addr_),
+      name (std::move (name_)),
+      sectindex (sectindex_)
+  {
+  }
+
+  other_sections (other_sections &&other) = default;
+
+  DISABLE_COPY_AND_ASSIGN (other_sections);
+
   CORE_ADDR addr;
-  char *name;
+  std::string name;
 
   /* SECTINDEX must be valid for associated BFD or set to -1.  */
   int sectindex;
@@ -61,15 +72,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 +343,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 +372,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 +420,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 +431,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;
Simon Marchi March 16, 2018, 8 p.m. | #5
On 2018-03-16 03:04 PM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

> 

> Simon> I took a quick look, it LGTM, but indeed having a constructor in

> Simon> other_sections would make it nicer IMO.

> 

> Yeah, it's a lot better.

> 

> Tom


Thanks for doing this, LGTM.

Simon

Patch

diff --git a/gdb/jit.c b/gdb/jit.c
index 62d6634541..9a46db3917 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -888,10 +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;
 
@@ -931,8 +929,8 @@  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);
+  section_addr_info_up sai
+    = alloc_section_addr_info (bfd_count_sections (nbfd.get ()));
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd.get (), sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
@@ -948,10 +946,10 @@  JITed symbol file is not an object file, ignoring it.\n"));
 
   /* 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.get (),
 				      OBJF_SHARED | OBJF_NOT_FILENAME, NULL);
 
-  do_cleanups (old_cleanups);
   add_objfile_entry (objfile, entry_addr);
 }
 
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index a9aaf89540..22b20fa12a 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_up 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.get (), debug_objfile->obfd);
 
       gdb_assert (debug_objfile->num_sections
 		  == gdb_bfd_count_sections (debug_objfile->obfd));
@@ -923,11 +920,9 @@  objfile_relocate (struct objfile *objfile,
 	new_debug_offsets (SIZEOF_N_SECTION_OFFSETS (debug_objfile->num_sections));
       relative_addr_info_to_section_offsets (new_debug_offsets.data (),
 					     debug_objfile->num_sections,
-					     objfile_addrs);
+					     objfile_addrs.get ());
 
       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..ccbc8609b0 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -687,13 +687,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_up 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.get (),
+						      OBJF_SHARED, NULL);
 	      so->objfile->addr_low = so->addr_low;
-	      free_section_addr_info (sap);
 	    }
 
 	  so->symbols_loaded = 1;
diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c
index 8d91c729a5..90eacbe61c 100644
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -88,9 +88,7 @@  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,8 +112,7 @@  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);
+  section_addr_info_up sai = alloc_section_addr_info (bfd_count_sections (nbfd));
   i = 0;
   for (sec = nbfd->sections; sec != NULL; sec = sec->next)
     if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
@@ -131,14 +128,13 @@  symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr,
     add_flags |= SYMFILE_VERBOSE;
 
   objf = symbol_file_add_from_bfd (nbfd, bfd_get_filename (nbfd),
-				   add_flags, sai, OBJF_SHARED, NULL);
+				   add_flags, sai.get (), 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 58747d545b..0a514b34fc 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"
 
@@ -219,7 +220,7 @@  find_lowest_section (bfd *abfd, asection *sect, void *obj)
    new object's 'num_sections' field is set to 0; it must be updated
    by the caller.  */
 
-struct section_addr_info *
+section_addr_info_up
 alloc_section_addr_info (size_t num_sections)
 {
   struct section_addr_info *sap;
@@ -230,21 +231,20 @@  alloc_section_addr_info (size_t num_sections)
   sap = (struct section_addr_info *) xmalloc (size);
   memset (sap, 0, size);
 
-  return sap;
+  return section_addr_info_up (sap);
 }
 
 /* Build (allocate and populate) a section_addr_info struct from
    an existing section table.  */
 
-extern struct section_addr_info *
+section_addr_info_up
 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_up sap = alloc_section_addr_info (end - start);
 
   for (stp = start, oidx = 0; stp != end; stp++)
     {
@@ -268,14 +268,14 @@  build_section_addr_info_from_section_table (const struct target_section *start,
 
 /* Create a section_addr_info from section offsets in ABFD.  */
 
-static struct section_addr_info *
+static section_addr_info_up
 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));
+  section_addr_info_up sap
+    = alloc_section_addr_info (bfd_count_sections (abfd));
   for (i = 0, sec = abfd->sections; sec != NULL; sec = sec->next)
     if (bfd_get_section_flags (abfd, sec) & (SEC_ALLOC | SEC_LOAD))
       {
@@ -292,16 +292,15 @@  build_section_addr_info_from_bfd (bfd *abfd)
 
 /* Create a section_addr_info from section offsets in OBJFILE.  */
 
-struct section_addr_info *
+section_addr_info_up
 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);
+  section_addr_info_up sap = build_section_addr_info_from_bfd (objfile->obfd);
   for (i = 0; i < sap->num_sections; i++)
     {
       int sectindex = sap->other[i].sectindex;
@@ -313,8 +312,8 @@  build_section_addr_info_from_objfile (const struct objfile *objfile)
 
 /* Free all memory allocated by build_section_addr_info_from_section_table.  */
 
-extern void
-free_section_addr_info (struct section_addr_info *sap)
+void
+section_addr_info_deleter::operator () (struct section_addr_info *sap)
 {
   int idx;
 
@@ -502,39 +501,35 @@  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;
+  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 **
+static std::vector<struct other_sections *>
 addrs_section_sort (struct section_addr_info *addrs)
 {
-  struct other_sections **array;
   int i;
 
-  /* `+ 1' for the NULL terminator.  */
-  array = XNEWVEC (struct other_sections *, addrs->num_sections + 1);
+  std::vector<struct other_sections *> array (addrs->num_sections);
   for (i = 0; i < addrs->num_sections; i++)
     array[i] = &addrs->other[i];
-  array[i] = NULL;
 
-  qsort (array, i, sizeof (*array), addrs_section_compar);
+  std::sort (array.begin (), array.end (), addrs_section_compar);
 
   return array;
 }
@@ -549,10 +544,6 @@  addr_info_make_relative (struct 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 +568,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<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_up abfd_addrs = build_section_addr_info_from_bfd (abfd);
+  std::vector<struct other_sections *> abfd_addrs_sorted
+    = addrs_section_sort (abfd_addrs.get ());
 
   /* 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<struct other_sections *>
+    addrs_to_abfd_addrs (addrs->num_sections, nullptr);
 
-  while (*addrs_sorted)
+  std::vector<struct other_sections *>::iterator abfd_sorted_iter
+    = abfd_addrs_sorted.begin ();
+  for (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);
 
-      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),
 			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),
 		     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->other;
 	  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.
@@ -681,8 +671,6 @@  addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd)
 	  addrs->other[i].sectindex = -1;
 	}
     }
-
-  do_cleanups (my_cleanup);
 }
 
 /* Parse the user's idea of an offset for dynamic linking, into our idea
@@ -971,7 +959,7 @@  syms_from_objfile_1 (struct objfile *objfile,
 		     struct section_addr_info *addrs,
 		     symfile_add_flags add_flags)
 {
-  struct section_addr_info *local_addr = NULL;
+  section_addr_info_up local_addr;
   struct cleanup *old_chain;
   const int mainline = add_flags & SYMFILE_MAINLINE;
 
@@ -1003,8 +991,7 @@  syms_from_objfile_1 (struct objfile *objfile,
   if (! addrs)
     {
       local_addr = alloc_section_addr_info (1);
-      make_cleanup (xfree, local_addr);
-      addrs = local_addr;
+      addrs = local_addr.get ();
     }
 
   if (mainline)
@@ -1053,7 +1040,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
@@ -1231,22 +1217,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_up sap = build_section_addr_info_from_objfile (objfile);
 
   symbol_file_add_with_addrs
-    (bfd, name, symfile_flags, sap,
+    (bfd, name, symfile_flags, sap.get (),
      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
@@ -2172,10 +2152,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 ();
 
@@ -2247,8 +2225,8 @@  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_up section_addrs
+    = alloc_section_addr_info (sect_opts.size ());
   for (sect_opt &sect : sect_opts)
     {
       CORE_ADDR addr;
@@ -2276,14 +2254,14 @@  add_symbol_file_command (const char *args, int from_tty)
   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.get (),
+			  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..0e03f3115e 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -369,7 +369,19 @@  struct sym_fns
   const struct quick_symbol_functions *qf;
 };
 
-extern struct section_addr_info *
+/* A deleter that frees a struct section_addr_info.  */
+
+struct section_addr_info_deleter
+{
+  void operator() (struct section_addr_info *handle);
+};
+
+/* A unique pointer that holds a section_addr_info.  */
+
+typedef std::unique_ptr<struct section_addr_info> section_addr_info_up;
+
+
+extern section_addr_info_up
   build_section_addr_info_from_objfile (const struct objfile *objfile);
 
 extern void relative_addr_info_to_section_offsets
@@ -430,24 +442,17 @@  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);
+extern section_addr_info_up 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_up
+   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;