PR3532: adding syms during bfd_hash_traverse

Alan Modra amodra@bigpond.net.au
Mon Nov 20 01:37:00 GMT 2006


Growing a hash table during a traversal breaks things quite badly.

	PR 3532
	* bfd-in.h (struct bfd_hash_table): Reorganize.  Add "frozen".
	* hash.c (bfd_hash_table_init_n): Init frozen.
	(bfd_hash_lookup): Don't grow if frozen.
	(bfd_hash_traverse): Freeze hash table during traversal.

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.120
diff -u -p -r1.120 bfd-in.h
--- bfd/bfd-in.h	13 Nov 2006 20:39:21 -0000	1.120
+++ bfd/bfd-in.h	20 Nov 2006 01:25:09 -0000
@@ -398,12 +398,6 @@ struct bfd_hash_table
 {
   /* The hash array.  */
   struct bfd_hash_entry **table;
-  /* The number of slots in the hash table.  */
-  unsigned int size;
-  /* The number of entries in the hash table.  */
-  unsigned int count;
-  /* The size of elements.  */
-  unsigned int entsize;
   /* A function used to create new elements in the hash table.  The
      first entry is itself a pointer to an element.  When this
      function is first invoked, this pointer will be NULL.  However,
@@ -416,6 +410,14 @@ struct bfd_hash_table
    /* An objalloc for this hash table.  This is a struct objalloc *,
      but we use void * to avoid requiring the inclusion of objalloc.h.  */
   void *memory;
+  /* The number of slots in the hash table.  */
+  unsigned int size;
+  /* The number of entries in the hash table.  */
+  unsigned int count;
+  /* The size of elements.  */
+  unsigned int entsize;
+  /* If non-zero, don't grow the hash table.  */
+  unsigned int frozen:1;
 };
 
 /* Initialize a hash table.  */
Index: bfd/hash.c
===================================================================
RCS file: /cvs/src/src/bfd/hash.c,v
retrieving revision 1.23
diff -u -p -r1.23 hash.c
--- bfd/hash.c	6 Jun 2006 03:04:12 -0000	1.23
+++ bfd/hash.c	20 Nov 2006 01:25:14 -0000
@@ -383,6 +383,7 @@ bfd_hash_table_init_n (struct bfd_hash_t
   table->size = size;
   table->entsize = entsize;
   table->count = 0;
+  table->frozen = 0;
   table->newfunc = newfunc;
   return TRUE;
 }
@@ -471,7 +472,7 @@ bfd_hash_lookup (struct bfd_hash_table *
   table->table[index] = hashp;
   table->count++;
 
-  if (table->count > table->size * 3 / 4)
+  if (!table->frozen && table->count > table->size * 3 / 4)
     {
       unsigned long newsize = higher_prime_number (table->size);
       struct bfd_hash_entry **newtable;
@@ -482,8 +483,7 @@ bfd_hash_lookup (struct bfd_hash_table *
 	 that much memory, don't try to grow the table.  */
       if (newsize == 0 || alloc / sizeof (struct bfd_hash_entry *) != newsize)
 	{
-	  /* Lie.  Stops us trying to grow again for a while.  */
-	  table->count = 0;
+	  table->frozen = 1;
 	  return hashp;
 	}
 
@@ -573,14 +573,17 @@ bfd_hash_traverse (struct bfd_hash_table
 {
   unsigned int i;
 
+  table->frozen = 1;
   for (i = 0; i < table->size; i++)
     {
       struct bfd_hash_entry *p;
 
       for (p = table->table[i]; p != NULL; p = p->next)
 	if (! (*func) (p, info))
-	  return;
+	  goto out;
     }
+ out:
+  table->frozen = 0;
 }
 
 void

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list