summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schlemmer <azarah@gentoo.org>2003-09-13 20:14:17 +0000
committerMartin Schlemmer <azarah@gentoo.org>2003-09-13 20:14:17 +0000
commit44002c6d5b560296f4a931bed3ba21cf14df4b8f (patch)
treed18d20b40fe5ff9d57ab0a6d9dc8557a19ae5d0f /sys-devel/binutils/files
parentAdd patch to speedup C++ linking (diff)
downloadgentoo-2-44002c6d5b560296f4a931bed3ba21cf14df4b8f.tar.gz
gentoo-2-44002c6d5b560296f4a931bed3ba21cf14df4b8f.tar.bz2
gentoo-2-44002c6d5b560296f4a931bed3ba21cf14df4b8f.zip
Add patch to speedup C++ linking
Diffstat (limited to 'sys-devel/binutils/files')
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-cxx-speedup.patch882
-rw-r--r--sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r31
2 files changed, 883 insertions, 0 deletions
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-cxx-speedup.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-cxx-speedup.patch
new file mode 100644
index 000000000000..9ae5d51e223c
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-cxx-speedup.patch
@@ -0,0 +1,882 @@
+*** ./ld/mri.c 2003-07-23 12:08:12.000000000 -0300
+--- ./ld/mri.c.new 2003-09-04 11:44:00.000000000 -0300
+***************
+*** 227,232 ****
+--- 227,233 ----
+ tmp->spec.name = p->name;
+ tmp->spec.exclude_name_list = NULL;
+ tmp->spec.sorted = FALSE;
++ tmp->spec.wildcard_p = wildcardp( p->name );
+ lang_add_wild (NULL, tmp, FALSE);
+
+ /* If there is an alias for this section, add it too. */
+***************
+*** 238,243 ****
+--- 239,245 ----
+ tmp->spec.name = aptr->name;
+ tmp->spec.exclude_name_list = NULL;
+ tmp->spec.sorted = FALSE;
++ tmp->spec.wildcard_p = wildcardp( aptr->name );
+ lang_add_wild (NULL, tmp, FALSE);
+ }
+
+*** ./ld/ld.h 2003-07-23 12:08:12.000000000 -0300
+--- ./ld/ld.h.new 2003-09-04 11:59:57.000000000 -0300
+***************
+*** 71,76 ****
+--- 71,77 ----
+ const char *name;
+ struct name_list *exclude_name_list;
+ bfd_boolean sorted;
++ bfd_boolean wildcard_p;
+ };
+
+ struct wildcard_list {
+*** ./ld/ldgram.y 2003-08-21 12:28:48.000000000 -0300
+--- ./ld/ldgram.y.new 2003-09-04 11:58:56.000000000 -0300
+***************
+*** 411,434 ****
+--- 411,438 ----
+ $$.name = $1;
+ $$.sorted = FALSE;
+ $$.exclude_name_list = NULL;
++ $$.wildcard_p = wildcardp($1);
+ }
+ | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
+ {
+ $$.name = $5;
+ $$.sorted = FALSE;
+ $$.exclude_name_list = $3;
++ $$.wildcard_p = wildcardp($5);
+ }
+ | SORT '(' wildcard_name ')'
+ {
+ $$.name = $3;
+ $$.sorted = TRUE;
+ $$.exclude_name_list = NULL;
++ $$.wildcard_p = wildcardp($3);
+ }
+ | SORT '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
+ {
+ $$.name = $7;
+ $$.sorted = TRUE;
+ $$.exclude_name_list = $5;
++ $$.wildcard_p = wildcardp($7);
+ }
+ ;
+
+***************
+*** 479,484 ****
+--- 483,489 ----
+ tmp.name = $1;
+ tmp.exclude_name_list = NULL;
+ tmp.sorted = FALSE;
++ tmp.wildcard_p = wildcardp($1);
+ lang_add_wild (&tmp, NULL, ldgram_had_keep);
+ }
+ | '[' file_NAME_list ']'
+*** ./ld/ldlang.c 2003-08-21 12:28:48.000000000 -0300
+--- ./ld/ldlang.c.new 2003-09-04 11:56:26.000000000 -0300
+***************
+*** 63,69 ****
+
+ /* Forward declarations. */
+ static void exp_init_os (etree_type *);
+- static bfd_boolean wildcardp (const char *);
+ static lang_input_statement_type *lookup_name (const char *);
+ static bfd_boolean load_symbols (lang_input_statement_type *,
+ lang_statement_list_type *);
+--- 63,68 ----
+***************
+*** 191,197 ****
+ {
+ const char *sname = bfd_get_section_name (file->the_bfd, s);
+
+! if (wildcardp (sec->spec.name))
+ skip = fnmatch (sec->spec.name, sname, 0) != 0;
+ else
+ skip = strcmp (sec->spec.name, sname) != 0;
+--- 190,196 ----
+ {
+ const char *sname = bfd_get_section_name (file->the_bfd, s);
+
+! if ( sec->spec.wildcard_p )
+ skip = fnmatch (sec->spec.name, sname, 0) != 0;
+ else
+ skip = strcmp (sec->spec.name, sname) != 0;
+***************
+*** 954,960 ****
+ be enough to cause the pattern to be treated as a wildcard.
+ That lets us handle DOS filenames more naturally. */
+
+! static bfd_boolean
+ wildcardp (const char *pattern)
+ {
+ const char *s;
+--- 953,959 ----
+ be enough to cause the pattern to be treated as a wildcard.
+ That lets us handle DOS filenames more naturally. */
+
+! bfd_boolean
+ wildcardp (const char *pattern)
+ {
+ const char *s;
+***************
+*** 4182,4191 ****
+
+ if (filespec != NULL && filespec->name != NULL)
+ {
+! if (strcmp (filespec->name, "*") == 0)
+ filespec->name = NULL;
+! else if (! wildcardp (filespec->name))
+! lang_has_input_file = TRUE;
+ }
+
+ new = new_stat (lang_wild_statement, stat_ptr);
+--- 4181,4192 ----
+
+ if (filespec != NULL && filespec->name != NULL)
+ {
+!
+! if (strcmp (filespec->name, "*") == 0) {
+! filespec->wildcard_p = FALSE;
+ filespec->name = NULL;
+! } else if (! filespec->wildcard_p )
+! lang_has_input_file = TRUE;
+ }
+
+ new = new_stat (lang_wild_statement, stat_ptr);
+*** ./ld/ldlang.h 2003-08-21 12:28:48.000000000 -0300
+--- ./ld/ldlang.h.new 2003-09-04 11:51:29.000000000 -0300
+***************
+*** 407,412 ****
+--- 407,414 ----
+ (const char *);
+ extern void lang_add_wild
+ (struct wildcard_spec *, struct wildcard_list *, bfd_boolean);
++ extern bfd_boolean wildcardp
++ PARAMS ((const char *));
+ extern void lang_add_map
+ (const char *);
+ extern void lang_add_fill
+*** ./bfd/elflink.h 2003-08-21 12:28:48.000000000 -0300
+--- ./bfd/elflink.h.new 2003-09-04 13:12:40.000000000 -0300
+***************
+*** 1488,1500 ****
+ assembler code, handling it correctly would be very time
+ consuming, and other ELF linkers don't handle general aliasing
+ either. */
+ while (weaks != NULL)
+ {
+ struct elf_link_hash_entry *hlook;
+ asection *slook;
+ bfd_vma vlook;
+! struct elf_link_hash_entry **hpp;
+! struct elf_link_hash_entry **hppend;
+
+ hlook = weaks;
+ weaks = hlook->weakdef;
+--- 1488,1539 ----
+ assembler code, handling it correctly would be very time
+ consuming, and other ELF linkers don't handle general aliasing
+ either. */
++ {
++ #define HASH(h) (((h->root.u.def.value >> 3) ^ \
++ (h->root.u.def.section->target_index<<10))%(4*extsymcount))
++ struct hashentry {
++ struct elf_link_hash_entry *h;
++ struct hashentry *next;
++ };
++ struct hashentry *array;
++ struct elf_link_hash_entry **hpp;
++ struct elf_link_hash_entry **hppend;
++
++ array = (struct hashentry *) malloc(extsymcount*4*sizeof(struct hashentry));
++ memset(array, 0, extsymcount*4*sizeof(struct hashentry));
++
++ hpp = elf_sym_hashes (abfd);
++ hppend = hpp + extsymcount;
++ for (; hpp < hppend; hpp++)
++ {
++ unsigned int hash;
++ struct elf_link_hash_entry *h = *hpp;
++
++ if (!h || h->root.type != bfd_link_hash_defined)
++ continue;
++
++ hash = HASH(h);
++
++ if (!array[hash].h) {
++ array[hash].h = h;
++ } else {
++ struct hashentry *p = array + hash;
++ while (p->next)
++ p = p->next;
++ p->next = (struct hashentry *) malloc(sizeof(struct hashentry));
++ p->next->h = h;
++ p->next->next = 0;
++ }
++ }
++
++
+ while (weaks != NULL)
+ {
+ struct elf_link_hash_entry *hlook;
+ asection *slook;
+ bfd_vma vlook;
+! unsigned int hash;
+! struct hashentry *entry;
+
+ hlook = weaks;
+ weaks = hlook->weakdef;
+***************
+*** 1504,1525 ****
+ || hlook->root.type == bfd_link_hash_defweak
+ || hlook->root.type == bfd_link_hash_common
+ || hlook->root.type == bfd_link_hash_indirect);
+ slook = hlook->root.u.def.section;
+ vlook = hlook->root.u.def.value;
+
+! hpp = elf_sym_hashes (abfd);
+! hppend = hpp + extsymcount;
+! for (; hpp < hppend; hpp++)
+! {
+! struct elf_link_hash_entry *h;
+!
+! h = *hpp;
+! if (h != NULL && h != hlook
+! && h->root.type == bfd_link_hash_defined
+! && h->root.u.def.section == slook
+! && h->root.u.def.value == vlook)
+! {
+! hlook->weakdef = h;
+
+ /* If the weak definition is in the list of dynamic
+ symbols, make sure the real definition is put there
+--- 1543,1561 ----
+ || hlook->root.type == bfd_link_hash_defweak
+ || hlook->root.type == bfd_link_hash_common
+ || hlook->root.type == bfd_link_hash_indirect);
++ hash = HASH( hlook );
+ slook = hlook->root.u.def.section;
+ vlook = hlook->root.u.def.value;
+
+! entry = array + hash;
+! while (entry && entry->h)
+! {
+! struct elf_link_hash_entry *h = entry->h;
+! if (h != hlook
+! && h->root.u.def.section == slook
+! && h->root.u.def.value == vlook)
+! {
+! hlook->weakdef = h;
+
+ /* If the weak definition is in the list of dynamic
+ symbols, make sure the real definition is put there
+***************
+*** 1544,1549 ****
+--- 1580,1600 ----
+ }
+ break;
+ }
++ entry = entry->next;
++ }
++ }
++ {
++ unsigned int i;
++ for (i = 0; i < 4*extsymcount; ++i) {
++ struct hashentry *h = array[i].next;
++ while (h) {
++ struct hashentry *n = h->next;
++ free(h);
++ h = n;
++ }
++ }
++ free(array);
++
+ }
+ }
+
+*** ./bfd/merge.c 2002-12-16 18:22:52.000000000 -0200
+--- ./bfd/merge.c.new 2003-09-04 12:11:12.000000000 -0300
+***************
+*** 108,119 ****
+ struct sec_merge_sec_info *));
+ static bfd_boolean sec_merge_emit
+ PARAMS ((bfd *, struct sec_merge_hash_entry *));
+! static int cmplengthentry
+! PARAMS ((const PTR, const PTR));
+! static int last4_eq
+! PARAMS ((const PTR, const PTR));
+! static int last_eq
+! PARAMS ((const PTR, const PTR));
+ static bfd_boolean record_section
+ PARAMS ((struct sec_merge_info *, struct sec_merge_sec_info *));
+ static void merge_strings
+--- 108,117 ----
+ struct sec_merge_sec_info *));
+ static bfd_boolean sec_merge_emit
+ PARAMS ((bfd *, struct sec_merge_hash_entry *));
+!
+! static int strrevcmp PARAMS ((const PTR, const PTR));
+! static int is_suffix PARAMS ((const struct sec_merge_hash_entry *,
+! const struct sec_merge_hash_entry *));
+ static bfd_boolean record_section
+ PARAMS ((struct sec_merge_info *, struct sec_merge_sec_info *));
+ static void merge_strings
+***************
+*** 457,539 ****
+ return FALSE;
+ }
+
+! /* Compare two sec_merge_hash_entry structures. This is called via qsort. */
+!
+! static int
+! cmplengthentry (a, b)
+ const PTR a;
+ const PTR b;
+ {
+ struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
+ struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
+
+- if (A->len < B->len)
+- return 1;
+- else if (A->len > B->len)
+- return -1;
+-
+- return memcmp (A->root.string, B->root.string, A->len);
+- }
+-
+- static int
+- last4_eq (a, b)
+- const PTR a;
+- const PTR b;
+- {
+- struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
+- struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
+-
+- if (memcmp (A->root.string + A->len - 5 * A->u.entsize,
+- B->root.string + B->len - 5 * A->u.entsize,
+- 4 * A->u.entsize) != 0)
+- /* This was a hashtable collision. */
+- return 0;
+-
+- if (A->len <= B->len)
+- /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+- not to be equal by the hash table. */
+- return 0;
+-
+- if (A->alignment < B->alignment
+- || ((A->len - B->len) & (B->alignment - 1)))
+- /* The suffix is not sufficiently aligned. */
+- return 0;
+-
+- return memcmp (A->root.string + (A->len - B->len),
+- B->root.string, B->len - 5 * A->u.entsize) == 0;
+- }
+-
+- static int
+- last_eq (a, b)
+- const PTR a;
+- const PTR b;
+- {
+- struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
+- struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
+-
+- if (B->len >= 5 * A->u.entsize)
+- /* Longer strings are just pushed into the hash table,
+- they'll be used when looking up for very short strings. */
+- return 0;
+-
+- if (memcmp (A->root.string + A->len - 2 * A->u.entsize,
+- B->root.string + B->len - 2 * A->u.entsize,
+- A->u.entsize) != 0)
+- /* This was a hashtable collision. */
+- return 0;
+-
+- if (A->len <= B->len)
+- /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+- not to be equal by the hash table. */
+- return 0;
+-
+- if (A->alignment < B->alignment
+- || ((A->len - B->len) & (B->alignment - 1)))
+- /* The suffix is not sufficiently aligned. */
+- return 0;
+-
+- return memcmp (A->root.string + (A->len - B->len),
+- B->root.string, B->len - 2 * A->u.entsize) == 0;
+ }
+
+ /* Record one section into the hash table. */
+--- 456,481 ----
+ return FALSE;
+ }
+
+! static int strrevcmp(a, b)
+ const PTR a;
+ const PTR b;
+ {
+ struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
+ struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
++ const unsigned char *s = A->root.string + A->len - A->u.entsize;
++ const unsigned char *t = B->root.string + B->len - B->u.entsize;
++ int l = A->len < B->len ? A->len : B->len;
++
++ l -= (A->u.entsize - 1);
++ while (l) {
++ if (*s != *t)
++ return (int)*s - (int)*t;
++ s--;
++ t--;
++ l--;
++ }
++ return A->len - B->len;
+
+ }
+
+ /* Record one section into the hash table. */
+***************
+*** 620,625 ****
+--- 562,581 ----
+ return FALSE;
+ }
+
++ static int is_suffix(A, B)
++ const struct sec_merge_hash_entry *A;
++ const struct sec_merge_hash_entry *B;
++ {
++ if (A->len <= B->len)
++ /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
++ not to be equal by the hash table. */
++ return 0;
++
++ return memcmp (A->root.string + (A->len - B->len),
++ B->root.string, B->len - 1 * A->u.entsize) == 0;
++ }
++
++
+ /* This is a helper function for _bfd_merge_sections. It attempts to
+ merge strings matching suffixes of longer strings. */
+ static void
+***************
+*** 628,637 ****
+ {
+ struct sec_merge_hash_entry **array, **a, **end, *e;
+ struct sec_merge_sec_info *secinfo;
+- htab_t lasttab = NULL, last4tab = NULL;
+ bfd_size_type size, amt;
+
+! /* Now sort the strings by length, longest first. */
+ array = NULL;
+ amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
+ array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
+--- 584,592 ----
+ {
+ struct sec_merge_hash_entry **array, **a, **end, *e;
+ struct sec_merge_sec_info *secinfo;
+ bfd_size_type size, amt;
+
+! /* Now sort the strings */
+ array = NULL;
+ amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
+ array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
+***************
+*** 644,729 ****
+
+ sinfo->htab->size = a - array;
+
+- qsort (array, (size_t) sinfo->htab->size,
+- sizeof (struct sec_merge_hash_entry *), cmplengthentry);
+-
+- last4tab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
+- NULL, last4_eq, NULL, calloc, free);
+- lasttab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
+- NULL, last_eq, NULL, calloc, free);
+- if (lasttab == NULL || last4tab == NULL)
+- goto alloc_failure;
+-
+- /* Now insert the strings into hash tables (strings with last 4 characters
+- and strings with last character equal), look for longer strings which
+- we're suffix of. */
+ for (a = array, end = array + sinfo->htab->size; a < end; a++)
+ {
+- register hashval_t hash;
+- unsigned int c;
+- unsigned int i;
+- const unsigned char *s;
+- PTR *p;
+-
+ e = *a;
+ e->u.entsize = sinfo->htab->entsize;
+! if (e->len <= e->u.entsize)
+! break;
+! if (e->len > 4 * e->u.entsize)
+! {
+! s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
+! hash = 0;
+! for (i = 0; i < 4 * e->u.entsize; i++)
+! {
+! c = *--s;
+! hash += c + (c << 17);
+! hash ^= hash >> 2;
+! }
+! p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
+! if (p == NULL)
+! goto alloc_failure;
+! if (*p)
+! {
+! struct sec_merge_hash_entry *ent;
+
+- ent = (struct sec_merge_hash_entry *) *p;
+- e->u.suffix = ent;
+- e->alignment = 0;
+- continue;
+- }
+- else
+- *p = (PTR) e;
+- }
+- s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
+- hash = 0;
+- for (i = 0; i < e->u.entsize; i++)
+- {
+- c = *--s;
+- hash += c + (c << 17);
+- hash ^= hash >> 2;
+- }
+- p = htab_find_slot_with_hash (lasttab, e, hash, INSERT);
+- if (p == NULL)
+- goto alloc_failure;
+- if (*p)
+- {
+- struct sec_merge_hash_entry *ent;
+
+! ent = (struct sec_merge_hash_entry *) *p;
+! e->u.suffix = ent;
+! e->alignment = 0;
+ }
+- else
+- *p = (PTR) e;
+ }
+
+ alloc_failure:
+ if (array)
+ free (array);
+- if (lasttab)
+- htab_delete (lasttab);
+- if (last4tab)
+- htab_delete (last4tab);
+
+ /* Now assign positions to the strings we want to keep. */
+ size = 0;
+--- 599,644 ----
+
+ sinfo->htab->size = a - array;
+
+ for (a = array, end = array + sinfo->htab->size; a < end; a++)
+ {
+ e = *a;
+ e->u.entsize = sinfo->htab->entsize;
+! }
+
+
+! qsort (array, (size_t) sinfo->htab->size,
+! sizeof (struct sec_merge_hash_entry *), strrevcmp);
+!
+! for (a = array, end = array + sinfo->htab->size; a < end; a++)
+! {
+! e = *a;
+! if (e->len <= e->u.entsize)
+! continue;
+! {
+! bfd_boolean found = FALSE;
+! struct sec_merge_hash_entry **b = a+1;
+! while (b < end)
+! {
+! struct sec_merge_hash_entry *cmp = *b;
+! if (!is_suffix(cmp, e))
+! break;
+! if (e->alignment >= cmp->alignment
+! && !((e->len - cmp->len) & (cmp->alignment - 1)))
+! /* The suffix is sufficiently aligned. */
+! {
+! e->u.suffix = cmp;
+! found = TRUE;
+! }
+! ++b;
+! }
+! if( found )
+! e->alignment = 0;
+ }
+ }
+
+ alloc_failure:
+ if (array)
+ free (array);
+
+ /* Now assign positions to the strings we want to keep. */
+ size = 0;
+*** ./bfd/elf-strtab.c 2003-08-21 12:28:47.000000000 -0300
+--- ./bfd/elf-strtab.c.new 2003-09-04 13:21:17.000000000 -0300
+***************
+*** 57,62 ****
+--- 57,68 ----
+ struct elf_strtab_hash_entry **array;
+ };
+
++ static int strrevcmp PARAMS ((const PTR, const PTR));
++ static int is_suffix PARAMS ((const struct elf_strtab_hash_entry *,
++ const struct elf_strtab_hash_entry *));
++
++
++
+ /* Routine to create an entry in a section merge hashtab. */
+
+ static struct bfd_hash_entry *
+***************
+*** 253,284 ****
+ return TRUE;
+ }
+
+! /* Compare two elf_strtab_hash_entry structures. This is called via qsort. */
+!
+! static int
+! cmplengthentry (const void *a, const void *b)
+ {
+ struct elf_strtab_hash_entry *A = *(struct elf_strtab_hash_entry **) a;
+ struct elf_strtab_hash_entry *B = *(struct elf_strtab_hash_entry **) b;
+
+! if (A->len < B->len)
+! return 1;
+! else if (A->len > B->len)
+! return -1;
+
+- return memcmp (A->root.string, B->root.string, A->len);
+ }
+
+! static int
+! last4_eq (const void *a, const void *b)
+! {
+! const struct elf_strtab_hash_entry *A = a;
+! const struct elf_strtab_hash_entry *B = b;
+
+! if (memcmp (A->root.string + A->len - 5, B->root.string + B->len - 5, 4)
+! != 0)
+! /* This was a hashtable collision. */
+! return 0;
+
+ if (A->len <= B->len)
+ /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+--- 259,291 ----
+ return TRUE;
+ }
+
+! static int strrevcmp( a, b )
+! const PTR a;
+! const PTR b;
+ {
+ struct elf_strtab_hash_entry *A = *(struct elf_strtab_hash_entry **) a;
+ struct elf_strtab_hash_entry *B = *(struct elf_strtab_hash_entry **) b;
+
+! const unsigned char *s = A->root.string + A->len - 1;
+! const unsigned char *t = B->root.string + B->len - 1;
+! int l = A->len < B->len ? A->len : B->len;
+!
+! while (l) {
+! if (*s != *t)
+! return (int)*s - (int)*t;
+! s--;
+! t--;
+! l--;
+! }
+! return A->len - B->len;
+
+ }
+
+! static int is_suffix(A, B)
+! const struct elf_strtab_hash_entry *A;
+! const struct elf_strtab_hash_entry *B;
+
+! {
+
+ if (A->len <= B->len)
+ /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
+***************
+*** 286,292 ****
+ return 0;
+
+ return memcmp (A->root.string + (A->len - B->len),
+! B->root.string, B->len - 5) == 0;
+ }
+
+ /* This function assigns final string table offsets for used strings,
+--- 291,297 ----
+ return 0;
+
+ return memcmp (A->root.string + (A->len - B->len),
+! B->root.string, B->len - 1) == 0;
+ }
+
+ /* This function assigns final string table offsets for used strings,
+***************
+*** 296,304 ****
+ _bfd_elf_strtab_finalize (struct elf_strtab_hash *tab)
+ {
+ struct elf_strtab_hash_entry **array, **a, **end, *e;
+- htab_t last4tab = NULL;
+ bfd_size_type size, amt;
+- struct elf_strtab_hash_entry *last[256], **last_ptr[256];
+
+ /* GCC 2.91.66 (egcs-1.1.2) on i386 miscompiles this function when i is
+ a 64-bit bfd_size_type: a 64-bit target or --enable-64-bit-bfd.
+--- 301,307 ----
+***************
+*** 306,321 ****
+ cycles. */
+ size_t i;
+
+! /* Now sort the strings by length, longest first. */
+ array = NULL;
+ amt = tab->size * sizeof (struct elf_strtab_hash_entry *);
+ array = bfd_malloc (amt);
+ if (array == NULL)
+ goto alloc_failure;
+
+- memset (last, 0, sizeof (last));
+- for (i = 0; i < 256; ++i)
+- last_ptr[i] = &last[i];
+ for (i = 1, a = array; i < tab->size; ++i)
+ if (tab->array[i]->refcount)
+ *a++ = tab->array[i];
+--- 309,321 ----
+ cycles. */
+ size_t i;
+
+! /* Now sort the strings */
+ array = NULL;
+ amt = tab->size * sizeof (struct elf_strtab_hash_entry *);
+ array = bfd_malloc (amt);
+ if (array == NULL)
+ goto alloc_failure;
+
+ for (i = 1, a = array; i < tab->size; ++i)
+ if (tab->array[i]->refcount)
+ *a++ = tab->array[i];
+***************
+*** 324,403 ****
+
+ size = a - array;
+
+! qsort (array, size, sizeof (struct elf_strtab_hash_entry *), cmplengthentry);
+
+! last4tab = htab_create_alloc (size * 4, NULL, last4_eq, NULL, calloc, free);
+! if (last4tab == NULL)
+! goto alloc_failure;
+!
+! /* Now insert the strings into hash tables (strings with last 4 characters
+! and strings with last character equal), look for longer strings which
+! we're suffix of. */
+ for (a = array, end = array + size; a < end; a++)
+ {
+- register hashval_t hash;
+- unsigned int c;
+- unsigned int j;
+- const unsigned char *s;
+- void **p;
+-
+ e = *a;
+! if (e->len > 4)
+! {
+! s = e->root.string + e->len - 1;
+! hash = 0;
+! for (j = 0; j < 4; j++)
+! {
+! c = *--s;
+! hash += c + (c << 17);
+! hash ^= hash >> 2;
+! }
+! p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
+! if (p == NULL)
+! goto alloc_failure;
+! if (*p)
+! {
+! struct elf_strtab_hash_entry *ent;
+!
+! ent = *p;
+! e->u.suffix = ent;
+! e->len = 0;
+ continue;
+- }
+- else
+- *p = e;
+- }
+- else
+ {
+! struct elf_strtab_hash_entry *tem;
+!
+! c = e->root.string[e->len - 2] & 0xff;
+
+- for (tem = last[c]; tem; tem = tem->u.next)
+- if (tem->len > e->len
+- && memcmp (tem->root.string + (tem->len - e->len),
+- e->root.string, e->len - 1) == 0)
+ break;
+! if (tem)
+! {
+! e->u.suffix = tem;
+ e->len = 0;
+- continue;
+ }
+ }
+
+- c = e->root.string[e->len - 2] & 0xff;
+- /* Put longest strings first. */
+- *last_ptr[c] = e;
+- last_ptr[c] = &e->u.next;
+- e->u.next = NULL;
+- }
+
+ alloc_failure:
+ if (array)
+ free (array);
+- if (last4tab)
+- htab_delete (last4tab);
+
+ /* Now assign positions to the strings we want to keep. */
+ size = 1;
+--- 324,358 ----
+
+ size = a - array;
+
+! qsort (array, size, sizeof (struct elf_strtab_hash_entry *), strrevcmp);
+
+! /* now loop over the sorted array and merge suffixes */
+ for (a = array, end = array + size; a < end; a++)
+ {
+ e = *a;
+! if( e->len <= 1 )
+ continue;
+ {
+! struct elf_strtab_hash_entry **b = a+1;
+! int found = 0;
+! while (b < end) {
+! struct elf_strtab_hash_entry *cmp = *b;
+! if (!is_suffix(cmp, e))
+
+ break;
+! e->u.suffix = cmp;
+! found = 1;
+! ++b;
+! }
+! if( found )
+ e->len = 0;
+ }
+ }
+
+
+ alloc_failure:
+ if (array)
+ free (array);
+
+ /* Now assign positions to the strings we want to keep. */
+ size = 1;
diff --git a/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r3 b/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r3
new file mode 100644
index 000000000000..26abe27b6c76
--- /dev/null
+++ b/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r3
@@ -0,0 +1 @@
+MD5 71b99dba3045a359dc314dbebedcf502 binutils-2.14.90.0.6.tar.bz2 10399066