gdb: replace msym_bunch with deque

Message ID 20251217043141.1790384-1-simon.marchi@polymtl.ca
State New
Headers
Series gdb: replace msym_bunch with deque |

Commit Message

Simon Marchi Dec. 17, 2025, 4:31 a.m. UTC
  From: Simon Marchi <simon.marchi@efficios.com>

This patch replaces the msym_bunch implementation with an std::deque.

I initially tried to replace it with a vector.  However, that doesn't
work, because minimal_symbol references need to stay valid across calls
to minimal_symbol_reade::record_full in at least one spot.
elf_symtab_read calls minimal_symbol_reader::record_full (through
function record_minimal_symbol) to record a minimal symbol for a PLT
entry and then uses a previously added minimal symbol to set the size of
the PLT minimal symbol.  If we used a vector, a re-allocation could
happen which would invalidate the reference to the previous minimal
symbol (luckily this was caught by ASan).

An std::deque implementation typically uses a sequence of fixed-sized
arrays, much like our current msym_bunch implementation.  So adding an
item at the end will not invalidate existing references.  But unlike our
msym_bunch, we don't have to worry about memory management.

I am a bit puzzled about this code in
minimal_symbol_reader::record_full:

  /* If we already read minimal symbols for this objfile, then don't
     ever allocate a new one.  */
  if (!m_objfile->per_bfd->minsyms_read)
    {
      m_msym_bunch_index++;
      m_objfile->per_bfd->n_minsyms++;
    }

I am not sure when minsyms_read would already be true when reading
minimal symbols, and if we should do anything differently here.

Change-Id: I7d10c6aca42cc9dcf80b483394e1e56351a9465f
---
 gdb/minsyms.c | 95 ++++++++-------------------------------------------
 gdb/minsyms.h | 23 ++++---------
 2 files changed, 21 insertions(+), 97 deletions(-)


base-commit: 04a9afc1d81058275219b499fd75c983967a30c1
  

Comments

Tom Tromey Dec. 17, 2025, 4:01 p.m. UTC | #1
>>>>> "Simon" == simon marchi <simon.marchi@polymtl.ca> writes:

Simon> An std::deque implementation typically uses a sequence of fixed-sized
Simon> arrays, much like our current msym_bunch implementation.  So adding an
Simon> item at the end will not invalidate existing references.  But unlike our
Simon> msym_bunch, we don't have to worry about memory management.

FWIW we have another instance of this idiom in buildsym.

Simon> I am a bit puzzled about this code in
Simon> minimal_symbol_reader::record_full:

Simon> I am not sure when minsyms_read would already be true when reading
Simon> minimal symbols, and if we should do anything differently here.

It's been a long time since I worked on this, but IIRC there were
readers where minimal symbol reading was mixed with partial symbol reading.
In these cases we could reuse the already-read minimal symbols but not
the partial symbols.  This code, and the check in
minimal_symbol_reader::install, were there to allow the reuse without
creating new symbols.

The particular check you highlighted is just based on the idea that the
code is still trying to create a minimal symbol, but since it won't ever
be installed, there's no point to allocating more memory, we can just
reuse the same one over and over.

It's possible all this is obsolete given the stabs removal.  You'd have
to investigate.  But anyway all of this was a hack to avoid doing work
on these ancient / obsolete readers.

Simon> +  /* The minimal symbols recorded so far.  This uses a deque instead of e.g. a
Simon> +     vector, because references to minimal symbols need to stay valid across
Simon> +     calls to recod_full.  */

Typo, "record_full"

Tom
  
Tom Tromey Dec. 17, 2025, 6:46 p.m. UTC | #2
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> It's possible all this is obsolete given the stabs removal.  You'd have
Tom> to investigate.  But anyway all of this was a hack to avoid doing work
Tom> on these ancient / obsolete readers.

mdebugread.c seems to use this feature.

BTW I meant to approve your patch.
Approved-By: Tom Tromey <tom@tromey.com>

Tom
  
Simon Marchi Dec. 17, 2025, 7:58 p.m. UTC | #3
On 12/17/25 1:46 PM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
> 
> Tom> It's possible all this is obsolete given the stabs removal.  You'd have
> Tom> to investigate.  But anyway all of this was a hack to avoid doing work
> Tom> on these ancient / obsolete readers.
> 
> mdebugread.c seems to use this feature.

Indeed, I dug into that in the mean time.  I'd like if someone with
historical knowledge could fact-check me here.  My understanding is:

 - There is the ECOFF format, which based on COFF but also specifies a
   debug information format (is that what mdebug is?).  ECOFF seems to
   have been used mostly on Alpha and MIPS, before being superseded by
   ELF somewhere around 2000.
 - During the transition from ECOFF to ELF, it was made possible to put
   ECOFF debug info inside ELF.
 - The ECOFF debug info format was eventually completely replaced by
   DWARF, in about the same time frame.

So the situation that interests us is when you have ECOFF-in-ELF.  We
first read the ELF minimal symbols in elf_symfile_read, then go into
elfmdebug_build_psymtabs.  elfmdebug_build_psymtabs is able to generate
minimal symbols (useful when you have ECOFF debug info in an ECOFF
executable I presume), but in this case we don't want to have those
minimal symbols, we already have the ELF ones.  Hence the need for this
"don't actually create minimal symbols if we already have minimal
symbols".

Here are some relevant comments.  This on in elfmdebug_build_psymtabs:

  /* FIXME: It's not clear whether we should be getting minimal symbol
     information from .mdebug in an ELF file, or whether we will.
     Re-initialize the minimal symbol reader in case we do.  */

And this one in parse_partial_symbols (also in mdebugread.c):

  /* ECOFF in ELF:

     For ECOFF in ELF, we skip the creation of the minimal symbols.
     The ECOFF symbols should be a subset of the Elf symbols, and the
     section information of the elf symbols will be more accurate.
     FIXME!  What about Irix 5's native linker?

     By default, Elf sections which don't exist in ECOFF
     get put in ECOFF's absolute section by the gnu linker.
     Since absolute sections don't get relocated, we
     end up calculating an address different from that of
     the symbol's minimal symbol (created earlier from the
     Elf symtab).

     To fix this, either :
     1) don't create the duplicate symbol
     (assumes ECOFF symtab is a subset of the ELF symtab;
     assumes no side-effects result from ignoring ECOFF symbol)
     2) create it, only if lookup for existing symbol in ELF's minimal
     symbols fails
     (inefficient;
     assumes no side-effects result from ignoring ECOFF symbol)
     3) create it, but lookup ELF's minimal symbol and use it's section
     during relocation, then modify "uniquify" phase to merge and
     eliminate the duplicate symbol
     (highly inefficient)

     I've implemented #1 here...
     Skip the creation of the minimal symbols based on the ECOFF
     symbol table.  */

I'm thinking that ECOFF is ripe to get removed from GDB, given that it
has been replaced with ELF/DWARF for about 25 years.  That would mean
removing:

 - mdebugread.c
 - mipsread.c

Removing those would allow many more cleanups, I think.

> BTW I meant to approve your patch.
> Approved-By: Tom Tromey <tom@tromey.com>

Ok, so I think that the consequence of my patch is that if you're
parsing ECOFF-in-ELF, then we'll allocate minimal symbols unnecessarily
in mdebugread's minimal_symbol_reader.  They still won't get installed
because of the check in minimal_symbol_reader::install.  They will get
freed when the minimal_symbol_reader gets destroyed.  So that means
slightly higher memory usage for the duration of
elfmdebug_build_psymtabs, but no change in behavior.  I can live with
that, so I'll go ahead and push the patch.

Simon
  
Tom Tromey Dec. 18, 2025, 6:07 p.m. UTC | #4
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon> Indeed, I dug into that in the mean time.  I'd like if someone with
Simon> historical knowledge could fact-check me here.

FWIW I suspect no such person exists.

This stuff is definitely before my time.

Simon> I'm thinking that ECOFF is ripe to get removed from GDB, given that it
Simon> has been replaced with ELF/DWARF for about 25 years.  That would mean
Simon> removing:

Simon>  - mdebugread.c
Simon>  - mipsread.c

Simon> Removing those would allow many more cleanups, I think.

Works for me.

Tom
  
Simon Marchi Dec. 18, 2025, 6:09 p.m. UTC | #5
On 2025-12-18 13:07, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
> 
> Simon> Indeed, I dug into that in the mean time.  I'd like if someone with
> Simon> historical knowledge could fact-check me here.
> 
> FWIW I suspect no such person exists.

Given a lot of this is MIPS-specific, I was hoping that Maciej could be
able to help (adding in CC).

Simon
  
Maciej W. Rozycki Jan. 3, 2026, 11:24 p.m. UTC | #6
On Thu, 18 Dec 2025, Simon Marchi wrote:

> > Simon> Indeed, I dug into that in the mean time.  I'd like if someone with
> > Simon> historical knowledge could fact-check me here.
> > 
> > FWIW I suspect no such person exists.
> 
> Given a lot of this is MIPS-specific, I was hoping that Maciej could be
> able to help (adding in CC).

 I don't know offhand as it's stuff I haven't touched for ages now.  I'll 
see what I can do.  Also I can see you've pushed your change already, so I 
gather there's no rush.  NB it was bad timing to get into this discussion 
as I had an emergency situation to handle and overall hectic time through 
recent weeks.

 Happy New Year for now!

  Maciej
  
Simon Marchi Jan. 4, 2026, 4:09 a.m. UTC | #7
On 2026-01-03 18:24, Maciej W. Rozycki wrote:
> On Thu, 18 Dec 2025, Simon Marchi wrote:
> 
>>> Simon> Indeed, I dug into that in the mean time.  I'd like if someone with
>>> Simon> historical knowledge could fact-check me here.
>>>
>>> FWIW I suspect no such person exists.
>>
>> Given a lot of this is MIPS-specific, I was hoping that Maciej could be
>> able to help (adding in CC).
> 
>  I don't know offhand as it's stuff I haven't touched for ages now.  I'll 
> see what I can do.  Also I can see you've pushed your change already, so I 
> gather there's no rush.  NB it was bad timing to get into this discussion 
> as I had an emergency situation to handle and overall hectic time through 
> recent weeks.
> 
>  Happy New Year for now!

Thanks for replying, hope all is well for you.

I pushed the patch because I convinced myself that the patch wouldn't
break the ECOFF-in-ELF case.  Here is the relevant quote from my
previous message:

	Ok, so I think that the consequence of my patch is that if you're
	parsing ECOFF-in-ELF, then we'll allocate minimal symbols unnecessarily
	in mdebugread's minimal_symbol_reader.  They still won't get installed
	because of the check in minimal_symbol_reader::install.  They will get
	freed when the minimal_symbol_reader gets destroyed.  So that means
	slightly higher memory usage for the duration of
	elfmdebug_build_psymtabs, but no change in behavior.  I can live with
	that, so I'll go ahead and push the patch.

Of course, this is all based on my understanding, from the information I
gleaned here and there.  It seems like not many people remember this era
nowadays :(.

What would help me, if you have time (no rush), is to tell me if we can
reasonably consider the code in mipsread.c (and mdebugread.c, which
seems related) to be obsolete and remove it.

Simon
  
Maciej W. Rozycki Jan. 5, 2026, 8:07 a.m. UTC | #8
On Sat, 3 Jan 2026, Simon Marchi wrote:

> >> Given a lot of this is MIPS-specific, I was hoping that Maciej could be
> >> able to help (adding in CC).
> > 
> >  I don't know offhand as it's stuff I haven't touched for ages now.  I'll 
> > see what I can do.  Also I can see you've pushed your change already, so I 
> > gather there's no rush.  NB it was bad timing to get into this discussion 
> > as I had an emergency situation to handle and overall hectic time through 
> > recent weeks.
> > 
> >  Happy New Year for now!
> 
> Thanks for replying, hope all is well for you.

 I'm fine myself, thank you, just even busier and more distracted than 
usual.

> I pushed the patch because I convinced myself that the patch wouldn't
> break the ECOFF-in-ELF case.  Here is the relevant quote from my
> previous message:
> 
> 	Ok, so I think that the consequence of my patch is that if you're
> 	parsing ECOFF-in-ELF, then we'll allocate minimal symbols unnecessarily
> 	in mdebugread's minimal_symbol_reader.  They still won't get installed
> 	because of the check in minimal_symbol_reader::install.  They will get
> 	freed when the minimal_symbol_reader gets destroyed.  So that means
> 	slightly higher memory usage for the duration of
> 	elfmdebug_build_psymtabs, but no change in behavior.  I can live with
> 	that, so I'll go ahead and push the patch.
> 
> Of course, this is all based on my understanding, from the information I
> gleaned here and there.  It seems like not many people remember this era
> nowadays :(.

 My early MIPS experience certainly overlaps with the era (even MIPS/COFF, 
as in ULTRIX/MIPS), but I never got into the details back then.  At least 
I usually know where to look for when chasing bits now.

 The mdebug spec continues living online I believe, though it could be at
archive.org only nowadays; I can check.  I have a local copy for anyone 
needing it too.  Yes, it does refer Third Eye Software.

> What would help me, if you have time (no rush), is to tell me if we can
> reasonably consider the code in mipsread.c (and mdebugread.c, which
> seems related) to be obsolete and remove it.

 As I say I'll see what I can do.  Overall emitting ECOFF-in-ELF frame 
unwinding information aka Procedure Description Records (PDR), a valuable 
subset of the mdebug stuff, continues being supported by MIPS GCC and GAS.  
No other stuff is relevant anymore; we have no support for IRIX or ULTRIX 
targets left and the GNU tools can't produce other ECOFF debug information 
for MIPS targets anymore.

 NB I had plans/ideas to improve PDR handling in GDB, but this has never 
materialised.  It's good having/improving IMHO as PDR records are very 
lightweight and retained by `strip', and with its variable frame format 
the MIPS target is very bad for debugging when execution is stopped at a 
random place with no associated debug information, which might be libc or 
suchlike.  Then you just have the PC and the register stack available and 
nothing else, not even the return address ($ra may have been clobbered).

 But all the PDR support is gone from GDB AFAICT and ISTR now having a 
discussion as to bringing it back some 20 years ago while I was still at 
MTI, possibly with Daniel Jacobowitz.  The messages should be easy to 
chase, but otherwise I have to conclude none of this is relevant to MIPS 
targets anymore.  So I guess I've figured it out for you already.

 This stuff is possibly used by the Alpha target however, though I'm not 
sure offhand as I'm less familiar with the matters there.

 HTH,

  Maciej
  
Simon Marchi Jan. 5, 2026, 7:05 p.m. UTC | #9
On 2026-01-05 03:07, Maciej W. Rozycki wrote:
> On Sat, 3 Jan 2026, Simon Marchi wrote:
> 
>>>> Given a lot of this is MIPS-specific, I was hoping that Maciej could be
>>>> able to help (adding in CC).
>>>
>>>  I don't know offhand as it's stuff I haven't touched for ages now.  I'll 
>>> see what I can do.  Also I can see you've pushed your change already, so I 
>>> gather there's no rush.  NB it was bad timing to get into this discussion 
>>> as I had an emergency situation to handle and overall hectic time through 
>>> recent weeks.
>>>
>>>  Happy New Year for now!
>>
>> Thanks for replying, hope all is well for you.
> 
>  I'm fine myself, thank you, just even busier and more distracted than 
> usual.
> 
>> I pushed the patch because I convinced myself that the patch wouldn't
>> break the ECOFF-in-ELF case.  Here is the relevant quote from my
>> previous message:
>>
>> 	Ok, so I think that the consequence of my patch is that if you're
>> 	parsing ECOFF-in-ELF, then we'll allocate minimal symbols unnecessarily
>> 	in mdebugread's minimal_symbol_reader.  They still won't get installed
>> 	because of the check in minimal_symbol_reader::install.  They will get
>> 	freed when the minimal_symbol_reader gets destroyed.  So that means
>> 	slightly higher memory usage for the duration of
>> 	elfmdebug_build_psymtabs, but no change in behavior.  I can live with
>> 	that, so I'll go ahead and push the patch.
>>
>> Of course, this is all based on my understanding, from the information I
>> gleaned here and there.  It seems like not many people remember this era
>> nowadays :(.
> 
>  My early MIPS experience certainly overlaps with the era (even MIPS/COFF, 
> as in ULTRIX/MIPS), but I never got into the details back then.  At least 
> I usually know where to look for when chasing bits now.
> 
>  The mdebug spec continues living online I believe, though it could be at
> archive.org only nowadays; I can check.  I have a local copy for anyone 
> needing it too.  Yes, it does refer Third Eye Software.

I dug a bit deeper and found these links.  The last one is especially
useful to understand the history.

ECOFF spec
  https://web.archive.org/web/20160305114748/http://h41361.www4.hp.com/docs/base_doc/DOCUMENTATION/V50A_ACRO_SUP/OBJSPEC.PDF

mdebug, on David Anderson's page
  https://www.prevanders.net/#mdebug

mdebug spec (at least some version of it)
  https://www.prevanders.net/Mdebug.ps

Note from Peter Rowell about mdebug
  http://www.datahedron.com/mips.html
  https://www.prevanders.net/mdebug.html (mirror)

>> What would help me, if you have time (no rush), is to tell me if we can
>> reasonably consider the code in mipsread.c (and mdebugread.c, which
>> seems related) to be obsolete and remove it.
> 
>  As I say I'll see what I can do.  Overall emitting ECOFF-in-ELF frame 
> unwinding information aka Procedure Description Records (PDR), a valuable 
> subset of the mdebug stuff, continues being supported by MIPS GCC and GAS.  
> No other stuff is relevant anymore; we have no support for IRIX or ULTRIX 
> targets left and the GNU tools can't produce other ECOFF debug information 
> for MIPS targets anymore.
> 
>  NB I had plans/ideas to improve PDR handling in GDB, but this has never 
> materialised.  It's good having/improving IMHO as PDR records are very 
> lightweight and retained by `strip', and with its variable frame format 
> the MIPS target is very bad for debugging when execution is stopped at a 
> random place with no associated debug information, which might be libc or 
> suchlike.  Then you just have the PC and the register stack available and 
> nothing else, not even the return address ($ra may have been clobbered).
> 
>  But all the PDR support is gone from GDB AFAICT and ISTR now having a 
> discussion as to bringing it back some 20 years ago while I was still at 
> MTI, possibly with Daniel Jacobowitz.  The messages should be easy to 
> chase, but otherwise I have to conclude none of this is relevant to MIPS 
> targets anymore.  So I guess I've figured it out for you already.

Ok, thanks for the precious information.

>  This stuff is possibly used by the Alpha target however, though I'm not 
> sure offhand as I'm less familiar with the matters there.

I am mostly convinced that none of this is relevant anymore.  And if it
ever became relevant anymore for some reason, I think it would be better
to just start from scratch, given how much this has bit-rotten.

Simon
  
Tom Tromey Jan. 5, 2026, 7:17 p.m. UTC | #10
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon> I am mostly convinced that none of this is relevant anymore.  And if it
Simon> ever became relevant anymore for some reason, I think it would be better
Simon> to just start from scratch, given how much this has bit-rotten.

+1 to that

Tom
  

Patch

diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 70f5f61748a6..1b1e43845778 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -143,17 +143,6 @@  msymbol_is_function (struct objfile *objfile, minimal_symbol *minsym,
     }
 }
 
-/* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
-   At the end, copy them all into one newly allocated array.  */
-
-#define BUNCH_SIZE 127
-
-struct msym_bunch
-  {
-    struct msym_bunch *next;
-    struct minimal_symbol contents[BUNCH_SIZE];
-  };
-
 /* See minsyms.h.  */
 
 unsigned int
@@ -1087,32 +1076,10 @@  get_symbol_leading_char (program_space *pspace, bfd *abfd)
 /* See minsyms.h.  */
 
 minimal_symbol_reader::minimal_symbol_reader (struct objfile *obj)
-: m_objfile (obj),
-  m_msym_bunch (NULL),
-  /* Note that presetting m_msym_bunch_index to BUNCH_SIZE causes the
-     first call to save a minimal symbol to allocate the memory for
-     the first bunch.  */
-  m_msym_bunch_index (BUNCH_SIZE),
-  m_msym_count (0)
+  : m_objfile (obj)
 {
 }
 
-/* Discard the currently collected minimal symbols, if any.  If we wish
-   to save them for later use, we must have already copied them somewhere
-   else before calling this function.  */
-
-minimal_symbol_reader::~minimal_symbol_reader ()
-{
-  struct msym_bunch *next;
-
-  while (m_msym_bunch != NULL)
-    {
-      next = m_msym_bunch->next;
-      xfree (m_msym_bunch);
-      m_msym_bunch = next;
-    }
-}
-
 /* See minsyms.h.  */
 
 void
@@ -1180,9 +1147,6 @@  minimal_symbol_reader::record_full (std::string_view name,
 				    enum minimal_symbol_type ms_type,
 				    int section)
 {
-  struct msym_bunch *newobj;
-  struct minimal_symbol *msymbol;
-
   /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into
      the minimal symbols, because if there is also another symbol
      at the same address (e.g. the first function of the file),
@@ -1207,14 +1171,7 @@  minimal_symbol_reader::record_full (std::string_view name,
 				hex_string (LONGEST (address)),
 				section, (int) name.size (), name.data ());
 
-  if (m_msym_bunch_index == BUNCH_SIZE)
-    {
-      newobj = XCNEW (struct msym_bunch);
-      m_msym_bunch_index = 0;
-      newobj->next = m_msym_bunch;
-      m_msym_bunch = newobj;
-    }
-  msymbol = &m_msym_bunch->contents[m_msym_bunch_index];
+  minimal_symbol *msymbol = &m_msyms.emplace_back ();
   msymbol->set_language (language_unknown,
 			 &m_objfile->per_bfd->storage_obstack);
 
@@ -1226,17 +1183,13 @@  minimal_symbol_reader::record_full (std::string_view name,
 
   msymbol->set_unrelocated_address (address);
   msymbol->set_section_index (section);
-
   msymbol->set_type (ms_type);
 
   /* If we already read minimal symbols for this objfile, then don't
      ever allocate a new one.  */
   if (!m_objfile->per_bfd->minsyms_read)
-    {
-      m_msym_bunch_index++;
-      m_objfile->per_bfd->n_minsyms++;
-    }
-  m_msym_count++;
+    m_objfile->per_bfd->n_minsyms++;
+
   return msymbol;
 }
 
@@ -1465,59 +1418,41 @@  class minimal_symbol_install_worker
 void
 minimal_symbol_reader::install ()
 {
-  int mcount;
-  struct msym_bunch *bunch;
-  struct minimal_symbol *msymbols;
-  int alloc_count;
-
   if (m_objfile->per_bfd->minsyms_read)
     return;
 
-  if (m_msym_count > 0)
+  if (!m_msyms.empty ())
     {
-      symtab_create_debug_printf ("installing %d minimal symbols of objfile %s",
-				  m_msym_count, objfile_name (m_objfile));
+      symtab_create_debug_printf ("installing %zu minimal symbols of objfile %s",
+				  m_msyms.size (), objfile_name (m_objfile));
 
       /* Allocate enough space, into which we will gather the bunches
 	 of new and existing minimal symbols, sort them, and then
 	 compact out the duplicate entries.  Once we have a final
 	 table, we will give back the excess space.  */
-
-      alloc_count = m_msym_count + m_objfile->per_bfd->minimal_symbol_count;
+      int alloc_count
+	= m_msyms.size () + m_objfile->per_bfd->minimal_symbol_count;
       gdb::unique_xmalloc_ptr<minimal_symbol>
 	msym_holder (XNEWVEC (minimal_symbol, alloc_count));
-      msymbols = msym_holder.get ();
+      minimal_symbol *msymbols = msym_holder.get ();
 
       /* Copy in the existing minimal symbols, if there are any.  */
-
       if (m_objfile->per_bfd->minimal_symbol_count)
 	memcpy (msymbols, m_objfile->per_bfd->msymbols.get (),
 		m_objfile->per_bfd->minimal_symbol_count
 		* sizeof (struct minimal_symbol));
 
-      /* Walk through the list of minimal symbol bunches, adding each symbol
-	 to the new contiguous array of symbols.  Note that we start with the
-	 current, possibly partially filled bunch (thus we use the current
-	 msym_bunch_index for the first bunch we copy over), and thereafter
-	 each bunch is full.  */
-
-      mcount = m_objfile->per_bfd->minimal_symbol_count;
-
-      for (bunch = m_msym_bunch; bunch != NULL; bunch = bunch->next)
-	{
-	  memcpy (&msymbols[mcount], &bunch->contents[0],
-		  m_msym_bunch_index * sizeof (struct minimal_symbol));
-	  mcount += m_msym_bunch_index;
-	  m_msym_bunch_index = BUNCH_SIZE;
-	}
+      /* Walk through the list of recorded minimal symbol, adding each symbol
+	 to the new contiguous array of symbols.  */
+      int mcount = m_objfile->per_bfd->minimal_symbol_count;
+      std::copy (m_msyms.begin (), m_msyms.end (), &msymbols[mcount]);
+      mcount += m_msyms.size ();
 
       /* Sort the minimal symbols by address.  */
-
       std::sort (msymbols, msymbols + mcount, minimal_symbol_is_less_than);
 
       /* Compact out any duplicates, and free up whatever space we are
 	 no longer using.  */
-
       mcount = compact_minimal_symbols (msymbols, mcount, m_objfile);
       msym_holder.reset (XRESIZEVEC (struct minimal_symbol,
 				     msym_holder.release (),
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index ed38044a38c6..3467d5dc8d95 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -20,6 +20,8 @@ 
 #ifndef GDB_MINSYMS_H
 #define GDB_MINSYMS_H
 
+#include <deque>
+
 struct program_space;
 struct type;
 
@@ -78,8 +80,6 @@  struct bound_minimal_symbol
    as opaque and use functions provided by minsyms.c to inspect them.
 */
 
-struct msym_bunch;
-
 /* An RAII-based object that is used to record minimal symbols while
    they are being read.  */
 class minimal_symbol_reader
@@ -92,8 +92,6 @@  class minimal_symbol_reader
 
   explicit minimal_symbol_reader (struct objfile *);
 
-  ~minimal_symbol_reader ();
-
   /* Install the minimal symbols that have been collected into the
      given objfile.  */
 
@@ -154,19 +152,10 @@  class minimal_symbol_reader
 
   struct objfile *m_objfile;
 
-  /* Bunch currently being filled up.
-     The next field points to chain of filled bunches.  */
-
-  struct msym_bunch *m_msym_bunch;
-
-  /* Number of slots filled in current bunch.  */
-
-  int m_msym_bunch_index;
-
-  /* Total number of minimal symbols recorded so far for the
-     objfile.  */
-
-  int m_msym_count;
+  /* The minimal symbols recorded so far.  This uses a deque instead of e.g. a
+     vector, because references to minimal symbols need to stay valid across
+     calls to recod_full.  */
+  std::deque<minimal_symbol> m_msyms;
 };