summaryrefslogtreecommitdiff
path: root/patches/test/binutils-dynsort.diff
diff options
context:
space:
mode:
Diffstat (limited to 'patches/test/binutils-dynsort.diff')
-rw-r--r--patches/test/binutils-dynsort.diff1086
1 files changed, 0 insertions, 1086 deletions
diff --git a/patches/test/binutils-dynsort.diff b/patches/test/binutils-dynsort.diff
deleted file mode 100644
index c37fe3a59..000000000
--- a/patches/test/binutils-dynsort.diff
+++ /dev/null
@@ -1,1086 +0,0 @@
---- error - this patch is deprecated; cf. binutils-suse-dynsort.diff
-
-
---- binutils-2.16.91.0.4/bfd/ChangeLog 2005-11-13 17:16:34.000000000 +0000
-+++ binutils.current/bfd/ChangeLog 2006-01-18 17:33:24.000000000 +0000
-@@ -1,3 +1,40 @@
-+2006-01-18 Michael Meeks <michael.meeks@novell.com>
-+
-+ * bfdsort.c: import qsort.c from glibc-2.3 and re-work to
-+ provide missing closure argument, for more elegant sorting.
-+
-+ * elf-strtab.c (_bfd_elf_strtab_init, _bfd_elf_strtab_free):
-+ manage the sorted array.
-+ (_bfd_elf_strtab_emit): emit .dynstr in sorted order.
-+ (_bfd_elf_strtab_finalize, hash_compare): sort .dynstr
-+ primarily by elf bucket index.
-+
-+ * elflink.c (elf_finalize_dynstr): pass bucket count to
-+ strtab_finalize.
-+ (_bfd_elf_ver_hash): split for re-use from
-+ (elf_collect_hash_codes): here.
-+ (_bfd_elf_link_hash_traverse): new traversal function:
-+ walks sorted array if sorted, else walks the hash as before.
-+ (elf_sort_dynsym_hash): qsort method to sort dynsyms
-+ (elf_sort_collect_dynsyms): hash walker to collect symbols
-+ (_bfd_elf_sort_dynsyms): method - sorts .dynsym section.
-+ (bfd_elf_size_dynsym_hash_dynstr): do the .dynsym sort.
-+ (elf_link_sort_relocs, elf_link_sort_cmp2): sort relocs
-+ primarily by elf bucket index.
-+ (bfd_elf_final_link): update reloc sort call.
-+
-+ * elf.c (_bfd_elf_link_hash_table_init),
-+ (_bfd_elf_link_hash_table_free): init & free sorted array.
-+ (assign_section_numbers): upd. strtab_finalize call.
-+
-+ * elf32-m68hc1x.c (m68hc11_elf_bfd_link_hash_table_free),
-+ * elf-m10300.c (elf32_mn10300_link_hash_table_free),
-+ * elf32-hppa.c (elf32_hppa_link_hash_table_free),
-+ * elf64-ppc.c (ppc64_elf_link_hash_table_free),
-+ * elf.c (_bfd_elf_link_hash_table_free),
-+ * elfxx-target.h: implement elf specific hash free
-+ method & re-direct callers to it.
-+
- 2005-11-11 Nick Clifton <nickc@redhat.com>
-
- PR 1150
-
---- binutils-2.16.91.0.4/bfd/bfd.h 2005-12-23 17:03:29.000000000 +0000
-+++ binutils.current/bfd/bfd.h 2006-01-18 15:48:46.000000000 +0000
-@@ -639,6 +639,9 @@
- DYN_NO_NEEDED = 8
- };
-
-+typedef int(*bfd_qsort_closure_func)(const void *, const void *, const void *);
-+extern void bfd_qsort (void *base, bfd_size_type nmemb, bfd_size_type size,
-+ bfd_qsort_closure_func cmp, void *closure);
- extern bfd_boolean bfd_elf_record_link_assignment
- (struct bfd_link_info *, const char *, bfd_boolean);
- extern struct bfd_link_needed_list *bfd_elf_get_needed_list
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/ChangeLog binutils.current/bfd/ChangeLog
-Files binutils-2.16.91.0.4/bfd/doc/chew and binutils.current/bfd/doc/chew differ
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf32-hppa.c binutils.current/bfd/elf32-hppa.c
---- binutils-2.16.91.0.4/bfd/elf32-hppa.c 2005-11-13 17:16:34.000000000 +0000
-+++ binutils.current/bfd/elf32-hppa.c 2005-12-23 14:06:31.000000000 +0000
-@@ -435,7 +435,7 @@
- = (struct elf32_hppa_link_hash_table *) btab;
-
- bfd_hash_table_free (&htab->bstab);
-- _bfd_generic_link_hash_table_free (btab);
-+ _bfd_elf_link_hash_table_free (hash);
- }
-
- /* Build a name for an entry in the stub hash table. */
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf32-m68hc1x.c binutils.current/bfd/elf32-m68hc1x.c
---- binutils-2.16.91.0.4/bfd/elf32-m68hc1x.c 2005-06-22 21:53:34.000000000 +0100
-+++ binutils.current/bfd/elf32-m68hc1x.c 2005-12-23 14:07:21.000000000 +0000
-@@ -106,7 +106,7 @@
-
- bfd_hash_table_free (ret->stub_hash_table);
- free (ret->stub_hash_table);
-- _bfd_generic_link_hash_table_free (hash);
-+ _bfd_elf_link_hash_table_free (hash);
- }
-
- /* Assorted hash table functions. */
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf32-target.h binutils.current/bfd/elf32-target.h
---- binutils-2.16.91.0.4/bfd/elf32-target.h 2005-12-23 17:12:23.000000000 +0000
-+++ binutils.current/bfd/elf32-target.h 2005-12-23 14:51:28.000000000 +0000
-@@ -205,7 +205,7 @@
- #endif
-
- #ifndef bfd_elf32_bfd_link_hash_table_free
--#define bfd_elf32_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
-+#define bfd_elf32_bfd_link_hash_table_free _bfd_elf_link_hash_table_free
- #endif
-
- #ifdef elf_backend_relocate_section
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf64-ppc.c binutils.current/bfd/elf64-ppc.c
---- binutils-2.16.91.0.4/bfd/elf64-ppc.c 2005-11-13 17:16:34.000000000 +0000
-+++ binutils.current/bfd/elf64-ppc.c 2005-12-23 14:04:07.000000000 +0000
-@@ -3502,7 +3502,7 @@
-
- bfd_hash_table_free (&ret->stub_hash_table);
- bfd_hash_table_free (&ret->branch_hash_table);
-- _bfd_generic_link_hash_table_free (hash);
-+ _bfd_elf_link_hash_table_free (hash);
- }
-
- /* Satisfy the ELF linker by filling in some fields in our fake bfd. */
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf-bfd.h binutils.current/bfd/elf-bfd.h
---- binutils-2.16.91.0.4/bfd/elf-bfd.h 2005-12-22 10:42:52.000000000 +0000
-+++ binutils.current/bfd/elf-bfd.h 2005-12-23 14:59:54.000000000 +0000
-@@ -340,6 +340,10 @@
- {
- struct bfd_link_hash_table root;
-
-+ /* Symbol sort order for final traversal at output */
-+ unsigned int sorted_size;
-+ struct elf_link_hash_entry **sorted;
-+
- /* Whether we have created the special dynamic sections required
- when linking against or generating a shared object. */
- bfd_boolean dynamic_sections_created;
-@@ -418,11 +422,16 @@
- /* Traverse an ELF linker hash table. */
-
- #define elf_link_hash_traverse(table, func, info) \
-- (bfd_link_hash_traverse \
-- (&(table)->root, \
-- (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
-+ (_bfd_elf_link_hash_traverse \
-+ ((table), \
-+ (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
- (info)))
-
-+void _bfd_elf_link_hash_traverse
-+ (struct elf_link_hash_table *table,
-+ bfd_boolean (*func) (struct elf_link_hash_entry *, void *),
-+ void *info);
-+
- /* Get the ELF linker hash table from a link_info structure. */
-
- #define elf_hash_table(p) ((struct elf_link_hash_table *) ((p)->hash))
-@@ -1446,6 +1455,8 @@
-
- extern unsigned long bfd_elf_hash
- (const char *);
-+extern unsigned long _bfd_elf_ver_hash
-+ (const char *);
-
- extern bfd_reloc_status_type bfd_elf_generic_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-@@ -1463,6 +1474,7 @@
- (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
- extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create
- (bfd *);
-+extern void _bfd_elf_link_hash_table_free (struct bfd_link_hash_table *);
- extern void _bfd_elf_link_hash_copy_indirect
- (struct bfd_link_info *, struct elf_link_hash_entry *,
- struct elf_link_hash_entry *);
-@@ -1593,7 +1605,7 @@
- extern bfd_boolean _bfd_elf_strtab_emit
- (bfd *, struct elf_strtab_hash *);
- extern void _bfd_elf_strtab_finalize
-- (struct elf_strtab_hash *);
-+ (struct elf_strtab_hash *, size_t);
-
- extern bfd_boolean _bfd_elf_discard_section_eh_frame
- (bfd *, struct bfd_link_info *, asection *,
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf.c binutils.current/bfd/elf.c
---- binutils-2.16.91.0.4/bfd/elf.c 2005-12-22 10:42:52.000000000 +0000
-+++ binutils.current/bfd/elf.c 2005-12-23 14:04:18.000000000 +0000
-@@ -1560,6 +1560,8 @@
- table->tls_size = 0;
- table->loaded = NULL;
- table->is_relocatable_executable = FALSE;
-+ table->sorted = NULL;
-+ table->sorted_size = 0;
-
- ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
- table->root.type = bfd_link_elf_hash_table;
-@@ -1588,6 +1590,15 @@
- return &ret->root;
- }
-
-+void
-+_bfd_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
-+{
-+ struct elf_link_hash_table *table = (struct elf_link_hash_table *) hash;
-+ if (table->sorted)
-+ free (table->sorted);
-+ _bfd_generic_link_hash_table_free (hash);
-+}
-+
- /* This is a hook for the ELF emulation code in the generic linker to
- tell the backend linker what file name to use for the DT_NEEDED
- entry for a dynamic object. */
-@@ -2983,7 +2994,7 @@
- _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
- }
-
-- _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
-+ _bfd_elf_strtab_finalize (elf_shstrtab (abfd), 0);
- t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
-
- elf_numsections (abfd) = section_number;
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elflink.c binutils.current/bfd/elflink.c
---- binutils-2.16.91.0.4/bfd/elflink.c 2005-12-22 10:42:52.000000000 +0000
-+++ binutils.current/bfd/elflink.c 2006-01-18 16:36:45.000000000 +0000
-@@ -3007,7 +3007,8 @@
- const struct elf_backend_data *bed;
- bfd_byte *extdyn;
-
-- _bfd_elf_strtab_finalize (dynstr);
-+ _bfd_elf_strtab_finalize (dynstr, info->dynsort ?
-+ elf_hash_table (info)->bucketcount : 0);
- size = _bfd_elf_strtab_size (dynstr);
-
- bed = get_elf_backend_data (dynobj);
-@@ -4715,27 +4716,17 @@
- return FALSE;
- }
- }
--
--/* This function will be called though elf_link_hash_traverse to store
-- all hash value of the exported symbols in an array. */
-
--static bfd_boolean
--elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
-+/*
-+ * Compute the elf hash value of the name ignoring the version.
-+ */
-+unsigned long
-+_bfd_elf_ver_hash (const char *name)
- {
-- unsigned long **valuep = data;
-- const char *name;
- char *p;
- unsigned long ha;
- char *alc = NULL;
-
-- if (h->root.type == bfd_link_hash_warning)
-- h = (struct elf_link_hash_entry *) h->root.u.i.link;
--
-- /* Ignore indirect symbols. These are added by the versioning code. */
-- if (h->dynindx == -1)
-- return TRUE;
--
-- name = h->root.root.string;
- p = strchr (name, ELF_VER_CHR);
- if (p != NULL)
- {
-@@ -4748,6 +4739,31 @@
- /* Compute the hash value. */
- ha = bfd_elf_hash (name);
-
-+ if (alc != NULL)
-+ free (alc);
-+
-+ return ha;
-+}
-+
-+
-+/* This function will be called though elf_link_hash_traverse to store
-+ all hash value of the exported symbols in an array. */
-+
-+static bfd_boolean
-+elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
-+{
-+ unsigned long **valuep = data;
-+ unsigned long ha;
-+
-+ if (h->root.type == bfd_link_hash_warning)
-+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
-+
-+ /* Ignore indirect symbols. These are added by the versioning code. */
-+ if (h->dynindx == -1)
-+ return TRUE;
-+
-+ ha = _bfd_elf_ver_hash (h->root.root.string);
-+
- /* Store the found hash value in the array given as the argument. */
- *(*valuep)++ = ha;
-
-@@ -4755,9 +4771,6 @@
- later. */
- h->u.elf_hash_value = ha;
-
-- if (alc != NULL)
-- free (alc);
--
- return TRUE;
- }
-
-@@ -4920,6 +4933,123 @@
- return best_size;
- }
-
-+void _bfd_elf_link_hash_traverse
-+ (struct elf_link_hash_table *table,
-+ bfd_boolean (*func) (struct elf_link_hash_entry *, void *),
-+ void *info)
-+{
-+ if (!table->sorted)
-+ bfd_link_hash_traverse \
-+ (&(table)->root, \
-+ (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \
-+ (info));
-+ else
-+ {
-+ unsigned int i;
-+ for (i = 0; i < table->sorted_size; i++)
-+ {
-+ if (! func (table->sorted[i], info))
-+ return;
-+ }
-+ }
-+}
-+
-+/* Sort by elf hash value % buckets */
-+static int
-+elf_sort_dynsym_hash (const void *arg1, const void *arg2, const void *closure)
-+{
-+ size_t h1_bucket, h2_bucket;
-+ const struct elf_link_hash_entry *h1;
-+ const struct elf_link_hash_entry *h2;
-+ const bfd_size_type *bucketcount;
-+
-+ h1 = *(const struct elf_link_hash_entry **) arg1;
-+ h2 = *(const struct elf_link_hash_entry **) arg2;
-+ bucketcount = closure;
-+
-+ h1_bucket = h1->u.elf_hash_value % *bucketcount;
-+ h2_bucket = h2->u.elf_hash_value % *bucketcount;
-+
-+ if (h1_bucket > h2_bucket)
-+ return 1;
-+ if (h1_bucket < h2_bucket)
-+ return -1;
-+
-+ return 0;
-+}
-+
-+struct elf_dynsym_sort_info
-+{
-+ bfd_boolean do_dynsym;
-+ unsigned int alloc_size;
-+ unsigned int sorted_size;
-+ struct elf_link_hash_entry **sorted_syms;
-+};
-+
-+/* collect sym entries into an array for later sorting */
-+static bfd_boolean
-+elf_sort_collect_dynsyms (struct elf_link_hash_entry *h, void *data)
-+{
-+ struct elf_dynsym_sort_info *sinfo = data;
-+
-+ if ((sinfo->do_dynsym && h->dynindx < 0) ||
-+ (!sinfo->do_dynsym && h->dynindx >= 0))
-+ return TRUE;
-+
-+ if (sinfo->sorted_size >= sinfo->alloc_size)
-+ {
-+ sinfo->alloc_size *= 2;
-+ /* FIXME: need to free this data too ... */
-+ sinfo->sorted_syms = bfd_realloc (sinfo->sorted_syms,
-+ sizeof (struct elf_link_hash_entry *) *
-+ sinfo->alloc_size);
-+ }
-+ sinfo->sorted_syms [sinfo->sorted_size++] = h;
-+
-+ return TRUE;
-+}
-+
-+/*
-+ * Sort the exported elf symbols by elf_hash % bucketcount to
-+ * improve run-time linker cache behavior. Subsequent
-+ * elf_link_hash_traverse calls will reflect this new order.
-+ */
-+static bfd_boolean
-+_bfd_elf_sort_dynsyms (struct bfd_link_info *info)
-+{
-+ bfd_size_type bucketcount;
-+ struct elf_dynsym_sort_info sinfo;
-+
-+ sinfo.alloc_size = 8;
-+ sinfo.sorted_syms = bfd_malloc (sizeof (struct elf_link_hash_entry *) *
-+ sinfo.alloc_size);
-+ if (!sinfo.sorted_syms)
-+ return FALSE;
-+
-+ sinfo.sorted_size = 0;
-+
-+ /* append dynsyms for sorting */
-+ sinfo.do_dynsym = TRUE;
-+ elf_link_hash_traverse (elf_hash_table (info), elf_sort_collect_dynsyms, &sinfo);
-+
-+ /* sort them ... */
-+ bucketcount = elf_hash_table (info)->bucketcount;
-+ bfd_qsort (sinfo.sorted_syms, sinfo.sorted_size,
-+ sizeof (struct elf_link_hash_entry *),
-+ elf_sort_dynsym_hash,
-+ &bucketcount);
-+
-+ /* append everything else */
-+ sinfo.do_dynsym = FALSE;
-+ elf_link_hash_traverse (elf_hash_table (info), elf_sort_collect_dynsyms, &sinfo);
-+
-+ /* freed in _bfd_elf_link_hash_table_free */
-+ elf_hash_table (info)->sorted = sinfo.sorted_syms;
-+ elf_hash_table (info)->sorted_size = sinfo.sorted_size;
-+
-+ return TRUE;
-+}
-+
- /* Set up the sizes and contents of the ELF dynamic sections. This is
- called by the ELF linker emulation before_allocation routine. We
- must set the sizes of the sections before the linker sets the
-@@ -5686,6 +5816,7 @@
- section symbol for each output section, which come first.
- Next come all of the back-end allocated local dynamic syms,
- followed by the rest of the global symbols. */
-+ /* To sort these optimally we need the correct bucketcount */
-
- dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
- &section_sym_count);
-@@ -5756,6 +5887,17 @@
- for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
- if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0))
- return FALSE;
-+
-+ /* Sort .dynsym to accelerate runtime linking */
-+ if (info->dynsort)
-+ {
-+ if (!_bfd_elf_sort_dynsyms (info))
-+ return FALSE;
-+
-+ /* renumber to reflect the new sorting order */
-+ _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-+ &section_sym_count);
-+ }
- }
-
- return TRUE;
-@@ -5892,6 +6034,7 @@
- bfd_vma sym_mask;
- } u;
- enum elf_reloc_type_class type;
-+ unsigned long elf_bucket;
- /* We use this as an array of size int_rels_per_ext_rel. */
- Elf_Internal_Rela rela[1];
- };
-@@ -5928,6 +6071,10 @@
- const struct elf_link_sort_rela *b = B;
- int copya, copyb;
-
-+ if (a->elf_bucket < b->elf_bucket)
-+ return -1;
-+ if (a->elf_bucket > b->elf_bucket)
-+ return 1;
- if (a->u.offset < b->u.offset)
- return -1;
- if (a->u.offset > b->u.offset)
-@@ -5946,8 +6093,9 @@
- }
-
- static size_t
--elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
-+elf_link_sort_relocs (bfd *abfd, struct elf_final_link_info *finfo, asection **psec)
- {
-+ struct bfd_link_info *info = finfo->info;
- asection *reldyn;
- bfd_size_type count, size;
- size_t i, ret, sort_elt, ext_size;
-@@ -5959,6 +6107,7 @@
- void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
- struct bfd_link_order *lo;
- bfd_vma r_sym_mask;
-+ int r_sym_shift;
-
- reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
- if (reldyn == NULL || reldyn->size == 0)
-@@ -6000,15 +6149,29 @@
- }
-
- if (bed->s->arch_size == 32)
-- r_sym_mask = ~(bfd_vma) 0xff;
-+ {
-+ r_sym_mask = ~(bfd_vma) 0xff;
-+ r_sym_shift = 8;
-+ }
- else
-- r_sym_mask = ~(bfd_vma) 0xffffffff;
-+ {
-+ r_sym_mask = ~(bfd_vma) 0xffffffff;
-+ r_sym_shift = 32;
-+ }
-
- for (lo = reldyn->map_head.link_order; lo != NULL; lo = lo->next)
- if (lo->type == bfd_indirect_link_order)
- {
- bfd_byte *erel, *erelend;
- asection *o = lo->u.indirect.section;
-+ int base_offset = -1;
-+ int base_max = 0;
-+
-+ if (elf_hash_table (info)->sorted_size > 0)
-+ {
-+ base_offset = elf_hash_table (info)->sorted[0]->dynindx;
-+ base_max = base_offset + elf_hash_table (info)->sorted_size;
-+ }
-
- if (o->contents == NULL && o->size != 0)
- {
-@@ -6023,10 +6186,24 @@
- p = sort + o->output_offset / ext_size * sort_elt;
- while (erel < erelend)
- {
-+ long dyn_idx;
-+ size_t bucketcount = elf_hash_table (info)->bucketcount;
- struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
- (*swap_in) (abfd, erel, s->rela);
- s->type = (*bed->elf_backend_reloc_type_class) (s->rela);
- s->u.sym_mask = r_sym_mask;
-+
-+ if (s->type != reloc_class_relative)
-+ dyn_idx = s->rela->r_info >> r_sym_shift;
-+ else
-+ dyn_idx = -1;
-+
-+ if (info->dynsort && base_offset >= 0 &&
-+ dyn_idx < base_max && dyn_idx >= base_offset)
-+ s->elf_bucket = elf_hash_table (info)->sorted [dyn_idx - base_offset]->u.elf_hash_value % bucketcount;
-+ else
-+ s->elf_bucket = 0;
-+
- p += sort_elt;
- erel += ext_size;
- }
-@@ -8426,7 +8612,7 @@
- }
-
- if (dynamic && info->combreloc && dynobj != NULL)
-- relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
-+ relativecount = elf_link_sort_relocs (abfd, &finfo, &reldyn);
-
- /* If we are linking against a dynamic object, or generating a
- shared library, finish up the dynamic linking information. */
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf-m10300.c binutils.current/bfd/elf-m10300.c
---- binutils-2.16.91.0.4/bfd/elf-m10300.c 2005-11-13 17:16:34.000000000 +0000
-+++ binutils.current/bfd/elf-m10300.c 2005-12-23 14:06:10.000000000 +0000
-@@ -3729,8 +3729,7 @@
-
- _bfd_generic_link_hash_table_free
- ((struct bfd_link_hash_table *) ret->static_hash_table);
-- _bfd_generic_link_hash_table_free
-- ((struct bfd_link_hash_table *) ret);
-+ _bfd_elf_link_hash_table_free (hash);
- }
-
- static unsigned long
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elf-strtab.c binutils.current/bfd/elf-strtab.c
---- binutils-2.16.91.0.4/bfd/elf-strtab.c 2005-05-10 23:46:41.000000000 +0100
-+++ binutils.current/bfd/elf-strtab.c 2006-01-18 16:37:04.000000000 +0000
-@@ -39,6 +39,7 @@
- /* Entry this is a suffix of (if len < 0). */
- struct elf_strtab_hash_entry *suffix;
- } u;
-+ long hash_bucket;
- };
-
- /* The strtab hash table. */
-@@ -54,6 +55,8 @@
- bfd_size_type sec_size;
- /* Array of pointers to strtab entries. */
- struct elf_strtab_hash_entry **array;
-+ /* Array of pointers to strtab entries. */
-+ struct elf_strtab_hash_entry **array_sorted;
- };
-
- /* Routine to create an entry in a section merge hashtab. */
-@@ -117,6 +120,7 @@
- }
-
- table->array[0] = NULL;
-+ table->array_sorted = NULL;
-
- return table;
- }
-@@ -128,6 +132,8 @@
- {
- bfd_hash_table_free (&tab->table);
- free (tab->array);
-+ if (tab->array_sorted)
-+ free (tab->array_sorted);
- free (tab);
- }
-
-@@ -229,6 +235,12 @@
- _bfd_elf_strtab_emit (register bfd *abfd, struct elf_strtab_hash *tab)
- {
- bfd_size_type off = 1, i;
-+ struct elf_strtab_hash_entry **array;
-+
-+ if (tab->array_sorted != NULL)
-+ array = tab->array_sorted;
-+ else
-+ array = tab->array;
-
- if (bfd_bwrite ("", 1, abfd) != 1)
- return FALSE;
-@@ -238,12 +250,12 @@
- register const char *str;
- register unsigned int len;
-
-- BFD_ASSERT (tab->array[i]->refcount == 0);
-- len = tab->array[i]->len;
-+ BFD_ASSERT (array[i]->refcount == 0);
-+ len = array[i]->len;
- if ((int) len < 0)
- continue;
-
-- str = tab->array[i]->root.string;
-+ str = array[i]->root.string;
- if (bfd_bwrite (str, len, abfd) != len)
- return FALSE;
-
-@@ -278,6 +290,26 @@
- return lenA - lenB;
- }
-
-+/* sort by hash bucket position */
-+static int
-+hash_compare (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->hash_bucket > B->hash_bucket)
-+ return 1;
-+ if (A->hash_bucket < B->hash_bucket)
-+ return -1;
-+
-+ /* Make qsort faster for lots of identical empty symbols */
-+ if (a > b)
-+ return 1;
-+ if (a < b)
-+ return -1;
-+ return 0;
-+}
-+
- static inline int
- is_suffix (const struct elf_strtab_hash_entry *A,
- const struct elf_strtab_hash_entry *B)
-@@ -293,9 +325,8 @@
-
- /* This function assigns final string table offsets for used strings,
- merging strings matching suffixes of longer strings if possible. */
--
- void
--_bfd_elf_strtab_finalize (struct elf_strtab_hash *tab)
-+_bfd_elf_strtab_finalize (struct elf_strtab_hash *tab, size_t bucket_count)
- {
- struct elf_strtab_hash_entry **array, **a, *e;
- bfd_size_type size, amt;
-@@ -361,15 +392,37 @@
- }
- }
-
--alloc_failure:
-- if (array)
-- free (array);
-+ if (bucket_count != 0)
-+ {
-+ array[0] = NULL;
-+ for (i = 1; i < tab->size; ++i)
-+ {
-+ e = tab->array[i];
-+ array[i] = e;
-+
-+ if (e->len > 0)
-+ {
-+ e->hash_bucket = _bfd_elf_ver_hash (e->root.string);
-+ e->hash_bucket %= bucket_count;
-+ }
-+ else
-+ e->hash_bucket = 0;
-+ }
-+ qsort (array + 1, tab->size - 1, sizeof (struct elf_strtab_hash_entry *), hash_compare);
-+ tab->array_sorted = array;
-+ }
-+ else
-+ {
-+ free (array);
-+ alloc_failure:
-+ array = tab->array;
-+ }
-
- /* Assign positions to the strings we want to keep. */
- size = 1;
- for (i = 1; i < tab->size; ++i)
- {
-- e = tab->array[i];
-+ e = array[i];
- if (e->refcount && e->len > 0)
- {
- e->u.index = size;
-@@ -382,7 +435,7 @@
- /* Adjust the rest. */
- for (i = 1; i < tab->size; ++i)
- {
-- e = tab->array[i];
-+ e = array[i];
- if (e->refcount && e->len < 0)
- e->u.index = e->u.suffix->u.index + (e->u.suffix->len + e->len);
- }
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/bfd/elfxx-target.h binutils.current/bfd/elfxx-target.h
---- binutils-2.16.91.0.4/bfd/elfxx-target.h 2005-08-22 20:27:41.000000000 +0100
-+++ binutils.current/bfd/elfxx-target.h 2005-12-23 14:06:51.000000000 +0000
-@@ -205,7 +205,7 @@
- #endif
-
- #ifndef bfd_elfNN_bfd_link_hash_table_free
--#define bfd_elfNN_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
-+#define bfd_elfNN_bfd_link_hash_table_free _bfd_elf_link_hash_table_free
- #endif
-
- #ifdef elf_backend_relocate_section
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/include/bfdlink.h binutils.current/include/bfdlink.h
---- binutils-2.16.91.0.4/include/bfdlink.h 2005-12-22 10:42:52.000000000 +0000
-+++ binutils.current/include/bfdlink.h 2006-01-18 16:19:19.000000000 +0000
-@@ -327,6 +327,9 @@
- /* TRUE if unreferenced sections should be removed. */
- unsigned int gc_sections: 1;
-
-+ /* TRUE if dynsym/dynstr/relocs should be sorted */
-+ unsigned int dynsort : 1;
-+
- /* What to do with unresolved symbols in an object file.
- When producing executables the default is GENERATE_ERROR.
- When producing shared libraries the default is IGNORE. The
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/ld/eelf_i386.c binutils.current/ld/eelf_i386.c
---- binutils-2.16.91.0.4/ld/eelf_i386.c 2005-12-23 17:21:49.000000000 +0000
-+++ binutils.current/ld/eelf_i386.c 2006-01-18 17:21:10.000000000 +0000
-@@ -3949,6 +3949,10 @@
- link_info.relro = TRUE;
- else if (strcmp (optarg, "norelro") == 0)
- link_info.relro = FALSE;
-+ else if (strcmp (optarg, "dynsort") == 0)
-+ link_info.dynsort = TRUE;
-+ else if (strcmp (optarg, "nodynsort") == 0)
-+ link_info.dynsort = FALSE;
- /* What about the other Solaris -z options? FIXME. */
- break;
- }
-@@ -3966,6 +3970,7 @@
- fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
- fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
- fprintf (file, _(" -z defs\t\tReport unresolved symbols in object files.\n"));
-+ fprintf (file, _(" -z dynsort\t\tSort dynamic link sections\n"));
- fprintf (file, _(" -z execstack\t\tMark executable as requiring executable stack\n"));
- fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
- fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n"));
-@@ -3977,6 +3982,7 @@
- fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n"));
- fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n"));
- fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n"));
-+ fprintf (file, _(" -z nodynsort\t\tDon't sort dynamic link sections\n"));
- fprintf (file, _(" -z noexecstack\tMark executable as not requiring executable stack\n"));
- fprintf (file, _(" -z norelro\t\tDon't create RELRO program header\n"));
- fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n"));
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/ld/ldmain.c binutils.current/ld/ldmain.c
---- binutils-2.16.91.0.4/ld/ldmain.c 2005-12-07 10:42:37.000000000 +0000
-+++ binutils.current/ld/ldmain.c 2006-01-18 16:19:56.000000000 +0000
-@@ -316,6 +316,7 @@
- link_info.need_relax_finalize = FALSE;
- link_info.warn_shared_textrel = FALSE;
- link_info.gc_sections = FALSE;
-+ link_info.dynsort = FALSE;
-
- ldfile_add_arch ("");
-
-diff -u -r -x texis -x Makeconfig -x version.h -x '*.o' -x '*.1' -x 'Makefile*' -x 'config*' -x libtool -x '*.info' -x '*.tex' binutils-2.16.91.0.4/ld/ld.texinfo binutils.current/ld/ld.texinfo
---- binutils-2.16.91.0.4/ld/ld.texinfo 2005-12-07 10:42:37.000000000 +0000
-+++ binutils.current/ld/ld.texinfo 2006-01-18 16:29:15.000000000 +0000
-@@ -928,6 +928,9 @@
- Disallows undefined symbols in object files. Undefined symbols in
- shared libraries are still allowed.
-
-+@item dynsort
-+Sorts dynamic link sections, to reduce cache misses during linking.
-+
- @item execstack
- Marks the object as requiring executable stack.
-
-@@ -969,7 +972,10 @@
- @item nodump
- Marks the object can not be dumped by @code{dldump}.
-
-+@item nodynsort
-+Disables dynamic link section sorting.
-+
- @item noexecstack
- Marks the object as not requiring executable stack.
-
-
-
-New module: bfdsort.c:
-
---- binutils-2.16.91.0.4/bfd/Makefile.am 2005-12-07 10:42:37.000000000 +0000
-+++ binutils.current/bfd/Makefile.am 2006-01-18 15:50:23.000000000 +0000
-@@ -32,7 +32,7 @@
- # need two copies of the executable, one to download and one for the
- # debugger).
- BFD32_LIBS = \
-- archive.lo archures.lo bfd.lo bfdio.lo bfdwin.lo \
-+ archive.lo archures.lo bfd.lo bfdio.lo bfdsort.lo bfdwin.lo \
- cache.lo coffgen.lo corefile.lo \
- format.lo init.lo libbfd.lo opncls.lo reloc.lo \
- section.lo syms.lo targets.lo hash.lo linker.lo \
-@@ -42,7 +42,7 @@
- BFD64_LIBS = archive64.lo
-
- BFD32_LIBS_CFILES = \
-- archive.c archures.c bfd.c bfdio.c bfdwin.c \
-+ archive.c archures.c bfd.c bfdio.c bfdsort.c bfdwin.c \
- cache.c coffgen.c corefile.c \
- format.c init.c libbfd.c opncls.c reloc.c \
- section.c syms.c targets.c hash.c linker.c \
-
---- /dev/null 2006-01-18 11:12:51.092369250 +0000
-+++ binutils.current/bfd/bfdsort.c 2006-01-18 15:55:17.000000000 +0000
-@@ -0,0 +1,253 @@
-+/*
-+ * This module copied from glibc/stdlib/qsort.c & adapted,
-+ * in order to add support for a closure argument.
-+ */
-+
-+/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+ Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, write to the Free
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+/* If you consider tuning this algorithm, you should consult first:
-+ Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
-+ Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
-+
-+#include "bfd.h"
-+#include "sysdep.h"
-+
-+/* Byte-wise swap two items of size SIZE. */
-+#define SWAP(a, b, size) \
-+ do \
-+ { \
-+ register bfd_size_type __size = (size); \
-+ register char *__a = (a), *__b = (b); \
-+ do \
-+ { \
-+ char __tmp = *__a; \
-+ *__a++ = *__b; \
-+ *__b++ = __tmp; \
-+ } while (--__size > 0); \
-+ } while (0)
-+
-+/* Discontinue quicksort algorithm when partition gets below this size.
-+ This particular magic number was chosen to work best on a Sun 4/260. */
-+#define MAX_THRESH 4
-+
-+/* Stack node declarations used to store unfulfilled partition obligations. */
-+typedef struct
-+ {
-+ char *lo;
-+ char *hi;
-+ } stack_node;
-+
-+/* The next 4 #defines implement a very fast in-line stack abstraction. */
-+/* The stack needs log (total_elements) entries (we could even subtract
-+ log(MAX_THRESH)). Since total_elements has type size_t, we get as
-+ upper bound for log (total_elements):
-+ bits per byte (CHAR_BIT) * sizeof(size_t). */
-+#define STACK_SIZE (8 * sizeof(bfd_size_type))
-+#define PUSH(low, high) do { top->lo = (low); top->hi = (high); ++top; } while (0)
-+#define POP(low, high) do { --top; low = top->lo; high = top->hi; } while (0)
-+#define STACK_NOT_EMPTY (stack < top)
-+
-+
-+/* Order size using quicksort. This implementation incorporates
-+ four optimizations discussed in Sedgewick:
-+
-+ 1. Non-recursive, using an explicit stack of pointer that store the
-+ next array partition to sort. To save time, this maximum amount
-+ of space required to store an array of SIZE_MAX is allocated on the
-+ stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
-+ only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
-+ Pretty cheap, actually.
-+
-+ 2. Chose the pivot element using a median-of-three decision tree.
-+ This reduces the probability of selecting a bad pivot value and
-+ eliminates certain extraneous comparisons.
-+
-+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
-+ insertion sort to order the MAX_THRESH items within each partition.
-+ This is a big win, since insertion sort is faster for small, mostly
-+ sorted array segments.
-+
-+ 4. The larger of the two sub-partitions is always pushed onto the
-+ stack first, with the algorithm then concentrating on the
-+ smaller partition. This *guarantees* no more than log (total_elems)
-+ stack size is needed (actually O(1) in this case)! */
-+
-+void
-+bfd_qsort (void *pbase, bfd_size_type total_elems, bfd_size_type size,
-+ bfd_qsort_closure_func cmp, void *closure)
-+{
-+ register char *base_ptr = (char *) pbase;
-+
-+ const bfd_size_type max_thresh = MAX_THRESH * size;
-+
-+ if (total_elems == 0)
-+ /* Avoid lossage with unsigned arithmetic below. */
-+ return;
-+
-+ if (total_elems > MAX_THRESH)
-+ {
-+ char *lo = base_ptr;
-+ char *hi = &lo[size * (total_elems - 1)];
-+ stack_node stack[STACK_SIZE];
-+ stack_node *top = stack;
-+
-+ PUSH (NULL, NULL);
-+
-+ while (STACK_NOT_EMPTY)
-+ {
-+ char *left_ptr;
-+ char *right_ptr;
-+
-+ /* Select median value from among LO, MID, and HI. Rearrange
-+ LO and HI so the three values are sorted. This lowers the
-+ probability of picking a pathological pivot value and
-+ skips a comparison for both the LEFT_PTR and RIGHT_PTR in
-+ the while loops. */
-+
-+ char *mid = lo + size * ((hi - lo) / size >> 1);
-+
-+ if ((*cmp) ((void *) mid, (void *) lo, closure) < 0)
-+ SWAP (mid, lo, size);
-+ if ((*cmp) ((void *) hi, (void *) mid, closure) < 0)
-+ SWAP (mid, hi, size);
-+ else
-+ goto jump_over;
-+ if ((*cmp) ((void *) mid, (void *) lo, closure) < 0)
-+ SWAP (mid, lo, size);
-+ jump_over:;
-+
-+ left_ptr = lo + size;
-+ right_ptr = hi - size;
-+
-+ /* Here's the famous ``collapse the walls'' section of quicksort.
-+ Gotta like those tight inner loops! They are the main reason
-+ that this algorithm runs much faster than others. */
-+ do
-+ {
-+ while ((*cmp) ((void *) left_ptr, (void *) mid, closure) < 0)
-+ left_ptr += size;
-+
-+ while ((*cmp) ((void *) mid, (void *) right_ptr, closure) < 0)
-+ right_ptr -= size;
-+
-+ if (left_ptr < right_ptr)
-+ {
-+ SWAP (left_ptr, right_ptr, size);
-+ if (mid == left_ptr)
-+ mid = right_ptr;
-+ else if (mid == right_ptr)
-+ mid = left_ptr;
-+ left_ptr += size;
-+ right_ptr -= size;
-+ }
-+ else if (left_ptr == right_ptr)
-+ {
-+ left_ptr += size;
-+ right_ptr -= size;
-+ break;
-+ }
-+ }
-+ while (left_ptr <= right_ptr);
-+
-+ /* Set up pointers for next iteration. First determine whether
-+ left and right partitions are below the threshold size. If so,
-+ ignore one or both. Otherwise, push the larger partition's
-+ bounds on the stack and continue sorting the smaller one. */
-+
-+ if ((bfd_size_type) (right_ptr - lo) <= max_thresh)
-+ {
-+ if ((bfd_size_type) (hi - left_ptr) <= max_thresh)
-+ /* Ignore both small partitions. */
-+ POP (lo, hi);
-+ else
-+ /* Ignore small left partition. */
-+ lo = left_ptr;
-+ }
-+ else if ((bfd_size_type) (hi - left_ptr) <= max_thresh)
-+ /* Ignore small right partition. */
-+ hi = right_ptr;
-+ else if ((right_ptr - lo) > (hi - left_ptr))
-+ {
-+ /* Push larger left partition indices. */
-+ PUSH (lo, right_ptr);
-+ lo = left_ptr;
-+ }
-+ else
-+ {
-+ /* Push larger right partition indices. */
-+ PUSH (left_ptr, hi);
-+ hi = right_ptr;
-+ }
-+ }
-+ }
-+
-+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
-+ is completely sorted using insertion sort, since this is efficient
-+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
-+ of the array to sort, and END_PTR points at the very last element in
-+ the array (*not* one beyond it!). */
-+
-+#define min(x, y) ((x) < (y) ? (x) : (y))
-+
-+ {
-+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
-+ char *tmp_ptr = base_ptr;
-+ char *thresh = min(end_ptr, base_ptr + max_thresh);
-+ register char *run_ptr;
-+
-+ /* Find smallest element in first threshold and place it at the
-+ array's beginning. This is the smallest array element,
-+ and the operation speeds up insertion sort's inner loop. */
-+
-+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
-+ if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, closure) < 0)
-+ tmp_ptr = run_ptr;
-+
-+ if (tmp_ptr != base_ptr)
-+ SWAP (tmp_ptr, base_ptr, size);
-+
-+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
-+
-+ run_ptr = base_ptr + size;
-+ while ((run_ptr += size) <= end_ptr)
-+ {
-+ tmp_ptr = run_ptr - size;
-+ while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, closure) < 0)
-+ tmp_ptr -= size;
-+
-+ tmp_ptr += size;
-+ if (tmp_ptr != run_ptr)
-+ {
-+ char *trav;
-+
-+ trav = run_ptr + size;
-+ while (--trav >= run_ptr)
-+ {
-+ char c = *trav;
-+ char *hi, *lo;
-+
-+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
-+ *hi = *lo;
-+ *hi = c;
-+ }
-+ }
-+ }
-+ }
-+}