summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schlemmer <azarah@gentoo.org>2003-10-05 02:20:37 +0000
committerMartin Schlemmer <azarah@gentoo.org>2003-10-05 02:20:37 +0000
commite41c4d8bb52c8f5c2f45deee7774694d0a55b0da (patch)
treefcf90b4ef326019611c1b5db5def5c4305e5d133 /sys-devel
parentUpdate patches (diff)
downloadhistorical-e41c4d8bb52c8f5c2f45deee7774694d0a55b0da.tar.gz
historical-e41c4d8bb52c8f5c2f45deee7774694d0a55b0da.tar.bz2
historical-e41c4d8bb52c8f5c2f45deee7774694d0a55b0da.zip
Update patches
Diffstat (limited to 'sys-devel')
-rw-r--r--sys-devel/binutils/Manifest5
-rw-r--r--sys-devel/binutils/binutils-2.14.90.0.6-r4.ebuild205
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-eh-frame-ro-2.patch427
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-howto.patch37
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-sdata.patch33
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-speedup.patch314
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-merge-speedup.patch740
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-sparc-cfi.patch367
-rw-r--r--sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r41
9 files changed, 2127 insertions, 2 deletions
diff --git a/sys-devel/binutils/Manifest b/sys-devel/binutils/Manifest
index 66ab7fd7212b..fabf6c6fc6d0 100644
--- a/sys-devel/binutils/Manifest
+++ b/sys-devel/binutils/Manifest
@@ -6,10 +6,10 @@ MD5 bc3f212a30ea4168eaf3b97df6d552ac binutils-2.14.90.0.6-r3.ebuild 6018
MD5 0128e4349da81a9b35d368f3f5457d08 binutils-2.14.90.0.6-r1.ebuild 5115
MD5 b7ddfee30d6b7884c1b9088c6fde759d binutils-2.13.90.0.16-r1.ebuild 4661
MD5 1b11085f74185bfe7061a6fb01d62ebd binutils-2.12.90.0.15.ebuild 3501
-MD5 f94a95cd137c0cc794cd93b62078219d ChangeLog 16477
+MD5 dd51081dd69d908fd59eee586387256d ChangeLog 17076
MD5 b7db6fb32b4653b2832c60bc12dce7a1 binutils-2.11.92.0.7.ebuild 2325
MD5 0605cad192892662d9ab7bcf4292a278 binutils-2.11.92.0.12.3-r2.ebuild 3047
-MD5 7774199cffbb0dc812bf1229f7076919 binutils-2.14.90.0.6-r4.ebuild 6284
+MD5 eef83daafb41a3e0beafc59446a00002 binutils-2.14.90.0.6-r4.ebuild 6284
MD5 87e2477ba1072a1fc76af67ab531b0a2 binutils-2.14.90.0.4.1-r1.ebuild 6288
MD5 92e0fa5133dbba4ffefc25a217f28686 binutils-2.14.90.0.5-r1.ebuild 5781
MD5 3b32997c2ca6b9893839c439e077e82d files/digest-binutils-2.14.90.0.6-r1 75
@@ -92,5 +92,6 @@ MD5 613770b55db9f6e3c11f040a94c9c4ea files/2.14/binutils-2.14.90.0.4-cfi4.patch
MD5 60ff948d89725566178e8149375c3f31 files/2.14/binutils-2.14.90.0.4-gas-execstack.patch 3379
MD5 951847a76c7f1ad39d4eb7eeff4b9ca2 files/2.14/binutils-2.14.90.0.6-cxx-speedup.patch 24221
MD5 8ca75664936a5e5043c6036bacbf88dc files/2.14/binutils-2.14.90.0.6-hppa-static.diff 2764
+MD5 09de3fa664f792872af4d6a029909315 files/2.14/binutils-2.14.90.0.6-eh-frame-ro.patch 14503
MD5 5fa7bd6f7e2c4fa50b74367a85f37541 files/2.14/binutils-2.14.90.0.4-ppc64-prelink.patch 4721
MD5 e7283a4967ce5101a016b31e747e8442 files/2.14/binutils-2.14.90.0.4-cfi2.patch 18449
diff --git a/sys-devel/binutils/binutils-2.14.90.0.6-r4.ebuild b/sys-devel/binutils/binutils-2.14.90.0.6-r4.ebuild
new file mode 100644
index 000000000000..775b21716c0d
--- /dev/null
+++ b/sys-devel/binutils/binutils-2.14.90.0.6-r4.ebuild
@@ -0,0 +1,205 @@
+# Copyright 1999-2003 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/binutils/binutils-2.14.90.0.6-r4.ebuild,v 1.1 2003/10/05 02:20:24 azarah Exp $
+
+IUSE="nls bootstrap build"
+
+# NOTE to Maintainer: ChangeLog states that it no longer use perl to build
+# the manpages, but seems this is incorrect ....
+
+inherit eutils libtool flag-o-matic
+
+# Generate borked binaries. Bug #6730
+filter-flags "-fomit-frame-pointer -fssa"
+
+S="${WORKDIR}/${P}"
+DESCRIPTION="Tools necessary to build programs"
+SRC_URI="mirror://kernel/linux/devel/binutils/${P}.tar.bz2
+ mirror://kernel/linux/devel/binutils/test/${P}.tar.bz2"
+HOMEPAGE="http://sources.redhat.com/binutils/"
+
+SLOT="0"
+LICENSE="GPL-2 | LGPL-2"
+KEYWORDS="~amd64 ~x86 ~ppc ~alpha ~sparc ~mips ~hppa ~arm ~ia64"
+
+DEPEND="virtual/glibc
+ >=sys-apps/portage-2.0.21
+ nls? ( sys-devel/gettext )
+ || ( dev-lang/perl
+ ( !build? ( dev-lang/perl ) )
+ ( !bootstrap? ( dev-lang/perl ) )
+ )"
+# This is a hairy one. Basically depend on dev-lang/perl
+# if "build" or "bootstrap" not in USE.
+
+
+# filter CFLAGS=".. -O2 .." on arm
+if [ "${ARCH}" = "arm" ]; then
+ CFLAGS="$(echo "${CFLAGS}" | sed -e 's,-O[2-9] ,-O1 ,')"
+fi
+
+src_unpack() {
+
+ unpack ${A}
+
+ cd ${S}
+ epatch ${FILESDIR}/2.13/${PN}-2.13.90.0.10-glibc21.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.4-sparc-nonpic.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-sparc-cfi.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-eh-frame-ro-2.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.4-ltconfig-multilib.patch
+# Might think of adding the Prescott stuff later on
+# epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.4-pni.patch
+# This one cause failures in sash and util-linux-2.12 (bug #27330)
+# epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.5-place-orphan.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.5-s390-pie.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.5-ppc64-pie.patch
+ epatch ${FILESDIR}/2.13/${PN}-2.13.90.0.10-x86_64-testsuite.patch
+ epatch ${FILESDIR}/2.13/${PN}-2.13.90.0.10-x86_64-gotpcrel.patch
+ epatch ${FILESDIR}/2.13/${PN}-2.13.90.0.18-testsuite-Wall-fixes.patch
+ # There is a bug in binutils 2.14.* which causes a segfault in certain
+ # circumstances when linking. This bug does not exist in binutils 2.11.*.
+ #
+ # More details on the bug can be found here:
+ # http://sources.redhat.com/ml/bug-binutils/2003-q3/msg00559.html
+ # http://sources.redhat.com/ml/bug-binutils/2003-q3/msg00735.html
+ #
+ # Bug #27492, thanks to Adam Chodorowski <adam@chodorowski.com> for
+ # reporting.
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-dont-crash-on-null-owner.patch
+ # This increase c++ linking 2 to 3 times, bug #27540.
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-merge-speedup.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-bfd-elf-interp.patch
+ # Some IA64 patches
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-ia64-howto.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-ia64-sdata.patch
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-ia64-speedup.patch
+
+ if [ "${ARCH}" == "hppa" ] || [ "${ARCH}" == "hppa64" ]
+ then
+ epatch ${FILESDIR}/2.14/${PN}-2.14.90.0.6-hppa-static.diff
+ fi
+ if [ "${ARCH}" == "amd64" ]
+ then
+ epatch ${FILESDIR}/${PN}-2.14.amd64-32bit-path-fix.patch
+ fi
+
+ use x86 &> /dev/null \
+ && epatch ${FILESDIR}/2.13/${PN}-2.13.90.0.20-array-sects-compat.patch
+
+ # Libtool is broken (Redhat).
+ for x in ${S}/opcodes/Makefile.{am,in}
+ do
+ cp ${x} ${x}.orig
+ gawk '
+ {
+ if ($0 ~ /LIBADD/)
+ gsub("../bfd/libbfd.la", "-L../bfd/.libs ../bfd/libbfd.la")
+
+ print
+ }' ${x}.orig > ${x}
+ rm -rf ${x}.orig
+ done
+}
+
+src_compile() {
+ local myconf=
+
+ use nls && \
+ myconf="${myconf} --without-included-gettext" || \
+ myconf="${myconf} --disable-nls"
+
+ # Fix /usr/lib/libbfd.la
+ elibtoolize --portage
+
+ ./configure --enable-shared \
+ --enable-64-bit-bfd \
+ --prefix=/usr \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --host=${CHOST} \
+ ${myconf} || die
+
+ make configure-bfd || die
+ make headers -C bfd || die
+ emake tooldir="${ROOT}/usr/bin" \
+ all || die
+
+ if [ -z "`use build`" ]
+ then
+ if [ -z "`use bootstrap`" ]
+ then
+ # Nuke the manpages to recreate them (only use this if we have perl)
+ find . -name '*.1' -exec rm -f {} \; || :
+ fi
+ # Make the info pages (makeinfo included with gcc is used)
+ make info || die
+ fi
+}
+
+src_install() {
+
+ make prefix=${D}/usr \
+ mandir=${D}/usr/share/man \
+ infodir=${D}/usr/share/info \
+ install || die
+
+ insinto /usr/include
+ doins include/libiberty.h
+
+ # c++filt is included with gcc -- what are these GNU people thinking?
+ # but not the manpage, so leave that!
+# We install it now, as gcc-3.3 do not have it any longer ...
+# rm -f ${D}/usr/bin/c++filt #${D}/usr/share/man/man1/c++filt*
+
+ # By default strip has a symlink going from /usr/${CHOST}/bin/strip to
+ # /usr/bin/strip we should reverse it:
+
+ rm ${D}/usr/${CHOST}/bin/strip; mv ${D}/usr/bin/strip ${D}/usr/${CHOST}/bin/strip
+ # The strip symlink gets created in the loop below
+
+ # By default ar, as, ld, nm, ranlib and strip are in two places; create
+ # symlinks. This will reduce the size of the tbz2 significantly. We also
+ # move all the stuff in /usr/bin to /usr/${CHOST}/bin and create the
+ # appropriate symlinks. Things are cleaner that way.
+ cd ${D}/usr/bin
+ local x=
+ for x in * strip
+ do
+ if [ ! -e ../${CHOST}/bin/${x} ]
+ then
+ mv ${x} ../${CHOST}/bin/${x}
+ else
+ rm -f ${x}
+ fi
+ ln -s ../${CHOST}/bin/${x} ${x}
+ done
+
+ cd ${S}
+ if [ -z "`use build`" ]
+ then
+ make prefix=${D}/usr \
+ mandir=${D}/usr/share/man \
+ infodir=${D}/usr/share/info \
+ install-info || die
+
+ dodoc COPYING* README
+ docinto bfd
+ dodoc bfd/ChangeLog* bfd/COPYING bfd/README bfd/PORTING bfd/TODO
+ docinto binutils
+ dodoc binutils/ChangeLog binutils/NEWS binutils/README
+ docinto gas
+ dodoc gas/ChangeLog* gas/CONTRIBUTORS gas/COPYING gas/NEWS gas/README*
+ docinto gprof
+ dodoc gprof/ChangeLog* gprof/TEST gprof/TODO
+ docinto ld
+ dodoc ld/ChangeLog* ld/README ld/NEWS ld/TODO
+ docinto libiberty
+ dodoc libiberty/ChangeLog* libiberty/COPYING.LIB libiberty/README
+ docinto opcodes
+ dodoc opcodes/ChangeLog*
+ # Install pre-generated manpages .. currently we do not ...
+ else
+ rm -rf ${D}/usr/share/man
+ fi
+}
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-eh-frame-ro-2.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-eh-frame-ro-2.patch
new file mode 100644
index 000000000000..c0b1c13cdaff
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-eh-frame-ro-2.patch
@@ -0,0 +1,427 @@
+2002-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ * ldgram.y (sect_constraint): New.
+ (ONLY_IF_RO, ONLY_IF_RW): New tokens.
+ (section): Add sect_constraint. Pass additional argument
+ to lang_enter_output_section_statement.
+ * mri.c (mri_draw_tree): Pass additional argument to
+ lang_enter_output_section_statement.
+ * emultempl/pe.em (place_orphan): Likewise.
+ (output_prev_sec_find): Disregard output section statements with
+ constraint == -1.
+ * emultempl/mmo.em (output_prev_sec_find): Likewise.
+ (mmo_place_orphan): Pass additional argument to
+ lang_enter_output_section_statement.
+ * emultempl/elf32.em (output_prev_sec_find): Disregard output section
+ statements with constraint == -1.
+ (place_orphan): Pass additional argument to
+ lang_enter_output_section_statement.
+ * ldlang.c (lang_enter_overlay_section): Likewise.
+ (lang_output_section_find_1): New.
+ (lang_output_section_find): Use it.
+ (lang_output_section_statement_lookup_1): New.
+ (lang_output_section_statement_lookup): Use it.
+ (check_section_callback, check_input_sections): New.
+ (map_input_to_output_sections): Check if all input sections
+ are readonly if ONLY_IF_RO or ONLY_IF_RW was seen.
+ (strip_excluded_output_sections): Disregard output section statements
+ with constraint == -1.
+ (lang_record_phdrs): Likewise.
+ (lang_enter_output_section_statement): Add constraint argument.
+ Use lang_output_section_statement_lookup_1.
+ * ldlang.h (lang_output_section_statement_type): Add constraint
+ and all_input_readonly fields.
+ (lang_enter_output_section_statement): Adjust prototype.
+ * ldlex.l (ONLY_IF_RO, ONLY_IF_RW): New tokens.
+ * scripttempl/elf.sc (.eh_frame, .gcc_except_table): Move into text
+ segment if all input sections are readonly.
+
+--- ld/emultempl/mmo.em.jj Wed Jul 23 11:08:12 2003
++++ ld/emultempl/mmo.em Fri Sep 19 17:30:02 2003
+@@ -47,6 +47,8 @@ output_prev_sec_find (lang_output_sectio
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
++ if (lookup->constraint == -1)
++ continue;
+ if (lookup == os)
+ break;
+ if (lookup->bfd_section != NULL
+@@ -130,7 +132,7 @@ mmo_place_orphan (lang_input_statement_t
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- (etree_type *) NULL);
++ (etree_type *) NULL, 0);
+
+ lang_add_section (&os->children, s, os, file);
+
+--- ld/emultempl/pe.em.jj Thu Aug 21 11:28:48 2003
++++ ld/emultempl/pe.em Fri Sep 19 17:30:02 2003
+@@ -1453,6 +1453,8 @@ output_prev_sec_find (lang_output_sectio
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
++ if (lookup->constraint == -1)
++ continue;
+ if (lookup == os)
+ return s;
+
+@@ -1617,7 +1619,7 @@ gld_${EMULATION_NAME}_place_orphan (lang
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- (etree_type *) NULL);
++ (etree_type *) NULL, 0);
+
+ lang_add_section (&add_child, s, os, file);
+
+--- ld/emultempl/elf32.em.jj Thu Aug 21 11:28:48 2003
++++ ld/emultempl/elf32.em Fri Sep 19 17:30:02 2003
+@@ -1016,7 +1016,8 @@ output_rel_find (asection *sec, int isdy
+ for (u = lang_output_section_statement.head; u; u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+- if (strncmp (".rel", lookup->name, 4) == 0)
++ if (lookup->constraint != -1
++ && strncmp (".rel", lookup->name, 4) == 0)
+ {
+ int lookrela = lookup->name[4] == 'a';
+
+@@ -1264,7 +1265,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- load_base);
++ load_base, 0);
+
+ lang_add_section (&os->children, s, os, file);
+
+--- ld/scripttempl/elf.sc.jj Wed Jul 23 11:08:12 2003
++++ ld/scripttempl/elf.sc Fri Sep 19 17:30:02 2003
+@@ -283,6 +283,8 @@ cat <<EOF
+ ${CREATE_SHLIB-${SBSS2}}
+ ${OTHER_READONLY_SECTIONS}
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
++ .eh_frame ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table) }
+
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+@@ -316,8 +318,8 @@ cat <<EOF
+ .data1 ${RELOCATING-0} : { *(.data1) }
+ .tdata ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
+ .tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
+- .eh_frame ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
+- .gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
++ .eh_frame ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table) }
+ ${WRITABLE_RODATA+${RODATA}}
+ ${OTHER_READWRITE_SECTIONS}
+ ${TEXT_DYNAMIC-${DYNAMIC}}
+--- ld/ldgram.y.jj Thu Aug 21 11:28:48 2003
++++ ld/ldgram.y Fri Sep 19 17:38:10 2003
+@@ -143,14 +143,14 @@ static int error_index;
+ %token ORIGIN FILL
+ %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
+ %token ALIGNMOD AT SUBALIGN PROVIDE
+-%type <token> assign_op atype attributes_opt
++%type <token> assign_op atype attributes_opt sect_constraint
+ %type <name> filename
+ %token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
+ %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
+ %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
+ %token <name> VERS_TAG VERS_IDENTIFIER
+ %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+-%token KEEP
++%token KEEP ONLY_IF_RO ONLY_IF_RW
+ %token EXCLUDE_FILE
+ %type <versyms> vers_defns
+ %type <versnode> vers_tag
+@@ -833,22 +833,29 @@ opt_subalign:
+ | { $$ = 0; }
+ ;
+
++sect_constraint:
++ ONLY_IF_RO { $$ = ONLY_IF_RO; }
++ | ONLY_IF_RW { $$ = ONLY_IF_RW; }
++ | { $$ = 0; }
++ ;
++
+ section: NAME { ldlex_expression(); }
+ opt_exp_with_type
+ opt_at
+ opt_subalign { ldlex_popstate (); ldlex_script (); }
++ sect_constraint
+ '{'
+ {
+ lang_enter_output_section_statement($1, $3,
+ sectype,
+- 0, 0, $5, $4);
++ 0, 0, $5, $4, $7);
+ }
+ statement_list_opt
+ '}' { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+ {
+ ldlex_popstate ();
+- lang_leave_output_section_statement ($15, $12, $14, $13);
++ lang_leave_output_section_statement ($16, $13, $15, $14);
+ }
+ opt_comma
+ {}
+--- ld/mri.c.jj Wed Jul 23 11:08:12 2003
++++ ld/mri.c Fri Sep 19 17:30:02 2003
+@@ -220,7 +220,7 @@ mri_draw_tree (void)
+
+ lang_enter_output_section_statement (p->name, base,
+ p->ok_to_load ? 0 : noload_section,
+- 1, align, subalign, NULL);
++ 1, align, subalign, NULL, 0);
+ base = 0;
+ tmp = xmalloc (sizeof *tmp);
+ tmp->next = NULL;
+--- ld/ldlang.h.jj Thu Aug 21 11:28:48 2003
++++ ld/ldlang.h Fri Sep 19 17:30:02 2003
+@@ -132,6 +132,8 @@ typedef struct lang_output_section_state
+
+ int subsection_alignment; /* alignment of components */
+ int section_alignment; /* alignment of start of section */
++ int constraint;
++ bfd_boolean all_input_readonly;
+
+ union etree_union *load_base;
+
+@@ -394,7 +396,7 @@ extern lang_output_section_statement_typ
+ bfd_vma block_value,
+ etree_type *align,
+ etree_type *subalign,
+- etree_type *);
++ etree_type *, int);
+ extern void lang_final
+ (void);
+ extern void lang_process
+--- ld/ldlang.c.jj Thu Aug 21 11:28:48 2003
++++ ld/ldlang.c Fri Sep 19 17:40:21 2003
+@@ -562,7 +562,7 @@ lang_memory_default (asection *section)
+ }
+
+ lang_output_section_statement_type *
+-lang_output_section_find (const char *const name)
++lang_output_section_find_1 (const char *const name, int constraint)
+ {
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+@@ -570,18 +570,26 @@ lang_output_section_find (const char *co
+ for (u = lang_output_section_statement.head; u != NULL; u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+- if (strcmp (name, lookup->name) == 0)
++ if (strcmp (name, lookup->name) == 0
++ && lookup->constraint != -1
++ && (constraint == 0 || constraint == lookup->constraint))
+ return lookup;
+ }
+ return NULL;
+ }
+
+ lang_output_section_statement_type *
+-lang_output_section_statement_lookup (const char *const name)
++lang_output_section_find (const char *const name)
++{
++ return lang_output_section_find_1 (name, 0);
++}
++
++lang_output_section_statement_type *
++lang_output_section_statement_lookup_1 (const char *const name, int constraint)
+ {
+ lang_output_section_statement_type *lookup;
+
+- lookup = lang_output_section_find (name);
++ lookup = lang_output_section_find_1 (name, constraint);
+ if (lookup == NULL)
+ {
+ lookup = new_stat (lang_output_section_statement, stat_ptr);
+@@ -594,6 +602,7 @@ lang_output_section_statement_lookup (co
+ lookup->next = NULL;
+ lookup->bfd_section = NULL;
+ lookup->processed = FALSE;
++ lookup->constraint = constraint;
+ lookup->sectype = normal_section;
+ lookup->addr_tree = NULL;
+ lang_list_init (&lookup->children);
+@@ -613,6 +622,12 @@ lang_output_section_statement_lookup (co
+ return lookup;
+ }
+
++lang_output_section_statement_type *
++lang_output_section_statement_lookup (const char *const name)
++{
++ return lang_output_section_statement_lookup_1 (name, 0);
++}
++
+ static void
+ lang_map_flags (flagword flag)
+ {
+@@ -1278,6 +1293,30 @@ output_section_callback (lang_wild_state
+ }
+ }
+
++/* Check if all sections in a wild statement for a particular FILE
++ are readonly. */
++
++static void
++check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
++ struct wildcard_list *sec ATTRIBUTE_UNUSED,
++ asection *section,
++ lang_input_statement_type *file ATTRIBUTE_UNUSED,
++ void *output)
++{
++ /* Exclude sections that match UNIQUE_SECTION_LIST. */
++ if (unique_section_p (bfd_get_section_name (file->the_bfd, section)))
++ return;
++
++ if (section->output_section == NULL)
++ {
++ flagword flags = bfd_get_section_flags (section->owner, section);
++
++ if ((flags & SEC_READONLY) == 0)
++ ((lang_output_section_statement_type *) output)->all_input_readonly
++ = FALSE;
++ }
++}
++
+ /* This is passed a file name which must have been seen already and
+ added to the statement tree. We will see if it has been opened
+ already and had its symbols read. If not then we'll read it. */
+@@ -1923,6 +1962,40 @@ lang_place_undefineds (void)
+ insert_undefined (ptr->name);
+ }
+
++/* Check for all readonly or some readwrite sections. */
++
++static void
++check_input_sections (lang_statement_union_type *s,
++ lang_output_section_statement_type *output_section_statement)
++{
++ for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
++ {
++ switch (s->header.type)
++ {
++ case lang_wild_statement_enum:
++ walk_wild (&s->wild_statement, check_section_callback,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ case lang_constructors_statement_enum:
++ check_input_sections (constructor_list.head,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ case lang_group_statement_enum:
++ check_input_sections (s->group_statement.children.head,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ default:
++ break;
++ }
++ }
++}
++
+ /* Open input files and attach to output sections. */
+
+ static void
+@@ -1943,6 +2016,23 @@ map_input_to_output_sections
+ output_section_statement);
+ break;
+ case lang_output_section_statement_enum:
++ if (s->output_section_statement.constraint)
++ {
++ if (s->output_section_statement.constraint == -1)
++ break;
++ s->output_section_statement.all_input_readonly = TRUE;
++ check_input_sections (s->output_section_statement.children.head,
++ &s->output_section_statement);
++ if ((s->output_section_statement.all_input_readonly
++ && s->output_section_statement.constraint == ONLY_IF_RW)
++ || (!s->output_section_statement.all_input_readonly
++ && s->output_section_statement.constraint == ONLY_IF_RO))
++ {
++ s->output_section_statement.constraint = -1;
++ break;
++ }
++ }
++
+ map_input_to_output_sections (s->output_section_statement.children.head,
+ target,
+ &s->output_section_statement);
+@@ -2013,6 +2103,8 @@ strip_excluded_output_sections (void)
+ asection *s;
+
+ os = &u->output_section_statement;
++ if (os->constraint == -1)
++ continue;
+ s = os->bfd_section;
+ if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+ {
+@@ -3857,13 +3949,15 @@ lang_enter_output_section_statement (con
+ bfd_vma block_value,
+ etree_type *align,
+ etree_type *subalign,
+- etree_type *ebase)
++ etree_type *ebase,
++ int constraint)
+ {
+ lang_output_section_statement_type *os;
+
+ current_section =
+ os =
+- lang_output_section_statement_lookup (output_section_statement_name);
++ lang_output_section_statement_lookup_1 (output_section_statement_name,
++ constraint);
+
+ /* Add this statement to tree. */
+ #if 0
+@@ -4558,6 +4652,8 @@ lang_record_phdrs (void)
+ struct lang_output_section_phdr_list *pl;
+
+ os = &u->output_section_statement;
++ if (os->constraint == -1)
++ continue;
+
+ pl = os->phdrs;
+ if (pl != NULL)
+@@ -4617,7 +4713,8 @@ lang_record_phdrs (void)
+ {
+ struct lang_output_section_phdr_list *pl;
+
+- if (u->output_section_statement.bfd_section == NULL)
++ if (u->output_section_statement.constraint == -1
++ || u->output_section_statement.bfd_section == NULL)
+ continue;
+
+ for (pl = u->output_section_statement.phdrs;
+@@ -4689,7 +4786,7 @@ lang_enter_overlay_section (const char *
+ etree_type *size;
+
+ lang_enter_output_section_statement (name, overlay_vma, normal_section,
+- 0, 0, overlay_subalign, 0);
++ 0, 0, overlay_subalign, 0, 0);
+
+ /* If this is the first section, then base the VMA of future
+ sections on this one. This will work correctly even if `.' is
+--- ld/ldlex.l.jj Thu Aug 21 11:28:48 2003
++++ ld/ldlex.l Fri Sep 19 17:30:02 2003
+@@ -299,6 +299,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^]([*?
+ <EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);}
+ <EXPRESSION,BOTH,SCRIPT>"INFO" { RTOKEN(INFO);}
+ <EXPRESSION,BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY);}
++<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); }
++<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); }
+ <BOTH,SCRIPT>"o" { RTOKEN(ORIGIN);}
+ <BOTH,SCRIPT>"org" { RTOKEN(ORIGIN);}
+ <BOTH,SCRIPT>"l" { RTOKEN( LENGTH);}
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-howto.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-howto.patch
new file mode 100644
index 000000000000..bee66b64da38
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-howto.patch
@@ -0,0 +1,37 @@
+2003-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ * elfxx-ia64.c (ia64_howto_table): Fix size of R_IA64_TPREL64[LM]SB,
+ R_IA64_DTPREL{32,64}[LM]SB and R_IA64_DTPMOD64[LM]SB.
+
+--- bfd/elfxx-ia64.c.jj 2003-09-30 16:44:32.000000000 +0200
++++ bfd/elfxx-ia64.c 2003-09-30 17:53:11.000000000 +0200
+@@ -446,21 +446,21 @@ static reloc_howto_type ia64_howto_table
+ IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
+
+- IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 4, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
+
+ IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, FALSE, FALSE),
+- IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
++ IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
+ };
+
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-sdata.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-sdata.patch
new file mode 100644
index 000000000000..55a8f67fa72d
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-sdata.patch
@@ -0,0 +1,33 @@
+2003-09-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elfxx-ia64.c (elfNN_ia64_special_sections): Mark all sections
+ started with ".sbss" or "".sdata" as SHF_IA_64_SHORT.
+
+2003-08-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elfxx-ia64.c (elfNN_ia64_create_dynamic_sections): Align the
+ .got section at 8 bytes.
+
+--- bfd/elfxx-ia64.c 20 Aug 2003 08:37:18 -0000 1.98
++++ bfd/elfxx-ia64.c 10 Sep 2003 20:48:32 -0000 1.100
+@@ -1781,6 +1781,8 @@ elfNN_ia64_create_dynamic_sections (abfd
+ {
+ flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
+ bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
++ /* The .got section is always aligned at 8 bytes. */
++ bfd_set_section_alignment (abfd, ia64_info->got_sec, 3);
+ }
+
+ if (!get_pltoff (abfd, info, ia64_info))
+@@ -4746,9 +4748,9 @@ elfNN_ia64_reloc_type_class (rela)
+
+ static struct bfd_elf_special_section const elfNN_ia64_special_sections[]=
+ {
+- { ".sbss", 0, NULL, 0,
++ { ".sbss", 5, NULL, 0,
+ SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
+- { ".sdata", 0, NULL, 0,
++ { ".sdata", 6, NULL, 0,
+ SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
+ { NULL, 0, NULL, 0,
+ 0, 0 }
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-speedup.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-speedup.patch
new file mode 100644
index 000000000000..d93f6e98c351
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-ia64-speedup.patch
@@ -0,0 +1,314 @@
+2003-09-11 Jakub Jelinek <jakub@redhat.com>
+
+ * elfxx-ia64.c: Include objalloc.h, hashtab.h.
+ (struct elfNN_ia64_local_hash_entry): Remove root. Add id and r_sym
+ fields.
+ (struct elfNN_ia64_local_hash_table): Remove.
+ (struct elfNN_ia64_link_hash_table): Change loc_hash_table's type
+ to htab_t. Add loc_hash_memory field.
+ (elfNN_ia64_local_hash_table_init, elfNN_ia64_new_loc_hash_entry):
+ Removed.
+ (elfNN_ia64_local_htab_hash, elfNN_ia64_local_htab_eq): New
+ functions.
+ (elfNN_ia64_hash_table_create): Use hashtab.h hashtable for
+ loc_hash_table. Initialize loc_hash_memory.
+ (elfNN_ia64_hash_table_free): New function.
+ (elfNN_ia64_local_hash_lookup): Remove.
+ (elfNN_ia64_local_dyn_sym_thunk): Change into htab_traverse
+ callback.
+ (elfNN_ia64_dyn_sym_traverse): Use htab_traverse.
+ (get_local_sym_hash): Use hashtab.h hashtable for loc_hash_table.
+ (bfd_elfNN_bfd_link_hash_table_free): Define.
+
+--- bfd/elfxx-ia64.c.jj 2003-09-18 05:30:39.000000000 -0400
++++ bfd/elfxx-ia64.c 2003-09-18 07:37:36.000000000 -0400
+@@ -24,6 +24,8 @@
+ #include "elf-bfd.h"
+ #include "opcode/ia64.h"
+ #include "elf/ia64.h"
++#include "objalloc.h"
++#include "hashtab.h"
+
+ /* THE RULES for all the stuff the linker creates --
+
+@@ -115,7 +117,8 @@ struct elfNN_ia64_dyn_sym_info
+
+ struct elfNN_ia64_local_hash_entry
+ {
+- struct bfd_hash_entry root;
++ int id;
++ unsigned int r_sym;
+ struct elfNN_ia64_dyn_sym_info *info;
+
+ /* TRUE if this hash entry's addends was translated for
+@@ -123,12 +126,6 @@ struct elfNN_ia64_local_hash_entry
+ unsigned sec_merge_done : 1;
+ };
+
+-struct elfNN_ia64_local_hash_table
+-{
+- struct bfd_hash_table root;
+- /* No additional fields for now. */
+-};
+-
+ struct elfNN_ia64_link_hash_entry
+ {
+ struct elf_link_hash_entry root;
+@@ -153,7 +150,8 @@ struct elfNN_ia64_link_hash_table
+ unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
+ bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */
+
+- struct elfNN_ia64_local_hash_table loc_hash_table;
++ htab_t loc_hash_table;
++ void *loc_hash_memory;
+ };
+
+ struct elfNN_ia64_allocate_data
+@@ -201,12 +199,6 @@ static bfd_boolean elfNN_ia64_is_local_l
+ PARAMS ((bfd *abfd, const char *name));
+ static bfd_boolean elfNN_ia64_dynamic_symbol_p
+ PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
+-static bfd_boolean elfNN_ia64_local_hash_table_init
+- PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,
+- new_hash_entry_func new));
+-static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry
+- PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
+- const char *string));
+ static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
+ PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
+ const char *string));
+@@ -215,15 +207,17 @@ static void elfNN_ia64_hash_copy_indirec
+ struct elf_link_hash_entry *));
+ static void elfNN_ia64_hash_hide_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
++static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *));
++static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1,
++ const void *ptr2));
+ static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
+ PARAMS ((bfd *abfd));
+-static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup
+- PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string,
+- bfd_boolean create, bfd_boolean copy));
++static void elfNN_ia64_hash_table_free
++ PARAMS ((struct bfd_link_hash_table *hash));
+ static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
+ PARAMS ((struct bfd_hash_entry *, PTR));
+-static bfd_boolean elfNN_ia64_local_dyn_sym_thunk
+- PARAMS ((struct bfd_hash_entry *, PTR));
++static int elfNN_ia64_local_dyn_sym_thunk
++ PARAMS ((void **, PTR));
+ static void elfNN_ia64_dyn_sym_traverse
+ PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
+ bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
+@@ -1520,44 +1514,6 @@ elfNN_ia64_dynamic_symbol_p (h, info, r_
+ return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected);
+ }
+
+-static bfd_boolean
+-elfNN_ia64_local_hash_table_init (ht, abfd, new)
+- struct elfNN_ia64_local_hash_table *ht;
+- bfd *abfd ATTRIBUTE_UNUSED;
+- new_hash_entry_func new;
+-{
+- memset (ht, 0, sizeof (*ht));
+- return bfd_hash_table_init (&ht->root, new);
+-}
+-
+-static struct bfd_hash_entry*
+-elfNN_ia64_new_loc_hash_entry (entry, table, string)
+- struct bfd_hash_entry *entry;
+- struct bfd_hash_table *table;
+- const char *string;
+-{
+- struct elfNN_ia64_local_hash_entry *ret;
+- ret = (struct elfNN_ia64_local_hash_entry *) entry;
+-
+- /* Allocate the structure if it has not already been allocated by a
+- subclass. */
+- if (!ret)
+- ret = bfd_hash_allocate (table, sizeof (*ret));
+-
+- if (!ret)
+- return 0;
+-
+- /* Initialize our local data. All zeros, and definitely easier
+- than setting a handful of bit fields. */
+- memset (ret, 0, sizeof (*ret));
+-
+- /* Call the allocation method of the superclass. */
+- ret = ((struct elfNN_ia64_local_hash_entry *)
+- bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+-
+- return (struct bfd_hash_entry *) ret;
+-}
+-
+ static struct bfd_hash_entry*
+ elfNN_ia64_new_elf_hash_entry (entry, table, string)
+ struct bfd_hash_entry *entry;
+@@ -1657,6 +1613,33 @@ elfNN_ia64_hash_hide_symbol (info, xh, f
+ }
+ }
+
++/* Compute a hash of a local hash entry. */
++
++static hashval_t
++elfNN_ia64_local_htab_hash (ptr)
++ const void *ptr;
++{
++ struct elfNN_ia64_local_hash_entry *entry
++ = (struct elfNN_ia64_local_hash_entry *) ptr;
++
++ return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8))
++ ^ entry->r_sym ^ (entry->id >> 16);
++}
++
++/* Compare local hash entries. */
++
++static int
++elfNN_ia64_local_htab_eq (ptr1, ptr2)
++ const void *ptr1, *ptr2;
++{
++ struct elfNN_ia64_local_hash_entry *entry1
++ = (struct elfNN_ia64_local_hash_entry *) ptr1;
++ struct elfNN_ia64_local_hash_entry *entry2
++ = (struct elfNN_ia64_local_hash_entry *) ptr2;
++
++ return entry1->id == entry2->id && entry1->r_sym == entry2->r_sym;
++}
++
+ /* Create the derived linker hash table. The IA-64 ELF port uses this
+ derived hash table to keep information specific to the IA-64 ElF
+ linker (without using static variables). */
+@@ -1678,8 +1661,10 @@ elfNN_ia64_hash_table_create (abfd)
+ return 0;
+ }
+
+- if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
+- elfNN_ia64_new_loc_hash_entry))
++ ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash,
++ elfNN_ia64_local_htab_eq, NULL);
++ ret->loc_hash_memory = objalloc_create ();
++ if (!ret->loc_hash_table || !ret->loc_hash_memory)
+ {
+ free (ret);
+ return 0;
+@@ -1688,16 +1673,19 @@ elfNN_ia64_hash_table_create (abfd)
+ return &ret->root.root;
+ }
+
+-/* Look up an entry in a Alpha ELF linker hash table. */
++/* Destroy IA-64 linker hash table. */
+
+-static INLINE struct elfNN_ia64_local_hash_entry *
+-elfNN_ia64_local_hash_lookup(table, string, create, copy)
+- struct elfNN_ia64_local_hash_table *table;
+- const char *string;
+- bfd_boolean create, copy;
++static void
++elfNN_ia64_hash_table_free (hash)
++ struct bfd_link_hash_table *hash;
+ {
+- return ((struct elfNN_ia64_local_hash_entry *)
+- bfd_hash_lookup (&table->root, string, create, copy));
++ struct elfNN_ia64_link_hash_table *ia64_info
++ = (struct elfNN_ia64_link_hash_table *) hash;
++ if (ia64_info->loc_hash_table)
++ htab_delete (ia64_info->loc_hash_table);
++ if (ia64_info->loc_hash_memory)
++ objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
++ _bfd_generic_link_hash_table_free (hash);
+ }
+
+ /* Traverse both local and global hash tables. */
+@@ -1729,20 +1717,20 @@ elfNN_ia64_global_dyn_sym_thunk (xentry,
+ }
+
+ static bfd_boolean
+-elfNN_ia64_local_dyn_sym_thunk (xentry, xdata)
+- struct bfd_hash_entry *xentry;
++elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
++ void **slot;
+ PTR xdata;
+ {
+ struct elfNN_ia64_local_hash_entry *entry
+- = (struct elfNN_ia64_local_hash_entry *) xentry;
++ = (struct elfNN_ia64_local_hash_entry *) *slot;
+ struct elfNN_ia64_dyn_sym_traverse_data *data
+ = (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
+ struct elfNN_ia64_dyn_sym_info *dyn_i;
+
+ for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
+ if (! (*data->func) (dyn_i, data->data))
+- return FALSE;
+- return TRUE;
++ return 0;
++ return 1;
+ }
+
+ static void
+@@ -1758,8 +1746,8 @@ elfNN_ia64_dyn_sym_traverse (ia64_info,
+
+ elf_link_hash_traverse (&ia64_info->root,
+ elfNN_ia64_global_dyn_sym_thunk, &xdata);
+- bfd_hash_traverse (&ia64_info->loc_hash_table.root,
+- elfNN_ia64_local_dyn_sym_thunk, &xdata);
++ htab_traverse (ia64_info->loc_hash_table,
++ elfNN_ia64_local_dyn_sym_thunk, &xdata);
+ }
+
+ static bfd_boolean
+@@ -1819,22 +1807,33 @@ get_local_sym_hash (ia64_info, abfd, rel
+ const Elf_Internal_Rela *rel;
+ bfd_boolean create;
+ {
+- struct elfNN_ia64_local_hash_entry *ret;
++ struct elfNN_ia64_local_hash_entry e, *ret;
+ asection *sec = abfd->sections;
+- char addr_name [34];
++ hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8))
++ ^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16);
++ void **slot;
++
++ e.id = sec->id;
++ e.r_sym = ELFNN_R_SYM (rel->r_info);
++ slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
++ create ? INSERT : NO_INSERT);
+
+- BFD_ASSERT ((sizeof (sec->id)*2 + 1 + sizeof (unsigned long)*2 + 1) <= 34);
+- BFD_ASSERT (sec);
+-
+- /* Construct a string for use in the elfNN_ia64_local_hash_table.
+- name describes what was once anonymous memory. */
++ if (!slot)
++ return NULL;
+
+- sprintf (addr_name, "%x:%lx",
+- sec->id, (unsigned long) ELFNN_R_SYM (rel->r_info));
++ if (*slot)
++ return (struct elfNN_ia64_local_hash_entry *) *slot;
+
+- /* Collect the canonical entry data for this address. */
+- ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
+- addr_name, create, create);
++ ret = (struct elfNN_ia64_local_hash_entry *)
++ objalloc_alloc ((struct objalloc *) ia64_info->loc_hash_memory,
++ sizeof (struct elfNN_ia64_local_hash_entry));
++ if (ret)
++ {
++ memset (ret, 0, sizeof (*ret));
++ ret->id = sec->id;
++ ret->r_sym = ELFNN_R_SYM (rel->r_info);
++ *slot = ret;
++ }
+ return ret;
+ }
+
+@@ -4823,6 +4822,8 @@ elfNN_hpux_backend_section_from_bfd_sect
+ /* Stuff for the BFD linker: */
+ #define bfd_elfNN_bfd_link_hash_table_create \
+ elfNN_ia64_hash_table_create
++#define bfd_elfNN_bfd_link_hash_table_free \
++ elfNN_ia64_hash_table_free
+ #define elf_backend_create_dynamic_sections \
+ elfNN_ia64_create_dynamic_sections
+ #define elf_backend_check_relocs \
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-merge-speedup.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-merge-speedup.patch
new file mode 100644
index 000000000000..671538cd05b8
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-merge-speedup.patch
@@ -0,0 +1,740 @@
+2003-09-10 Lars Knoll <lars@trolltech.com>
+ Michael Matz <matz@suse.de>
+ Alan Modra <amodra@bigpond.net.au>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * merge.c (struct elf_strtab_hash_entry): Make len signed.
+ Remove u.next field.
+ (cmplengthentry, last4_eq, last_eq): Delete.
+ (strrevcmp, strrevcmp_align, is_suffix): New.
+ (merge_strings): Use them to implement fast suffix merging.
+ * elf-strtab.c (cmplengthentry, last4_eq): Delete.
+ (strrevcmp, is_suffix): New.
+ (_bfd_elf_strtab_finalize): Rework to implement fast suffix merging.
+
+ * ld-elf/merge2.s: New test.
+ * ld-elf/merge2.d: New.
+
+--- bfd/elf-strtab.c.jj 2002-12-16 15:22:51.000000000 -0500
++++ bfd/elf-strtab.c 2003-09-18 07:24:00.000000000 -0400
+@@ -1,5 +1,5 @@
+ /* ELF strtab with GC and suffix merging support.
+- Copyright 2001, 2002 Free Software Foundation, Inc.
++ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Written by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of BFD, the Binary File Descriptor library.
+@@ -30,15 +30,14 @@
+ struct elf_strtab_hash_entry
+ {
+ struct bfd_hash_entry root;
+- /* Length of this entry. */
+- unsigned int len;
++ /* Length of this entry. This includes the zero terminator. */
++ int len;
+ unsigned int refcount;
+ union {
+ /* Index within the merged section. */
+ bfd_size_type index;
+- /* Entry this is a suffix of (if len is 0). */
++ /* Entry this is a suffix of (if len < 0). */
+ struct elf_strtab_hash_entry *suffix;
+- struct elf_strtab_hash_entry *next;
+ } u;
+ };
+
+@@ -158,6 +157,8 @@ _bfd_elf_strtab_add (struct elf_strtab_h
+ if (entry->len == 0)
+ {
+ entry->len = strlen (str) + 1;
++ /* 2G strings lose. */
++ BFD_ASSERT (entry->len > 0);
+ if (tab->size == tab->alloced)
+ {
+ bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *);
+@@ -235,14 +236,14 @@ _bfd_elf_strtab_emit (register bfd *abfd
+ for (i = 1; i < tab->size; ++i)
+ {
+ register const char *str;
+- register size_t len;
++ register unsigned int len;
+
+- str = tab->array[i]->root.string;
+- len = tab->array[i]->len;
+ BFD_ASSERT (tab->array[i]->refcount == 0);
+- if (len == 0)
++ len = tab->array[i]->len;
++ if ((int) len < 0)
+ continue;
+
++ str = tab->array[i]->root.string;
+ if (bfd_bwrite (str, len, abfd) != len)
+ return FALSE;
+
+@@ -256,37 +257,38 @@ _bfd_elf_strtab_emit (register bfd *abfd
+ /* Compare two elf_strtab_hash_entry structures. This is called via qsort. */
+
+ static int
+-cmplengthentry (const void *a, const void *b)
++strrevcmp (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;
++ unsigned int lenA = A->len;
++ unsigned int lenB = B->len;
++ const unsigned char *s = A->root.string + lenA - 1;
++ const unsigned char *t = B->root.string + lenB - 1;
++ int l = lenA < lenB ? lenA : lenB;
+
+- 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);
++ while (l)
++ {
++ if (*s != *t)
++ return (int) *s - (int) *t;
++ s--;
++ t--;
++ l--;
++ }
++ return lenA - lenB;
+ }
+
+ static int
+-last4_eq (const void *a, const void *b)
++is_suffix (const struct elf_strtab_hash_entry *A,
++ const struct elf_strtab_hash_entry *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
+ not to be equal by the hash table. */
+ return 0;
+
+ return memcmp (A->root.string + (A->len - B->len),
+- B->root.string, B->len - 5) == 0;
++ B->root.string, B->len - 1) == 0;
+ }
+
+ /* This function assigns final string table offsets for used strings,
+@@ -295,10 +297,8 @@ last4_eq (const void *a, const void *b)
+ void
+ _bfd_elf_strtab_finalize (struct elf_strtab_hash *tab)
+ {
+- struct elf_strtab_hash_entry **array, **a, **end, *e;
+- htab_t last4tab = NULL;
++ struct elf_strtab_hash_entry **array, **a, *e;
+ 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.
+@@ -306,105 +306,71 @@ _bfd_elf_strtab_finalize (struct elf_str
+ cycles. */
+ size_t i;
+
+- /* Now sort the strings by length, longest first. */
+- array = NULL;
++ /* Sort the strings by suffix and length. */
+ 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];
+- else
+- tab->array[i]->len = 0;
++ {
++ e = tab->array[i];
++ if (e->refcount)
++ {
++ *a++ = e;
++ /* Adjust the length to not include the zero terminator. */
++ e->len -= 1;
++ }
++ else
++ e->len = 0;
++ }
+
+ size = a - array;
++ if (size != 0)
++ {
++ qsort (array, size, sizeof (struct elf_strtab_hash_entry *), strrevcmp);
+
+- qsort (array, size, sizeof (struct elf_strtab_hash_entry *), cmplengthentry);
++ /* Loop over the sorted array and merge suffixes. Start from the
++ end because we want eg.
+
+- last4tab = htab_create_alloc (size * 4, NULL, last4_eq, NULL, calloc, free);
+- if (last4tab == NULL)
+- goto alloc_failure;
++ s1 -> "d"
++ s2 -> "bcd"
++ s3 -> "abcd"
+
+- /* 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;
++ to end up as
+
+- 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;
++ s3 -> "abcd"
++ s2 _____^
++ s1 _______^
+
+- ent = *p;
+- e->u.suffix = ent;
+- e->len = 0;
+- continue;
+- }
+- else
+- *p = e;
+- }
+- else
++ ie. we don't want s1 pointing into the old s2. */
++ e = *--a;
++ e->len += 1;
++ while (--a >= array)
+ {
+- struct elf_strtab_hash_entry *tem;
++ struct elf_strtab_hash_entry *cmp = *a;
+
+- 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)
++ cmp->len += 1;
++ if (is_suffix (e, cmp))
+ {
+- e->u.suffix = tem;
+- e->len = 0;
+- continue;
++ cmp->u.suffix = e;
++ cmp->len = -cmp->len;
+ }
++ else
++ e = cmp;
+ }
+-
+- 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. */
++ /* Assign positions to the strings we want to keep. */
+ size = 1;
+ for (i = 1; i < tab->size; ++i)
+ {
+ e = tab->array[i];
+- if (e->refcount && e->len)
++ if (e->refcount && e->len > 0)
+ {
+ e->u.index = size;
+ size += e->len;
+@@ -413,12 +379,11 @@ alloc_failure:
+
+ tab->sec_size = size;
+
+- /* And now adjust the rest. */
++ /* Adjust the rest. */
+ for (i = 1; i < tab->size; ++i)
+ {
+ e = tab->array[i];
+- if (e->refcount && ! e->len)
+- e->u.index = e->u.suffix->u.index
+- + (e->u.suffix->len - strlen (e->root.string) - 1);
++ if (e->refcount && e->len < 0)
++ e->u.index = e->u.suffix->u.index + (e->u.suffix->len + e->len);
+ }
+ }
+--- bfd/merge.c.jj 2002-12-16 15:22:52.000000000 -0500
++++ bfd/merge.c 2003-09-18 07:24:32.000000000 -0400
+@@ -1,5 +1,5 @@
+ /* SEC_MERGE support.
+- Copyright 2001, 2002 Free Software Foundation, Inc.
++ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Written by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of BFD, the Binary File Descriptor library.
+@@ -34,7 +34,7 @@ struct sec_merge_sec_info;
+ struct sec_merge_hash_entry
+ {
+ struct bfd_hash_entry root;
+- /* Length of this entry. */
++ /* Length of this entry. This includes the zero terminator. */
+ unsigned int len;
+ /* Start of this string needs to be aligned to
+ alignment octets (not 1 << align). */
+@@ -43,8 +43,6 @@ struct sec_merge_hash_entry
+ {
+ /* Index within the merged section. */
+ bfd_size_type index;
+- /* Entity size (if present in suffix hash tables). */
+- unsigned int entsize;
+ /* Entry this is a suffix of (if alignment is 0). */
+ struct sec_merge_hash_entry *suffix;
+ } u;
+@@ -108,12 +106,10 @@ static struct sec_merge_hash_entry *sec_
+ 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 int strrevcmp PARAMS ((const PTR, const PTR));
++static int strrevcmp_align 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
+@@ -231,9 +227,12 @@ sec_merge_hash_lookup (table, string, al
+ alignment, we need to insert another copy. */
+ if (hashp->alignment < alignment)
+ {
+- /* Mark the less aligned copy as deleted. */
+- hashp->len = 0;
+- hashp->alignment = 0;
++ if (create)
++ {
++ /* Mark the less aligned copy as deleted. */
++ hashp->len = 0;
++ hashp->alignment = 0;
++ }
+ break;
+ }
+ return hashp;
+@@ -457,85 +456,6 @@ _bfd_merge_section (abfd, psinfo, sec, p
+ 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. */
+ static bfd_boolean
+ record_section (sinfo, secinfo)
+@@ -620,19 +540,89 @@ error_return:
+ 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;
++ int lenA = A->len;
++ int lenB = B->len;
++ const unsigned char *s = A->root.string + lenA - 1;
++ const unsigned char *t = B->root.string + lenB - 1;
++ int l = lenA < lenB ? lenA : lenB;
++
++ while (l)
++ {
++ if (*s != *t)
++ return (int) *s - (int) *t;
++ s--;
++ t--;
++ l--;
++ }
++ return lenA - lenB;
++}
++
++/* Like strrevcmp, but for the case where all strings have the same
++ alignment > entsize. */
++
++static int
++strrevcmp_align (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;
++ int lenA = A->len;
++ int lenB = B->len;
++ const unsigned char *s = A->root.string + lenA - 1;
++ const unsigned char *t = B->root.string + lenB - 1;
++ int l = lenA < lenB ? lenA : lenB;
++
++ if ((lenA & (A->alignment - 1)) < (lenB & (A->alignment - 1)))
++ return -1;
++ if ((lenA & (A->alignment - 1)) > (lenB & (A->alignment - 1)))
++ return 1;
++
++ while (l)
++ {
++ if (*s != *t)
++ return (int) *s - (int) *t;
++ s--;
++ t--;
++ l--;
++ }
++ return lenA - lenB;
++}
++
++static INLINE 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) == 0;
++}
++
+ /* This is a helper function for _bfd_merge_sections. It attempts to
+ merge strings matching suffixes of longer strings. */
+ static void
+ merge_strings (sinfo)
+ struct sec_merge_info *sinfo;
+ {
+- struct sec_merge_hash_entry **array, **a, **end, *e;
++ struct sec_merge_hash_entry **array, **a, *e;
+ struct sec_merge_sec_info *secinfo;
+- htab_t lasttab = NULL, last4tab = NULL;
+ bfd_size_type size, amt;
++ unsigned int alignment = 0;
++ bfd_boolean equal_align = TRUE;
+
+- /* Now sort the strings by length, longest first. */
+- array = NULL;
++ /* Now sort the strings */
+ amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
+ array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
+ if (array == NULL)
+@@ -640,90 +630,47 @@ merge_strings (sinfo)
+
+ for (e = sinfo->htab->first, a = array; e; e = e->next)
+ if (e->alignment)
+- *a++ = e;
++ {
++ *a++ = e;
++ /* Adjust the length to not include the zero terminator. */
++ e->len -= sinfo->htab->entsize;
++ if (!alignment)
++ alignment = e->alignment;
++ else if (alignment != e->alignment)
++ equal_align = FALSE;
++ }
+
+ 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)
++ if (sinfo->htab->size != 0)
++ {
++ qsort (array, (size_t) sinfo->htab->size,
++ sizeof (struct sec_merge_hash_entry *),
++ (equal_align && alignment > sinfo->htab->entsize)
++ ? strrevcmp_align : strrevcmp);
++
++ /* Loop over the sorted array and merge suffixes */
++ e = *--a;
++ e->len += sinfo->htab->entsize;
++ while (--a >= array)
++ {
++ struct sec_merge_hash_entry *cmp = *a;
++
++ cmp->len += sinfo->htab->entsize;
++ if (e->alignment >= cmp->alignment
++ && !((e->len - cmp->len) & (cmp->alignment - 1))
++ && is_suffix (e, cmp))
+ {
+- struct sec_merge_hash_entry *ent;
+-
+- ent = (struct sec_merge_hash_entry *) *p;
+- e->u.suffix = ent;
+- e->alignment = 0;
+- continue;
++ cmp->u.suffix = e;
++ cmp->alignment = 0;
+ }
+ 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;
++ e = cmp;
+ }
+- 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;
+--- ld/testsuite/ld-elf/merge2.d.jj 2003-09-18 05:44:07.000000000 -0400
++++ ld/testsuite/ld-elf/merge2.d 2003-09-18 05:44:07.000000000 -0400
+@@ -0,0 +1,15 @@
++#source: merge2.s
++#ld: -T merge.ld
++#objdump: -s
++
++.*: file format .*elf.*
++
++Contents of section .text:
++ 1000 (3010)?0000(1030)? (3210)?0000(1032)? (3110)?0000(1031)? (3410)?0000(1034)? .*
++ 1010 (4010)?0000(1040)? (3810)?0000(1038)? (4810)?0000(1048)? (3c10)?0000(103c)? .*
++ 1020 (5010)?0000(1050)? (5410)?0000(1054)? (5810)?0000(1058)? (5010)?0000(1050)? .*
++Contents of section .rodata:
++ 1030 61626300 62000000 (78563412|12345678) 99999999 .*
++ 1040 (78563412|12345678) 00000000 99999999 00000000 .*
++ 1050 (78563412|12345678) 99999999 00000000 .*
++#pass
+--- ld/testsuite/ld-elf/merge2.s.jj 2003-09-18 05:44:07.000000000 -0400
++++ ld/testsuite/ld-elf/merge2.s 2003-09-18 05:44:07.000000000 -0400
+@@ -0,0 +1,58 @@
++ .section .rodata.str,"aMS","progbits",1
++.LC0:
++ .asciz "abc"
++.LC1:
++ .asciz "c"
++.LC2:
++ .asciz "bc"
++.LC3:
++ .asciz "b"
++
++
++ .section .rodata.str2,"aMS","progbits",4
++ .p2align 2
++.LC4:
++ .long 0x12345678
++ .long 0
++.LC5:
++ .long 0x12345678
++ .long 0x99999999
++ .long 0x12345678
++ .long 0
++.LC6:
++ .long 0x99999999
++ .long 0
++.LC7:
++ .long 0x99999999
++ .long 0x12345678
++ .long 0
++
++
++ .section .rodata.m,"aM","progbits",4
++ .p2align 2
++.LC8:
++ .long 0x12345678
++.LC9:
++ .long 0x99999999
++.LC10:
++ .long 0
++.LC11:
++ .long 0x12345678
++
++
++ .text
++ .global _start
++_start:
++ .long .LC0
++.LT0:
++ .long .LC1
++ .long .LC2
++ .long .LC3
++ .long .LC4
++ .long .LC5
++ .long .LC6
++ .long .LC7
++ .long .LC8
++ .long .LC9
++ .long .LC10
++ .long .LC11
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-sparc-cfi.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-sparc-cfi.patch
new file mode 100644
index 000000000000..94342cc65633
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.6-sparc-cfi.patch
@@ -0,0 +1,367 @@
+2003-08-29 Jakub Jelinek <jakub@redhat.com>
+
+ * dw2gencfi.c (cfi_pseudo_table): Add cfi_window_save.
+ (dot_cfi, output_cfi_insn): Handle DW_CFA_GNU_window_save.
+ (output_cie): Don't use DW_EH_PE_pcrel if neither DIFF_EXPR_OK
+ nor tc_cfi_emit_pcrel_expr are defined.
+ (output_fde): Use tc_cfi_emit_pcrel_expr if available and
+ DIFF_EXPR_OK is not defined.
+ * config/tc-sparc.h (TARGET_USE_CFIPOP): Define.
+ (tc_cfi_frame_initial_instructions, tc_regname_to_dw2regnum,
+ tc_cfi_emit_pcrel_expr): Define.
+ (sparc_cfi_frame_initial_instructions, sparc_regname_to_dw2regnum,
+ sparc_cfi_emit_pcrel_expr): New prototypes.
+ (sparc_cie_data_alignment): New decl.
+ (DWARF2_DEFAULT_RETURN_COLUMN, DWARF2_CIE_DATA_ALIGNMENT): Define.
+ * config/tc-sparc.c: Include dw2gencfi.h.
+ (sparc_cie_data_alignment): New variable.
+ (md_begin): Initialize it.
+ (sparc_cfi_frame_initial_instructions): New function.
+ (sparc_regname_to_dw2regnum): Likewise.
+ (sparc_cfi_emit_pcrel_expr): Likewise.
+ * doc/as.texinfo: Document .cfi_window_save.
+
+ * config/tc-sparc.c (s_common): Cast last argument to long and
+ change format string to shut up warning.
+testsuite/
+ * gas/cfi/cfi-sparc-1.s: New test.
+ * gas/cfi/cfi-sparc-1.d: New test.
+ * gas/cfi/cfi-sparc64-1.s: New test.
+ * gas/cfi/cfi-sparc64-1.d: New test.
+ * gas/cfi/cfi.exp: Run them.
+
+--- gas/dw2gencfi.c.jj 2003-06-18 13:57:59.000000000 -0400
++++ gas/dw2gencfi.c 2003-08-29 14:00:41.000000000 -0400
+@@ -374,6 +374,7 @@ const pseudo_typeS cfi_pseudo_table[] =
+ { "cfi_same_value", dot_cfi, DW_CFA_same_value },
+ { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
+ { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
++ { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
+ { "cfi_escape", dot_cfi_escape, 0 },
+ { NULL, NULL, 0 }
+ };
+@@ -529,6 +530,10 @@ dot_cfi (int arg)
+ cfi_add_CFA_restore_state ();
+ break;
+
++ case DW_CFA_GNU_window_save:
++ cfi_add_CFA_insn (DW_CFA_GNU_window_save);
++ break;
++
+ default:
+ abort ();
+ }
+@@ -798,6 +803,10 @@ output_cfi_insn (struct cfi_insn_data *i
+ out_one (insn->insn);
+ break;
+
++ case DW_CFA_GNU_window_save:
++ out_one (DW_CFA_GNU_window_save);
++ break;
++
+ case CFI_escape:
+ {
+ struct cfi_escape_data *e;
+@@ -838,7 +847,11 @@ output_cie (struct cie_entry *cie)
+ out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT); /* Data alignment */
+ out_one (cie->return_column); /* Return column */
+ out_uleb128 (1); /* Augmentation size */
++#if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
+ out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
++#else
++ out_one (DW_EH_PE_sdata4);
++#endif
+
+ if (cie->first)
+ for (i = cie->first; i != cie->last; i = i->next)
+@@ -867,10 +880,22 @@ output_fde (struct fde_entry *fde, struc
+ exp.X_add_symbol = after_size_address;
+ exp.X_op_symbol = cie->start_address;
+ emit_expr (&exp, 4); /* CIE offset */
+-
++
++#ifdef DIFF_EXPR_OK
+ exp.X_add_symbol = fde->start_address;
+ exp.X_op_symbol = symbol_temp_new_now ();
+ emit_expr (&exp, 4); /* Code offset */
++#else
++ exp.X_op = O_symbol;
++ exp.X_add_symbol = fde->start_address;
++ exp.X_op_symbol = NULL;
++#ifdef tc_cfi_emit_pcrel_expr
++ tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset */
++#else
++ emit_expr (&exp, 4); /* Code offset */
++#endif
++ exp.X_op = O_subtract;
++#endif
+
+ exp.X_add_symbol = fde->end_address;
+ exp.X_op_symbol = fde->start_address; /* Code length */
+--- gas/config/tc-sparc.h.jj 2003-01-24 18:37:51.000000000 -0500
++++ gas/config/tc-sparc.h 2003-08-29 15:38:47.000000000 -0400
+@@ -174,6 +174,21 @@ extern void cons_fix_new_sparc
+ } \
+ while (0)
+
+-#define DWARF2_LINE_MIN_INSN_LENGTH 4
++#define TARGET_USE_CFIPOP 1
++
++#define tc_cfi_frame_initial_instructions sparc_cfi_frame_initial_instructions
++extern void sparc_cfi_frame_initial_instructions PARAMS ((void));
++
++#define tc_regname_to_dw2regnum sparc_regname_to_dw2regnum
++extern int sparc_regname_to_dw2regnum PARAMS ((const char *regname));
++
++#define tc_cfi_emit_pcrel_expr sparc_cfi_emit_pcrel_expr
++extern void sparc_cfi_emit_pcrel_expr PARAMS ((expressionS *, unsigned int));
++
++extern int sparc_cie_data_alignment;
++
++#define DWARF2_LINE_MIN_INSN_LENGTH 4
++#define DWARF2_DEFAULT_RETURN_COLUMN 15
++#define DWARF2_CIE_DATA_ALIGNMENT sparc_cie_data_alignment
+
+ /* end of tc-sparc.h */
+--- gas/config/tc-sparc.c.jj 2003-07-02 11:01:56.000000000 -0400
++++ gas/config/tc-sparc.c 2003-08-29 15:39:10.000000000 -0400
+@@ -26,6 +26,7 @@
+ #include "subsegs.h"
+
+ #include "opcode/sparc.h"
++#include "dw2gencfi.h"
+
+ #ifdef OBJ_ELF
+ #include "elf/sparc.h"
+@@ -116,6 +117,9 @@ static int target_little_endian_data;
+ /* Symbols for global registers on v9. */
+ static symbolS *globals[8];
+
++/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */
++int sparc_cie_data_alignment;
++
+ /* V9 and 86x have big and little endian data, but instructions are always big
+ endian. The sparclet has bi-endian support but both data and insns have
+ the same endianness. Global `target_big_endian' is used for data.
+@@ -798,6 +802,7 @@ md_begin ()
+ if (! default_init_p)
+ init_default_arch ();
+
++ sparc_cie_data_alignment = sparc_arch_size == 64 ? -8 : -4;
+ op_hash = hash_new ();
+
+ while (i < (unsigned int) sparc_num_opcodes)
+@@ -3804,8 +3809,8 @@ s_common (ignore)
+ {
+ if (S_GET_VALUE (symbolP) != (valueT) size)
+ {
+- as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."),
+- S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
++ as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
++ S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size);
+ }
+ }
+ else
+@@ -4482,4 +4487,63 @@ cons_fix_new_sparc (frag, where, nbytes,
+ }
+
+ fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
++ sparc_cons_special_reloc = NULL;
++}
++
++void
++sparc_cfi_frame_initial_instructions ()
++{
++ cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
++}
++
++int
++sparc_regname_to_dw2regnum (const char *regname)
++{
++ char *p, *q;
++
++ if (!regname[0])
++ return -1;
++
++ q = "goli";
++ p = strchr (q, regname[0]);
++ if (p)
++ {
++ if (regname[1] < '0' || regname[1] > '8' || regname[2])
++ return -1;
++ return (p - q) * 8 + regname[1] - '0';
++ }
++ if (regname[0] == 's' && regname[1] == 'p' && !regname[2])
++ return 14;
++ if (regname[0] == 'f' && regname[1] == 'p' && !regname[2])
++ return 30;
++ if (regname[0] == 'f' || regname[0] == 'r')
++ {
++ unsigned int regnum;
++
++ regnum = strtoul (regname + 1, &q, 10);
++ if (p == q || *q)
++ return -1;
++ if (regnum >= ((regname[0] == 'f'
++ && SPARC_OPCODE_ARCH_V9_P (max_architecture))
++ ? 64 : 32))
++ return -1;
++ if (regname[0] == 'f')
++ {
++ regnum += 32;
++ if (regnum >= 64 && (regnum & 1))
++ return -1;
++ }
++ return regnum;
++ }
++ return -1;
++}
++
++void
++sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
++{
++ sparc_cons_special_reloc = "disp";
++ sparc_no_align_cons = 1;
++ emit_expr (exp, nbytes);
++ sparc_no_align_cons = 0;
++ sparc_cons_special_reloc = NULL;
+ }
+--- gas/doc/as.texinfo.jj 2003-07-29 05:40:36.000000000 -0400
++++ gas/doc/as.texinfo 2003-08-29 15:29:21.000000000 -0400
+@@ -4050,6 +4050,9 @@ using the known displacement of the CFA
+ This is often easier to use, because the number will match the
+ code it's annotating.
+
++@section @code{.cfi_window_save}
++SPARC register window has been saved.
++
+ @section @code{.cfi_escape} @var{expression}[, @dots{}]
+ Allows the user to add arbitrary bytes to the unwind info. One
+ might use this to add OS-specific CFI opcodes, or generic CFI
+--- gas/testsuite/gas/cfi/cfi-sparc-1.s.jj 2003-08-28 05:56:33.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-sparc-1.s 2003-08-28 06:26:37.000000000 -0400
+@@ -0,0 +1,23 @@
++#; $ as -o test.o -32 gas-cfi-test.s && gcc -m32 -nostdlib -o test test.o
++
++ .file "a.c"
++ .text
++ .align 4
++ .globl foo
++ .type foo, @function
++foo:
++ .cfi_startproc
++ save %sp, -104, %sp
++ .cfi_def_cfa_register %fp
++ .cfi_window_save
++ .cfi_register %o7, %i7
++ add %i0, 1, %o0
++ call bar, 0
++ add %i0, 2, %i0
++ call bar, 0
++ mov %i0, %o0
++ add %o0, 3, %o0
++ ret
++ restore %g0, %o0, %o0
++ .cfi_endproc
++ .size foo, .-foo
+--- gas/testsuite/gas/cfi/cfi-sparc64-1.s.jj 2003-08-28 05:56:33.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-sparc64-1.s 2003-08-28 06:26:44.000000000 -0400
+@@ -0,0 +1,26 @@
++#; $ as -o test.o -64 gas-cfi-test.s && gcc -m64 -nostdlib -o test test.o
++
++ .file "a.c"
++ .text
++ .align 4
++ .globl foo
++ .type foo, @function
++foo:
++ .cfi_startproc
++ save %sp, -192, %sp
++ .cfi_def_cfa_register %fp
++ .cfi_window_save
++ .cfi_register %o7, %i7
++ add %i0, 1, %o0
++ add %i0, 2, %i0
++ call bar, 0
++ sra %o0, 0, %o0
++ sra %i0, 0, %i0
++ call bar, 0
++ mov %i0, %o0
++ add %o0, 3, %o0
++ sra %o0, 0, %o0
++ ret
++ restore %g0, %o0, %o0
++ .cfi_endproc
++ .size foo, .-foo
+--- gas/testsuite/gas/cfi/cfi-sparc-1.d.jj 2003-08-29 15:17:54.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-sparc-1.d 2003-08-29 15:17:44.000000000 -0400
+@@ -0,0 +1,22 @@
++#readelf: -wf
++#name: CFI on SPARC 32-bit
++#as: -32
++
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: 4
++ Data alignment factor: -4
++ Return address column: 15
++ Augmentation data: 1b
++
++ DW_CFA_def_cfa: r14 ofs 0
++
++00000014 00000014 00000018 FDE cie=00000000 pc=0000001c..00000040
++ DW_CFA_advance_loc: 4 to 00000020
++ DW_CFA_def_cfa_reg: r30
++ DW_CFA_GNU_window_save
++ DW_CFA_register: r15 in r31
++
+--- gas/testsuite/gas/cfi/cfi-sparc64-1.d.jj 2003-08-29 15:17:51.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-sparc64-1.d 2003-08-29 15:17:35.000000000 -0400
+@@ -0,0 +1,25 @@
++#readelf: -wf
++#name: CFI on SPARC 64-bit
++#as: -64
++
++The section .eh_frame contains:
++
++00000000 00000011 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: 4
++ Data alignment factor: -8
++ Return address column: 15
++ Augmentation data: 1b
++
++ DW_CFA_def_cfa: r14 ofs 2047
++
++00000015 00000017 00000019 FDE cie=00000000 pc=0000001d..0000004d
++ DW_CFA_advance_loc: 4 to 00000021
++ DW_CFA_def_cfa_reg: r30
++ DW_CFA_GNU_window_save
++ DW_CFA_register: r15 in r31
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++
+--- gas/testsuite/gas/cfi/cfi.exp.jj 2003-08-10 15:56:11.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi.exp 2003-08-29 15:23:29.000000000 -0400
+@@ -39,6 +39,16 @@ if [istarget "x86_64-*"] then {
+ } elseif { [istarget "m68*-*"] } then {
+ run_dump_test "cfi-m68k"
+
++} elseif { [istarget sparc*-*-*] } then {
++ global NM
++ global NMFLAGS
++ global srcdir
++
++ catch "exec $srcdir/lib/run $NM $NMFLAGS --help" nm_help
++ run_dump_test "cfi-sparc-1"
++ if { [regexp "elf64\[_-\]sparc" $nm_help] } then {
++ run_dump_test "cfi-sparc64-1"
++ }
+ } else {
+ return
+ }
diff --git a/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r4 b/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r4
new file mode 100644
index 000000000000..26abe27b6c76
--- /dev/null
+++ b/sys-devel/binutils/files/digest-binutils-2.14.90.0.6-r4
@@ -0,0 +1 @@
+MD5 71b99dba3045a359dc314dbebedcf502 binutils-2.14.90.0.6.tar.bz2 10399066