--- a/bfd/elf32-avr32.c 2008-02-29 08:20:57.000000000 -0500 +++ b/bfd/elf32-avr32.c 2008-02-29 08:26:01.000000000 -0500 @@ -247,7 +247,7 @@ avr32_elf_link_hash_table_create(bfd *ab GOT. If we ever get more than this many references to the same symbol, we may need to do something special. */ -#define MAX_NR_GOT_HOLES 8192 +#define MAX_NR_GOT_HOLES 2048 /* AVR32 GOT entry. We need to keep track of refcounts and offsets @@ -916,16 +916,21 @@ avr32_elf_size_dynamic_sections (bfd *ou static void insert_got_entry(struct elf_avr32_link_hash_table *htab, struct got_entry *got) { - /* TODO: Support got_refcount > htab->nr_got_holes by using a - different sort algorithm for those. */ - BFD_ASSERT(got->refcount <= htab->nr_got_holes); + /* Any entries with got_refcount > htab->nr_got_holes end up in the + * last pigeonhole without any sorting. We expect the number of such + * entries to be small, so it is very unlikely to affect + * performance. */ + int entry = got->refcount; - got->pprev = &htab->got_hole[got->refcount]; - got->next = htab->got_hole[got->refcount]; + if (entry > htab->nr_got_holes) + entry = htab->nr_got_holes; + + got->pprev = &htab->got_hole[entry]; + got->next = htab->got_hole[entry]; if (got->next) got->next->pprev = &got->next; - htab->got_hole[got->refcount] = got; + htab->got_hole[entry] = got; } /* Decrement the refcount of a GOT entry and update its position in @@ -933,7 +938,6 @@ insert_got_entry(struct elf_avr32_link_h static void unref_got_entry(struct elf_avr32_link_hash_table *htab, struct got_entry *got) { - BFD_ASSERT(got->refcount <= htab->nr_got_holes); BFD_ASSERT(got->refcount > 0); if (got->next) @@ -955,7 +959,6 @@ ref_got_entry(struct elf_avr32_link_hash insert_got_entry(htab, got); BFD_ASSERT(got->refcount > 0); - BFD_ASSERT(got->refcount <= htab->nr_got_holes); } /* Assign offsets to all GOT entries we intend to keep. The entries @@ -1106,13 +1109,17 @@ avr32_elf_size_dynamic_sections (bfd *ou { /* Allocate holes for the pigeonhole sort algorithm */ pr_debug("Highest GOT refcount: %d\n", htab->nr_got_holes); + + /* Limit the memory usage by clipping the number of pigeonholes + * at a predefined maximum. All entries with a higher refcount + * will end up in the last pigeonhole. */ + if (htab->nr_got_holes >= MAX_NR_GOT_HOLES) { - /* TODO: Do something clever (different sorting algorithm) */ - _bfd_error_handler(_("Highest refcount %d too high (max %d)\n"), - htab->nr_got_holes, MAX_NR_GOT_HOLES); - bfd_set_error(bfd_error_no_memory); - return FALSE; + htab->nr_got_holes = MAX_NR_GOT_HOLES - 1; + + pr_debug("Limiting maximum number of GOT pigeonholes to %u\n", + htab->nr_got_holes); } htab->got_hole = bfd_zalloc(output_bfd, sizeof(struct got_entry *)