summaryrefslogtreecommitdiff
path: root/toolchain/binutils/2.17/502-avr32-fix-got-refcount.patch
blob: d9dc0ffad05c43c056289091609e4c1fba279c7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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 *)