diff options
Diffstat (limited to 'toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch')
-rw-r--r-- | toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch b/toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch new file mode 100644 index 000000000..d9dc0ffad --- /dev/null +++ b/toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch @@ -0,0 +1,78 @@ +--- 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 *) |