--- /dev/null
+#!/bin/sh -e
+## 203-hjl-binutils-indirect.dpatch
+##
+## DP: Description: PR ld/3351; avoid linker crash on ia64
+## DP: Author: H.J. Lu <hongjiu.lu@intel.com>
+## DP: Upstream status: hjl 2.17.50.0.18
+## DP: Original patch: binutils-indirect-1.patch
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+bfd/
+
+2006-10-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/3351
+ * elflink.c (_bfd_elf_update_dynamic_flags): New.
+ (_bfd_elf_merge_symbol): Update both real and indirect symbol
+ dynamic flags.
+ (_bfd_elf_add_default_symbol): Make the real symbol dynamic if
+ the indirect symbol is defined in a shared library.
+ (elf_link_add_object_symbols): Likewise. If the indirect
+ symbol has been forced local, don't make the real symbol
+ dynamic.
+ (elf_link_check_versioned_symbol): Check indirect symbol.
+ (elf_link_output_extsym): Use real symbol definition when
+ reporting indirect symbol error. Check version info for
+ dynamic versioned symbol.
+
+ld/testsuite/
+
+2006-10-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/3351
+ * ld-elf/indirect.exp: New file.
+ * ld-elf/indirect1a.c: Likewise.
+ * ld-elf/indirect1b.c: Likewise.
+ * ld-elf/indirect1c.c: Likewise.
+ * ld-elf/indirect2.c: Likewise.
+ * ld-elf/indirect3.out: Likewise.
+ * ld-elf/indirect3a.c: Likewise.
+ * ld-elf/indirect3b.c: Likewise.
+ * ld-elf/indirect3c.c: Likewise.
+ * ld-elf/indirect4.out: Likewise.
+ * ld-elf/indirect4a.c: Likewise.
+ * ld-elf/indirect4b.c: Likewise.
+ * ld-elf/indirect4c.c: Likewise.
+
+@DPATCH@
+diff -urNad binutils-2.18~cvs20070812~/bfd/elflink.c binutils-2.18~cvs20070812/bfd/elflink.c
+--- binutils-2.18~cvs20070812~/bfd/elflink.c 2007-07-27 03:04:29.000000000 +0200
++++ binutils-2.18~cvs20070812/bfd/elflink.c 2007-08-12 13:27:51.000000000 +0200
+@@ -823,6 +823,33 @@
+ return dynsymcount;
+ }
+
++/* Mark if a symbol has a definition in a dynamic object or is
++ weak in all dynamic objects. */
++
++static void
++_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
++ asection *sec, int bind)
++{
++ if (!h->dynamic_def)
++ {
++ if (!bfd_is_und_section (sec))
++ h->dynamic_def = 1;
++ else
++ {
++ /* Check if this symbol is weak in all dynamic objects. If it
++ is the first time we see it in a dynamic object, we mark
++ if it is weak. Otherwise, we clear it. */
++ if (!h->ref_dynamic)
++ {
++ if (bind == STB_WEAK)
++ h->dynamic_weak = 1;
++ }
++ else if (bind != STB_WEAK)
++ h->dynamic_weak = 0;
++ }
++ }
++}
++
+ /* This function is called when we want to define a new symbol. It
+ handles the various cases which arise when we find a definition in
+ a dynamic object, or when there is already a definition in a
+@@ -851,6 +878,7 @@
+ {
+ asection *sec, *oldsec;
+ struct elf_link_hash_entry *h;
++ struct elf_link_hash_entry *hi;
+ struct elf_link_hash_entry *flip;
+ int bind;
+ bfd *oldbfd;
+@@ -887,8 +915,9 @@
+ if (info->hash->creator != abfd->xvec)
+ return TRUE;
+
+- /* For merging, we only care about real symbols. */
+-
++ /* For merging, we only care about real symbols. But we need to make
++ sure that indirect symbol dynamic flags are updated. */
++ hi = h;
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+@@ -1047,23 +1076,11 @@
+ /* We need to remember if a symbol has a definition in a dynamic
+ object or is weak in all dynamic objects. Internal and hidden
+ visibility will make it unavailable to dynamic objects. */
+- if (newdyn && !h->dynamic_def)
++ if (newdyn)
+ {
+- if (!bfd_is_und_section (sec))
+- h->dynamic_def = 1;
+- else
+- {
+- /* Check if this symbol is weak in all dynamic objects. If it
+- is the first time we see it in a dynamic object, we mark
+- if it is weak. Otherwise, we clear it. */
+- if (!h->ref_dynamic)
+- {
+- if (bind == STB_WEAK)
+- h->dynamic_weak = 1;
+- }
+- else if (bind != STB_WEAK)
+- h->dynamic_weak = 0;
+- }
++ _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
++ if (h != hi)
++ _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
+ }
+
+ /* If the old symbol has non-default visibility, we ignore the new
+@@ -1075,6 +1092,7 @@
+ *skip = TRUE;
+ /* Make sure this symbol is dynamic. */
+ h->ref_dynamic = 1;
++ hi->ref_dynamic = 1;
+ /* A protected symbol has external availability. Make sure it is
+ recorded as dynamic.
+
+@@ -1609,6 +1627,7 @@
+ if (! dynamic)
+ {
+ if (info->shared
++ || hi->def_dynamic
+ || hi->ref_dynamic)
+ *dynsym = TRUE;
+ }
+@@ -3737,6 +3756,7 @@
+ flagword flags;
+ const char *name;
+ struct elf_link_hash_entry *h;
++ struct elf_link_hash_entry *hi;
+ bfd_boolean definition;
+ bfd_boolean size_change_ok;
+ bfd_boolean type_change_ok;
+@@ -4026,6 +4046,9 @@
+ goto error_free_vers;
+
+ h = *sym_hash;
++ /* We need to make sure that indirect symbol dynamic flags are
++ updated. */
++ hi = h;
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+@@ -4232,22 +4255,36 @@
+ }
+ else
+ h->def_regular = 1;
+- if (! info->executable
+- || h->def_dynamic
+- || h->ref_dynamic)
++
++ /* If the indirect symbol has been forced local, don't
++ make the real symbol dynamic. */
++ if ((h == hi || !hi->forced_local)
++ && (! info->executable
++ || h->def_dynamic
++ || h->ref_dynamic))
+ dynsym = TRUE;
+ }
+ else
+ {
+ if (! definition)
+- h->ref_dynamic = 1;
++ {
++ h->ref_dynamic = 1;
++ hi->ref_dynamic = 1;
++ }
+ else
+- h->def_dynamic = 1;
+- if (h->def_regular
+- || h->ref_regular
+- || (h->u.weakdef != NULL
+- && ! new_weakdef
+- && h->u.weakdef->dynindx != -1))
++ {
++ h->def_dynamic = 1;
++ hi->def_dynamic = 1;
++ }
++
++ /* If the indirect symbol has been forced local, don't
++ make the real symbol dynamic. */
++ if ((h == hi || !hi->forced_local)
++ && (h->def_regular
++ || h->ref_regular
++ || (h->u.weakdef != NULL
++ && ! new_weakdef
++ && h->u.weakdef->dynindx != -1)))
+ dynsym = TRUE;
+ }
+
+@@ -8396,6 +8433,10 @@
+ if (!is_elf_hash_table (info->hash))
+ return FALSE;
+
++ /* Check indirect symbol. */
++ while (h->root.type == bfd_link_hash_indirect)
++ h = (struct elf_link_hash_entry *) h->root.u.i.link;
++
+ switch (h->root.type)
+ {
+ default:
+@@ -8604,11 +8645,17 @@
+ && !h->dynamic_weak
+ && ! elf_link_check_versioned_symbol (finfo->info, bed, h))
+ {
++ struct elf_link_hash_entry *hi = h;
++
++ /* Check indirect symbol. */
++ while (hi->root.type == bfd_link_hash_indirect)
++ hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
++
+ (*_bfd_error_handler)
+ (_("%B: %s symbol `%s' in %B is referenced by DSO"),
+ finfo->output_bfd,
+- h->root.u.def.section == bfd_abs_section_ptr
+- ? finfo->output_bfd : h->root.u.def.section->owner,
++ hi->root.u.def.section == bfd_abs_section_ptr
++ ? finfo->output_bfd : hi->root.u.def.section->owner,
+ ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+ ? "internal"
+ : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+@@ -8804,6 +8851,23 @@
+ {
+ bfd_byte *esym;
+
++ /* Since there is no version information in the dynamic string,
++ if there is no version info in symbol version section, we will
++ have a run-time problem. */
++ if (h->verinfo.verdef == NULL)
++ {
++ char *p = strrchr (h->root.root.string, ELF_VER_CHR);
++
++ if (p && p [1] != '\0')
++ {
++ (*_bfd_error_handler)
++ (_("%B: No symbol version section for versioned symbol `%s'"),
++ finfo->output_bfd, h->root.root.string);
++ eoinfo->failed = TRUE;
++ return FALSE;
++ }
++ }
++
+ sym.st_name = h->dynstr_index;
+ esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
+ if (! check_dynsym (finfo->output_bfd, &sym))
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect.exp binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect.exp
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect.exp 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect.exp 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,126 @@
++# Expect script for various indirect symbol tests.
++# Copyright 2006 Free Software Foundation, Inc.
++#
++# This file is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program 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 General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
++#
++
++#
++# Written by H.J. Lu (hongjiu.lu@intel.com)
++#
++
++# Exclude non-ELF targets.
++
++if ![is_elf_format] {
++ return
++}
++
++# Check if compiler works
++if { [which $CC] == 0 } {
++ return
++}
++
++proc check_link_message { cmd string testname } {
++ send_log "$cmd\n"
++ verbose "$cmd"
++ catch "exec $cmd" exec_output
++ send_log "$exec_output\n"
++ verbose "$exec_output"
++
++ foreach str $string {
++ if [string match "*$str*" $exec_output] {
++ pass "$testname: $str"
++ } else {
++ fail "$testname: $str"
++ }
++ }
++}
++
++if { ![ld_compile $CC $srcdir/$subdir/indirect1a.c tmpdir/indirect1a.o]
++ || ![ld_compile $CC $srcdir/$subdir/indirect1b.c tmpdir/indirect1b.o]
++ || ![ld_compile "$CC -fPIC" $srcdir/$subdir/indirect2.c tmpdir/indirect2.o]
++ || ![ld_compile $CC $srcdir/$subdir/indirect3a.c tmpdir/indirect3a.o]
++ || ![ld_compile $CC $srcdir/$subdir/indirect3b.c tmpdir/indirect3b.o]
++ || ![ld_compile $CC $srcdir/$subdir/indirect4a.c tmpdir/indirect4a.o]
++ || ![ld_compile $CC $srcdir/$subdir/indirect4b.c tmpdir/indirect4b.o] } {
++ unresolved "Indirect symbol tests"
++ return
++}
++
++set build_tests {
++ {"Build libindirect1c.so"
++ "-shared" "-fPIC"
++ {indirect1c.c} {} "libindirect1c.so"}
++ {"Build libindirect3c.so"
++ "-shared" "-fPIC"
++ {indirect3c.c} {} "libindirect3c.so"}
++ {"Build libindirect4c.so"
++ "-shared" "-fPIC"
++ {indirect4c.c} {} "libindirect4c.so"}
++}
++
++run_cc_link_tests $build_tests
++
++global ld
++
++set string ": final link failed: Nonrepresentable section on output"
++
++set string1 ": local symbol \`foo\' in tmpdir/indirect1b.o is referenced by DSO"
++
++set testname "Indirect symbol 1a"
++set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/indirect1b.o tmpdir/libindirect1c.so"
++check_link_message "$cmd" [list $string1 $string] "$testname"
++
++set testname "Indirect symbol 1b"
++set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/libindirect1c.so tmpdir/indirect1b.o"
++check_link_message "$cmd" [list $string1 $string] "$testname"
++
++set string2 ": No symbol version section for versioned symbol \`foo@FOO\'"
++set testname "Indirect symbol 2"
++set cmd "$ld -shared -o tmpdir/indirect2.so tmpdir/indirect2.o"
++check_link_message "$cmd" [list $string2 $string] "$testname"
++
++# The following tests require running the executable generated by ld.
++if ![isnative] {
++ return
++}
++
++set run_tests {
++ {"Run with libindirect3c.so 1"
++ "tmpdir/indirect3a.o tmpdir/indirect3b.o tmpdir/libindirect3c.so" ""
++ {dummy.c} "indirect3a" "indirect3.out"}
++ {"Run with libindirect3c.so 2"
++ "tmpdir/indirect3a.o tmpdir/libindirect3c.so tmpdir/indirect3b.o" ""
++ {dummy.c} "indirect3b" "indirect3.out"}
++ {"Run with libindirect3c.so 3"
++ "tmpdir/indirect3b.o tmpdir/libindirect3c.so tmpdir/indirect3a.o" ""
++ {dummy.c} "indirect3c" "indirect3.out"}
++ {"Run with libindirect3c.so 4"
++ "tmpdir/libindirect3c.so tmpdir/indirect3b.o tmpdir/indirect3a.o" ""
++ {dummy.c} "indirect3d" "indirect3.out"}
++ {"Run with libindirect4c.so 1"
++ "tmpdir/indirect4a.o tmpdir/indirect4b.o tmpdir/libindirect4c.so" ""
++ {dummy.c} "indirect4a" "indirect4.out"}
++ {"Run with libindirect4c.so 2"
++ "tmpdir/indirect4a.o tmpdir/libindirect4c.so tmpdir/indirect4b.o" ""
++ {dummy.c} "indirect4b" "indirect4.out"}
++ {"Run with libindirect4c.so 3"
++ "tmpdir/indirect4b.o tmpdir/libindirect4c.so tmpdir/indirect4a.o" ""
++ {dummy.c} "indirect4c" "indirect4.out"}
++ {"Run with libindirect4c.so 4"
++ "tmpdir/libindirect4c.so tmpdir/indirect4b.o tmpdir/indirect4a.o" ""
++ {dummy.c} "indirect4d" "indirect4.out"}
++}
++
++run_ld_link_exec_tests [] $run_tests
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1a.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1a.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1a.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,8 @@
++extern void bar (void);
++
++int
++start (void)
++{
++ bar ();
++ return 0;
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1b.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1b.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1b.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,6 @@
++void
++foo (void)
++{
++}
++
++asm (".symver foo,foo@FOO");
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1c.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1c.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1c.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,7 @@
++extern void foo (void);
++
++void
++bar (void)
++{
++ foo ();
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect2.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect2.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect2.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect2.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,9 @@
++extern void foo (void);
++
++asm (".symver foo,foo@@@FOO");
++
++void
++bar (void)
++{
++ foo ();
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3.out binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3.out
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3.out 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3.out 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,2 @@
++MAIN
++DSO
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3a.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3a.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3a.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,10 @@
++extern void bar (void);
++extern void foo (void);
++
++int
++main (void)
++{
++ foo ();
++ bar ();
++ return 0;
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3b.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3b.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3b.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,9 @@
++#include <stdio.h>
++
++void
++foo (void)
++{
++ printf ("MAIN\n");
++}
++
++asm (".symver foo,foo@FOO");
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3c.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3c.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3c.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,15 @@
++#include <stdio.h>
++
++extern void foo (void);
++
++void
++foo (void)
++{
++ printf ("DSO\n");
++}
++
++void
++bar (void)
++{
++ foo ();
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4.out binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4.out
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4.out 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4.out 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,2 @@
++MAIN2
++MAIN2
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4a.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4a.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4a.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,10 @@
++extern void bar (void);
++extern void foo (void);
++
++int
++main (void)
++{
++ foo ();
++ bar ();
++ return 0;
++}
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4b.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4b.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4b.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,17 @@
++#include <stdio.h>
++
++void
++foo2 (void)
++{
++ printf ("MAIN2\n");
++}
++
++asm (".symver foo2,foo@@FOO2");
++
++void
++foo1 (void)
++{
++ printf ("MAIN1\n");
++}
++
++asm (".symver foo1,foo@FOO1");
+diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4c.c
+--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4c.c 1970-01-01 01:00:00.000000000 +0100
++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4c.c 2007-08-12 13:27:51.000000000 +0200
+@@ -0,0 +1,15 @@
++#include <stdio.h>
++
++extern void foo (void);
++
++void
++foo (void)
++{
++ printf ("DSO\n");
++}
++
++void
++bar (void)
++{
++ foo ();
++}