This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PR3532: adding syms during bfd_hash_traverse
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sourceware dot org
- Date: Mon, 20 Nov 2006 12:07:21 +1030
- Subject: PR3532: adding syms during bfd_hash_traverse
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