bfd/
authorAlan Modra <amodra@gmail.com>
Thu, 25 Mar 2004 12:48:45 +0000 (12:48 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 25 Mar 2004 12:48:45 +0000 (12:48 +0000)
* elflink.h (elf_link_add_object_symbols): Add DT_NEEDED for as-needed
and chained shared libs only if dynsym.  Clear dynsym on forced-local.

* elf-bfd.h (_bfd_elf_add_dynamic_entry): Declare.
(bfd_elf32_add_dynamic_entry, bfd_elf64_add_dynamic_entry): Delete.
(_bfd_elf_add_dt_needed_tag): Declare.
(_bfd_elf_sort_symbol): Declare.
(_bfd_elf_finalize_dynstr): Declare.
(RELOC_FOR_GLOBAL_SYM): Formatting.
* elfcode.h (elf_add_dynamic_entry): Delete.
* elflink.c (_bfd_elf_add_dynamic_entry): New function.  Corresponding
elflink.h function converted to use elf_size_info.
(_bfd_elf_add_dt_needed_tag): Likewise.
(_bfd_elf_sort_symbol): Likewise.
(_bfd_elf_finalize_dynstr): Likewise.
(compute_bucket_count): Likewise.
(bfd_elf_size_dynamic_sections): Likewise.  Check result of
_bfd_elf_strtab_add before calling _bfd_elf_strtab_addref.
(elf_adjust_dynstr_offsets, elf_collect_hash_codes): Moved from..
* elflink.h: ..here.
(sort_symbol, add_dt_needed_tag): Delete.
(elf_add_dynamic_entry, elf_finalize_dynstr): Delete.
(compute_bucket_count, NAME(bfd_elf,size_dynamic_sections)): Delete.
Update all users.
* elf32-arm.h (add_dynamic_entry): Update.  Remove casts.
* elf32-cris.c (add_dynamic_entry): Likewise.
* elf32-hppa.c (add_dynamic_entry): Likewise.
* elf32-i370.c (add_dynamic_entry): Likewise.
* elf32-i386.c (add_dynamic_entry): Likewise.
* elf32-m32r.c (add_dynamic_entry): Likewise.
* elf32-m68k.c (add_dynamic_entry): Likewise.
* elf32-ppc.c (add_dynamic_entry): Likewise.
* elf32-s390.c (add_dynamic_entry): Likewise.
* elf32-sh.c (add_dynamic_entry): Likewise.
* elf32-sparc.c (add_dynamic_entry): Likewise.
* elf32-vax.c (add_dynamic_entry): Likewise.
* elf32-xtensa.c (add_dynamic_entry): Likewise.
* elf64-alpha.c (add_dynamic_entry): Likewise.
* elf64-hppa.c (add_dynamic_entry): Likewise.
* elf64-ppc.c (add_dynamic_entry): Likewise.
* elf64-s390.c (add_dynamic_entry): Likewise.
* elf64-sparc.c (add_dynamic_entry): Likewise.
* elf64-x86-64.c (add_dynamic_entry): Likewise.
* elfxx-ia64.c (add_dynamic_entry): Likewise.
* elfxx-mips.c (MIPS_ELF_ADD_DYNAMIC_ENTRY): Likewise.
* elf-m10300.c (_bfd_mn10300_elf_size_dynamic_sections): Likewise.
* elf32-frv.c (elf32_frv_size_dynamic_sections): Likewise.
* elf64-sh64.c (sh64_elf64_size_dynamic_sections): Likewise.
ld/
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Update
size_dynamic_sections call.

31 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-m10300.c
bfd/elf32-arm.h
bfd/elf32-cris.c
bfd/elf32-frv.c
bfd/elf32-hppa.c
bfd/elf32-i370.c
bfd/elf32-i386.c
bfd/elf32-m32r.c
bfd/elf32-m68k.c
bfd/elf32-ppc.c
bfd/elf32-s390.c
bfd/elf32-sh.c
bfd/elf32-sparc.c
bfd/elf32-vax.c
bfd/elf32-xtensa.c
bfd/elf64-alpha.c
bfd/elf64-hppa.c
bfd/elf64-ppc.c
bfd/elf64-s390.c
bfd/elf64-sh64.c
bfd/elf64-sparc.c
bfd/elf64-x86-64.c
bfd/elfcode.h
bfd/elflink.c
bfd/elflink.h
bfd/elfxx-ia64.c
bfd/elfxx-mips.c
ld/ChangeLog
ld/emultempl/elf32.em

index 6560ebc..2a19c49 100644 (file)
@@ -1,3 +1,54 @@
+2004-03-25  Alan Modra  <amodra@bigpond.net.au>
+
+       * elflink.h (elf_link_add_object_symbols): Add DT_NEEDED for as-needed
+       and chained shared libs only if dynsym.  Clear dynsym on forced-local.
+       
+       * elf-bfd.h (_bfd_elf_add_dynamic_entry): Declare.
+       (bfd_elf32_add_dynamic_entry, bfd_elf64_add_dynamic_entry): Delete.
+       (_bfd_elf_add_dt_needed_tag): Declare.
+       (_bfd_elf_sort_symbol): Declare.
+       (_bfd_elf_finalize_dynstr): Declare.
+       (RELOC_FOR_GLOBAL_SYM): Formatting.
+       * elfcode.h (elf_add_dynamic_entry): Delete.
+       * elflink.c (_bfd_elf_add_dynamic_entry): New function.  Corresponding
+       elflink.h function converted to use elf_size_info.
+       (_bfd_elf_add_dt_needed_tag): Likewise.
+       (_bfd_elf_sort_symbol): Likewise.
+       (_bfd_elf_finalize_dynstr): Likewise.
+       (compute_bucket_count): Likewise.
+       (bfd_elf_size_dynamic_sections): Likewise.  Check result of
+       _bfd_elf_strtab_add before calling _bfd_elf_strtab_addref.
+       (elf_adjust_dynstr_offsets, elf_collect_hash_codes): Moved from..
+       * elflink.h: ..here.
+       (sort_symbol, add_dt_needed_tag): Delete.
+       (elf_add_dynamic_entry, elf_finalize_dynstr): Delete.
+       (compute_bucket_count, NAME(bfd_elf,size_dynamic_sections)): Delete.
+       Update all users.
+       * elf32-arm.h (add_dynamic_entry): Update.  Remove casts.
+       * elf32-cris.c (add_dynamic_entry): Likewise.
+       * elf32-hppa.c (add_dynamic_entry): Likewise.
+       * elf32-i370.c (add_dynamic_entry): Likewise.
+       * elf32-i386.c (add_dynamic_entry): Likewise.
+       * elf32-m32r.c (add_dynamic_entry): Likewise.
+       * elf32-m68k.c (add_dynamic_entry): Likewise.
+       * elf32-ppc.c (add_dynamic_entry): Likewise.
+       * elf32-s390.c (add_dynamic_entry): Likewise.
+       * elf32-sh.c (add_dynamic_entry): Likewise.
+       * elf32-sparc.c (add_dynamic_entry): Likewise.
+       * elf32-vax.c (add_dynamic_entry): Likewise.
+       * elf32-xtensa.c (add_dynamic_entry): Likewise.
+       * elf64-alpha.c (add_dynamic_entry): Likewise.
+       * elf64-hppa.c (add_dynamic_entry): Likewise.
+       * elf64-ppc.c (add_dynamic_entry): Likewise.
+       * elf64-s390.c (add_dynamic_entry): Likewise.
+       * elf64-sparc.c (add_dynamic_entry): Likewise.
+       * elf64-x86-64.c (add_dynamic_entry): Likewise.
+       * elfxx-ia64.c (add_dynamic_entry): Likewise.
+       * elfxx-mips.c (MIPS_ELF_ADD_DYNAMIC_ENTRY): Likewise.
+       * elf-m10300.c (_bfd_mn10300_elf_size_dynamic_sections): Likewise.
+       * elf32-frv.c (elf32_frv_size_dynamic_sections): Likewise.
+       * elf64-sh64.c (sh64_elf64_size_dynamic_sections): Likewise.
+
 2004-03-23  Paul Brook  <paul@codesourcery.com>
 
        * elf32-arm.h (arm_print_private_bfd_data): Add EABI v3.
index cd51e32..c2cd537 100644 (file)
@@ -1593,8 +1593,6 @@ extern void bfd_elf32_write_relocs
   (bfd *, asection *, void *);
 extern bfd_boolean bfd_elf32_slurp_reloc_table
   (bfd *, asection *, asymbol **, bfd_boolean);
-extern bfd_boolean bfd_elf32_add_dynamic_entry
-  (struct bfd_link_info *, bfd_vma, bfd_vma);
 
 extern const bfd_target *bfd_elf64_object_p
   (bfd *);
@@ -1641,8 +1639,15 @@ extern void bfd_elf64_write_relocs
   (bfd *, asection *, void *);
 extern bfd_boolean bfd_elf64_slurp_reloc_table
   (bfd *, asection *, asymbol **, bfd_boolean);
-extern bfd_boolean bfd_elf64_add_dynamic_entry
+
+extern bfd_boolean _bfd_elf_add_dynamic_entry
   (struct bfd_link_info *, bfd_vma, bfd_vma);
+extern int _bfd_elf_add_dt_needed_tag
+  (struct bfd_link_info *, const char *, bfd_boolean);
+extern int _bfd_elf_sort_symbol
+  (const void *, const void *);
+extern bfd_boolean _bfd_elf_finalize_dynstr
+  (bfd *, struct bfd_link_info *);
 
 #define bfd_elf32_link_record_dynamic_symbol \
   _bfd_elf_link_record_dynamic_symbol
@@ -1762,12 +1767,14 @@ extern bfd_boolean _sh_elf_set_mach_from_flags
        ;                                                               \
       else                                                             \
        {                                                               \
-         if (! info->callbacks->undefined_symbol                       \
-             (info, h->root.root.string, input_bfd,                    \
-              input_section, rel->r_offset,                            \
-              (info->unresolved_syms_in_objects == RM_GENERATE_ERROR   \
-               || ELF_ST_VISIBILITY (h->other))                        \
-              ))                                                       \
+         bfd_boolean err;                                              \
+         err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR  \
+                || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);       \
+         if (!info->callbacks->undefined_symbol (info,                 \
+                                                 h->root.root.string,  \
+                                                 input_bfd,            \
+                                                 input_section,        \
+                                                 rel->r_offset, err))  \
            return FALSE;                                               \
          warned = TRUE;                                                \
        }                                                               \
index a132794..8277bae 100644 (file)
@@ -4491,31 +4491,31 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
         in by the dynamic linker and used by the debugger.  */
       if (! info->shared)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0))
            return FALSE;
        }
 
       if (plt)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+             || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
            return FALSE;
        }
 
       if (relocs)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
-             || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
-                                               sizeof (Elf32_External_Rela)))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT,
+                                             sizeof (Elf32_External_Rela)))
            return FALSE;
        }
 
       if (reltext)
        {
-         if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
            return FALSE;
        }
     }
index 33f85bd..89540f0 100644 (file)
@@ -3665,7 +3665,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
index b851392..b405d9e 100644 (file)
@@ -2809,7 +2809,7 @@ elf_cris_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
index eedc55d..46a5ea4 100644 (file)
@@ -1,5 +1,5 @@
 /* FRV-specific support for 32-bit ELF.
-   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -3536,20 +3536,20 @@ elf32_frv_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       if (frv_got_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+       if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0))
          return FALSE;
 
       if (frv_pltrel_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+       if (!_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_REL)
+           || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
          return FALSE;
 
       if (frv_gotrel_section (info)->_raw_size)
-       if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0)
-           || ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
-                                             sizeof (Elf32_External_Rel)))
+       if (!_bfd_elf_add_dynamic_entry (info, DT_REL, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_RELSZ, 0)
+           || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
+                                           sizeof (Elf32_External_Rel)))
          return FALSE;
     }
 
index 63b98e5..cffd194 100644 (file)
@@ -2241,7 +2241,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         communicate the LTP value of a load module to the dynamic
         linker.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!add_dynamic_entry (DT_PLTGOT, 0))
        return FALSE;
index 57854c8..dd84b2d 100644 (file)
@@ -1,5 +1,5 @@
 /* i370-specific support for 32-bit ELF
-   Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
+   Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
    Hacked by Linas Vepstas for i370 linas@linas.org
@@ -791,7 +791,7 @@ i370_elf_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
index 8f30bb2..f1c27d0 100644 (file)
@@ -1895,7 +1895,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (TAG), (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index e3c6ffb..605abcf 100644 (file)
@@ -2442,7 +2442,7 @@ printf("m32r_elf_size_dynamic_sections()\n");
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (! info->shared)
        {
index f1bdd1a..9864ef2 100644 (file)
@@ -1247,7 +1247,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
index 5798eca..0195454 100644 (file)
@@ -3470,7 +3470,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (TAG), (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index bb88dff..eabd070 100644 (file)
@@ -2157,7 +2157,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 28a2fcc..3ec6638 100644 (file)
@@ -4620,7 +4620,7 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 0f8afe0..9f8f9ab 100644 (file)
@@ -2027,7 +2027,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index d2d5905..e6dc4a0 100644 (file)
@@ -1297,7 +1297,7 @@ elf_vax_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!info->shared)
        {
index c376a17..6cb987c 100644 (file)
@@ -1334,7 +1334,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (! info->shared)
        {
index 22c12c0..c84dddf 100644 (file)
@@ -4094,7 +4094,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 5bc9309..d64eca2 100644 (file)
@@ -1,5 +1,6 @@
 /* Support for HPPA 64-bit ELF
-   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -1832,7 +1833,7 @@ elf64_hppa_size_dynamic_sections (output_bfd, info)
         the PLT, it is how we communicate the __gp value of a load
         module to the dynamic linker.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
          || !add_dynamic_entry (DT_PLTGOT, 0))
index d8f0b5e..cf15f92 100644 (file)
@@ -6065,7 +6065,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (TAG), (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 3bf26bc..c35c0a9 100644 (file)
@@ -2127,7 +2127,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 03196c5..652a4f8 100644 (file)
@@ -1,5 +1,5 @@
 /* SuperH SH64-specific support for 64-bit ELF
-   Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -3728,31 +3728,31 @@ sh64_elf64_size_dynamic_sections (bfd *output_bfd,
         dynamic linker and used by the debugger.  */
       if (info->executable)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0))
            return FALSE;
        }
 
       if (plt)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+             || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
            return FALSE;
        }
 
       if (relocs)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
-             || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
-                                               sizeof (Elf64_External_Rela)))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT,
+                                             sizeof (Elf64_External_Rela)))
            return FALSE;
        }
 
       if (reltext)
        {
-         if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
+         if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
            return FALSE;
        }
     }
index 001f3a5..219a434 100644 (file)
@@ -1,6 +1,6 @@
 /* SPARC-specific support for 64-bit ELF
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -1876,7 +1876,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       int reg;
       struct sparc64_elf_app_reg * app_regs;
index 528f7a8..1aadfe5 100644 (file)
@@ -1683,7 +1683,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (info->executable)
        {
index 87d96fa..6f8ddc6 100644 (file)
@@ -116,7 +116,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define elf_no_info_to_howto_rel       NAME(bfd_elf,no_info_to_howto_rel)
 #define elf_find_section               NAME(bfd_elf,find_section)
 #define elf_bfd_link_add_symbols       NAME(bfd_elf,bfd_link_add_symbols)
-#define elf_add_dynamic_entry          NAME(bfd_elf,add_dynamic_entry)
 #define elf_write_shdrs_and_ehdr       NAME(bfd_elf,write_shdrs_and_ehdr)
 #define elf_write_out_phdrs            NAME(bfd_elf,write_out_phdrs)
 #define elf_write_relocs               NAME(bfd_elf,write_relocs)
index 39bf46f..fce550d 100644 (file)
@@ -2585,6 +2585,262 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   return result;
 }
 \f
+/* Add an entry to the .dynamic table.  */
+
+bfd_boolean
+_bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
+                           bfd_vma tag,
+                           bfd_vma val)
+{
+  struct elf_link_hash_table *hash_table;
+  const struct elf_backend_data *bed;
+  asection *s;
+  bfd_size_type newsize;
+  bfd_byte *newcontents;
+  Elf_Internal_Dyn dyn;
+
+  hash_table = elf_hash_table (info);
+  if (! is_elf_hash_table (hash_table))
+    return FALSE;
+
+  bed = get_elf_backend_data (hash_table->dynobj);
+  s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+  BFD_ASSERT (s != NULL);
+
+  newsize = s->_raw_size + bed->s->sizeof_dyn;
+  newcontents = bfd_realloc (s->contents, newsize);
+  if (newcontents == NULL)
+    return FALSE;
+
+  dyn.d_tag = tag;
+  dyn.d_un.d_val = val;
+  bed->s->swap_dyn_out (hash_table->dynobj, &dyn, newcontents + s->_raw_size);
+
+  s->_raw_size = newsize;
+  s->contents = newcontents;
+
+  return TRUE;
+}
+
+/* Add a DT_NEEDED entry for this dynamic object if DO_IT is true,
+   otherwise just check whether one already exists.  Returns -1 on error,
+   1 if a DT_NEEDED tag already exists, and 0 on success.  */
+
+int
+_bfd_elf_add_dt_needed_tag (struct bfd_link_info *info,
+                           const char *soname,
+                           bfd_boolean do_it)
+{
+  struct elf_link_hash_table *hash_table;
+  bfd_size_type oldsize;
+  bfd_size_type strindex;
+
+  hash_table = elf_hash_table (info);
+  oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+  strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
+  if (strindex == (bfd_size_type) -1)
+    return -1;
+
+  if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+    {
+      asection *sdyn;
+      const struct elf_backend_data *bed;
+      bfd_byte *extdyn;
+
+      bed = get_elf_backend_data (hash_table->dynobj);
+      sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+      BFD_ASSERT (sdyn != NULL);
+
+      for (extdyn = sdyn->contents;
+          extdyn < sdyn->contents + sdyn->_raw_size;
+          extdyn += bed->s->sizeof_dyn)
+       {
+         Elf_Internal_Dyn dyn;
+
+         bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+         if (dyn.d_tag == DT_NEEDED
+             && dyn.d_un.d_val == strindex)
+           {
+             _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+             return 1;
+           }
+       }
+    }
+
+  if (do_it)
+    {
+      if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+       return -1;
+    }
+  else
+    /* We were just checking for existence of the tag.  */
+    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+
+  return 0;
+}
+
+/* Sort symbol by value and section.  */
+int
+_bfd_elf_sort_symbol (const void *arg1, const void *arg2)
+{
+  const struct elf_link_hash_entry *h1;
+  const struct elf_link_hash_entry *h2;
+  bfd_signed_vma vdiff;
+
+  h1 = *(const struct elf_link_hash_entry **) arg1;
+  h2 = *(const struct elf_link_hash_entry **) arg2;
+  vdiff = h1->root.u.def.value - h2->root.u.def.value;
+  if (vdiff != 0)
+    return vdiff > 0 ? 1 : -1;
+  else
+    {
+      long sdiff = h1->root.u.def.section - h2->root.u.def.section;
+      if (sdiff != 0)
+       return sdiff > 0 ? 1 : -1;
+    }
+  return 0;
+}
+\f
+/* This function is used to adjust offsets into .dynstr for
+   dynamic symbols.  This is called via elf_link_hash_traverse.  */
+
+static bfd_boolean
+elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
+{
+  struct elf_strtab_hash *dynstr = data;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->dynindx != -1)
+    h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index);
+  return TRUE;
+}
+
+/* Assign string offsets in .dynstr, update all structures referencing
+   them.  */
+
+bfd_boolean
+_bfd_elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
+{
+  struct elf_link_hash_table *hash_table = elf_hash_table (info);
+  struct elf_link_local_dynamic_entry *entry;
+  struct elf_strtab_hash *dynstr = hash_table->dynstr;
+  bfd *dynobj = hash_table->dynobj;
+  asection *sdyn;
+  bfd_size_type size;
+  const struct elf_backend_data *bed;
+  bfd_byte *extdyn;
+
+  _bfd_elf_strtab_finalize (dynstr);
+  size = _bfd_elf_strtab_size (dynstr);
+
+  bed = get_elf_backend_data (dynobj);
+  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  BFD_ASSERT (sdyn != NULL);
+
+  /* Update all .dynamic entries referencing .dynstr strings.  */
+  for (extdyn = sdyn->contents;
+       extdyn < sdyn->contents + sdyn->_raw_size;
+       extdyn += bed->s->sizeof_dyn)
+    {
+      Elf_Internal_Dyn dyn;
+
+      bed->s->swap_dyn_in (dynobj, extdyn, &dyn);
+      switch (dyn.d_tag)
+       {
+       case DT_STRSZ:
+         dyn.d_un.d_val = size;
+         break;
+       case DT_NEEDED:
+       case DT_SONAME:
+       case DT_RPATH:
+       case DT_RUNPATH:
+       case DT_FILTER:
+       case DT_AUXILIARY:
+         dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val);
+         break;
+       default:
+         continue;
+       }
+      bed->s->swap_dyn_out (dynobj, &dyn, extdyn);
+    }
+
+  /* Now update local dynamic symbols.  */
+  for (entry = hash_table->dynlocal; entry ; entry = entry->next)
+    entry->isym.st_name = _bfd_elf_strtab_offset (dynstr,
+                                                 entry->isym.st_name);
+
+  /* And the rest of dynamic symbols.  */
+  elf_link_hash_traverse (hash_table, elf_adjust_dynstr_offsets, dynstr);
+
+  /* Adjust version definitions.  */
+  if (elf_tdata (output_bfd)->cverdefs)
+    {
+      asection *s;
+      bfd_byte *p;
+      bfd_size_type i;
+      Elf_Internal_Verdef def;
+      Elf_Internal_Verdaux defaux;
+
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
+      p = s->contents;
+      do
+       {
+         _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
+                                  &def);
+         p += sizeof (Elf_External_Verdef);
+         for (i = 0; i < def.vd_cnt; ++i)
+           {
+             _bfd_elf_swap_verdaux_in (output_bfd,
+                                       (Elf_External_Verdaux *) p, &defaux);
+             defaux.vda_name = _bfd_elf_strtab_offset (dynstr,
+                                                       defaux.vda_name);
+             _bfd_elf_swap_verdaux_out (output_bfd,
+                                        &defaux, (Elf_External_Verdaux *) p);
+             p += sizeof (Elf_External_Verdaux);
+           }
+       }
+      while (def.vd_next);
+    }
+
+  /* Adjust version references.  */
+  if (elf_tdata (output_bfd)->verref)
+    {
+      asection *s;
+      bfd_byte *p;
+      bfd_size_type i;
+      Elf_Internal_Verneed need;
+      Elf_Internal_Vernaux needaux;
+
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
+      p = s->contents;
+      do
+       {
+         _bfd_elf_swap_verneed_in (output_bfd, (Elf_External_Verneed *) p,
+                                   &need);
+         need.vn_file = _bfd_elf_strtab_offset (dynstr, need.vn_file);
+         _bfd_elf_swap_verneed_out (output_bfd, &need,
+                                    (Elf_External_Verneed *) p);
+         p += sizeof (Elf_External_Verneed);
+         for (i = 0; i < need.vn_cnt; ++i)
+           {
+             _bfd_elf_swap_vernaux_in (output_bfd,
+                                       (Elf_External_Vernaux *) p, &needaux);
+             needaux.vna_name = _bfd_elf_strtab_offset (dynstr,
+                                                        needaux.vna_name);
+             _bfd_elf_swap_vernaux_out (output_bfd,
+                                        &needaux,
+                                        (Elf_External_Vernaux *) p);
+             p += sizeof (Elf_External_Vernaux);
+           }
+       }
+      while (need.vn_next);
+    }
+
+  return TRUE;
+}
+\f
 /* Add symbols from an ELF archive file to the linker hash table.  We
    don't use _bfd_generic_link_add_archive_symbols because of a
    problem which arises on UnixWare.  The UnixWare libc.so is an
@@ -2809,3 +3065,975 @@ _bfd_elf_link_add_archive_symbols (bfd *abfd,
     free (included);
   return FALSE;
 }
+\f
+/* 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;
+  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)
+    {
+      alc = bfd_malloc (p - name + 1);
+      memcpy (alc, name, p - name);
+      alc[p - name] = '\0';
+      name = alc;
+    }
+
+  /* Compute the hash value.  */
+  ha = bfd_elf_hash (name);
+
+  /* Store the found hash value in the array given as the argument.  */
+  *(*valuep)++ = ha;
+
+  /* And store it in the struct so that we can put it in the hash table
+     later.  */
+  h->elf_hash_value = ha;
+
+  if (alc != NULL)
+    free (alc);
+
+  return TRUE;
+}
+
+/* Array used to determine the number of hash table buckets to use
+   based on the number of symbols there are.  If there are fewer than
+   3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets,
+   fewer than 37 we use 17 buckets, and so forth.  We never use more
+   than 32771 buckets.  */
+
+static const size_t elf_buckets[] =
+{
+  1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
+  16411, 32771, 0
+};
+
+/* Compute bucket count for hashing table.  We do not use a static set
+   of possible tables sizes anymore.  Instead we determine for all
+   possible reasonable sizes of the table the outcome (i.e., the
+   number of collisions etc) and choose the best solution.  The
+   weighting functions are not too simple to allow the table to grow
+   without bounds.  Instead one of the weighting factors is the size.
+   Therefore the result is always a good payoff between few collisions
+   (= short chain lengths) and table size.  */
+static size_t
+compute_bucket_count (struct bfd_link_info *info)
+{
+  size_t dynsymcount = elf_hash_table (info)->dynsymcount;
+  size_t best_size = 0;
+  unsigned long int *hashcodes;
+  unsigned long int *hashcodesp;
+  unsigned long int i;
+  bfd_size_type amt;
+
+  /* Compute the hash values for all exported symbols.  At the same
+     time store the values in an array so that we could use them for
+     optimizations.  */
+  amt = dynsymcount;
+  amt *= sizeof (unsigned long int);
+  hashcodes = bfd_malloc (amt);
+  if (hashcodes == NULL)
+    return 0;
+  hashcodesp = hashcodes;
+
+  /* Put all hash values in HASHCODES.  */
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_collect_hash_codes, &hashcodesp);
+
+  /* We have a problem here.  The following code to optimize the table
+     size requires an integer type with more the 32 bits.  If
+     BFD_HOST_U_64_BIT is set we know about such a type.  */
+#ifdef BFD_HOST_U_64_BIT
+  if (info->optimize)
+    {
+      unsigned long int nsyms = hashcodesp - hashcodes;
+      size_t minsize;
+      size_t maxsize;
+      BFD_HOST_U_64_BIT best_chlen = ~((BFD_HOST_U_64_BIT) 0);
+      unsigned long int *counts ;
+      bfd *dynobj = elf_hash_table (info)->dynobj;
+      const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
+
+      /* Possible optimization parameters: if we have NSYMS symbols we say
+        that the hashing table must at least have NSYMS/4 and at most
+        2*NSYMS buckets.  */
+      minsize = nsyms / 4;
+      if (minsize == 0)
+       minsize = 1;
+      best_size = maxsize = nsyms * 2;
+
+      /* Create array where we count the collisions in.  We must use bfd_malloc
+        since the size could be large.  */
+      amt = maxsize;
+      amt *= sizeof (unsigned long int);
+      counts = bfd_malloc (amt);
+      if (counts == NULL)
+       {
+         free (hashcodes);
+         return 0;
+       }
+
+      /* Compute the "optimal" size for the hash table.  The criteria is a
+        minimal chain length.  The minor criteria is (of course) the size
+        of the table.  */
+      for (i = minsize; i < maxsize; ++i)
+       {
+         /* Walk through the array of hashcodes and count the collisions.  */
+         BFD_HOST_U_64_BIT max;
+         unsigned long int j;
+         unsigned long int fact;
+
+         memset (counts, '\0', i * sizeof (unsigned long int));
+
+         /* Determine how often each hash bucket is used.  */
+         for (j = 0; j < nsyms; ++j)
+           ++counts[hashcodes[j] % i];
+
+         /* For the weight function we need some information about the
+            pagesize on the target.  This is information need not be 100%
+            accurate.  Since this information is not available (so far) we
+            define it here to a reasonable default value.  If it is crucial
+            to have a better value some day simply define this value.  */
+# ifndef BFD_TARGET_PAGESIZE
+#  define BFD_TARGET_PAGESIZE  (4096)
+# endif
+
+         /* We in any case need 2 + NSYMS entries for the size values and
+            the chains.  */
+         max = (2 + nsyms) * (bed->s->arch_size / 8);
+
+# if 1
+         /* Variant 1: optimize for short chains.  We add the squares
+            of all the chain lengths (which favors many small chain
+            over a few long chains).  */
+         for (j = 0; j < i; ++j)
+           max += counts[j] * counts[j];
+
+         /* This adds penalties for the overall size of the table.  */
+         fact = i / (BFD_TARGET_PAGESIZE / (bed->s->arch_size / 8)) + 1;
+         max *= fact * fact;
+# else
+         /* Variant 2: Optimize a lot more for small table.  Here we
+            also add squares of the size but we also add penalties for
+            empty slots (the +1 term).  */
+         for (j = 0; j < i; ++j)
+           max += (1 + counts[j]) * (1 + counts[j]);
+
+         /* The overall size of the table is considered, but not as
+            strong as in variant 1, where it is squared.  */
+         fact = i / (BFD_TARGET_PAGESIZE / (bed->s->arch_size / 8)) + 1;
+         max *= fact;
+# endif
+
+         /* Compare with current best results.  */
+         if (max < best_chlen)
+           {
+             best_chlen = max;
+             best_size = i;
+           }
+       }
+
+      free (counts);
+    }
+  else
+#endif /* defined (BFD_HOST_U_64_BIT) */
+    {
+      /* This is the fallback solution if no 64bit type is available or if we
+        are not supposed to spend much time on optimizations.  We select the
+        bucket count using a fixed set of numbers.  */
+      for (i = 0; elf_buckets[i] != 0; i++)
+       {
+         best_size = elf_buckets[i];
+         if (dynsymcount < elf_buckets[i + 1])
+           break;
+       }
+    }
+
+  /* Free the arrays we needed.  */
+  free (hashcodes);
+
+  return best_size;
+}
+
+/* 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
+   addresses of the various sections.  */
+
+bfd_boolean
+bfd_elf_size_dynamic_sections (bfd *output_bfd,
+                              const char *soname,
+                              const char *rpath,
+                              const char *filter_shlib,
+                              const char * const *auxiliary_filters,
+                              struct bfd_link_info *info,
+                              asection **sinterpptr,
+                              struct bfd_elf_version_tree *verdefs)
+{
+  bfd_size_type soname_indx;
+  bfd *dynobj;
+  const struct elf_backend_data *bed;
+  struct elf_assign_sym_version_info asvinfo;
+
+  *sinterpptr = NULL;
+
+  soname_indx = (bfd_size_type) -1;
+
+  if (!is_elf_hash_table (info->hash))
+    return TRUE;
+
+  if (info->execstack)
+    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
+  else if (info->noexecstack)
+    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
+  else
+    {
+      bfd *inputobj;
+      asection *notesec = NULL;
+      int exec = 0;
+
+      for (inputobj = info->input_bfds;
+          inputobj;
+          inputobj = inputobj->link_next)
+       {
+         asection *s;
+
+         if (inputobj->flags & DYNAMIC)
+           continue;
+         s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
+         if (s)
+           {
+             if (s->flags & SEC_CODE)
+               exec = PF_X;
+             notesec = s;
+           }
+         else
+           exec = PF_X;
+       }
+      if (notesec)
+       {
+         elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
+         if (exec && info->relocatable
+             && notesec->output_section != bfd_abs_section_ptr)
+           notesec->output_section->flags |= SEC_CODE;
+       }
+    }
+
+  /* Any syms created from now on start with -1 in
+     got.refcount/offset and plt.refcount/offset.  */
+  elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset;
+
+  /* The backend may have to create some sections regardless of whether
+     we're dynamic or not.  */
+  bed = get_elf_backend_data (output_bfd);
+  if (bed->elf_backend_always_size_sections
+      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
+    return FALSE;
+
+  dynobj = elf_hash_table (info)->dynobj;
+
+  /* If there were no dynamic objects in the link, there is nothing to
+     do here.  */
+  if (dynobj == NULL)
+    return TRUE;
+
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return FALSE;
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      struct elf_info_failed eif;
+      struct elf_link_hash_entry *h;
+      asection *dynstr;
+      struct bfd_elf_version_tree *t;
+      struct bfd_elf_version_expr *d;
+      bfd_boolean all_defined;
+
+      *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
+      BFD_ASSERT (*sinterpptr != NULL || !info->executable);
+
+      if (soname != NULL)
+       {
+         soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                            soname, TRUE);
+         if (soname_indx == (bfd_size_type) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
+           return FALSE;
+       }
+
+      if (info->symbolic)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+           return FALSE;
+         info->flags |= DF_SYMBOLIC;
+       }
+
+      if (rpath != NULL)
+       {
+         bfd_size_type indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
+                                     TRUE);
+         if (indx == (bfd_size_type) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_RPATH, indx))
+           return FALSE;
+
+         if  (info->new_dtags)
+           {
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
+             if (!_bfd_elf_add_dynamic_entry (info, DT_RUNPATH, indx))
+               return FALSE;
+           }
+       }
+
+      if (filter_shlib != NULL)
+       {
+         bfd_size_type indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                     filter_shlib, TRUE);
+         if (indx == (bfd_size_type) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
+           return FALSE;
+       }
+
+      if (auxiliary_filters != NULL)
+       {
+         const char * const *p;
+
+         for (p = auxiliary_filters; *p != NULL; p++)
+           {
+             bfd_size_type indx;
+
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         *p, TRUE);
+             if (indx == (bfd_size_type) -1
+                 || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
+               return FALSE;
+           }
+       }
+
+      eif.info = info;
+      eif.verdefs = verdefs;
+      eif.failed = FALSE;
+
+      /* If we are supposed to export all symbols into the dynamic symbol
+        table (this is not the normal case), then do so.  */
+      if (info->export_dynamic)
+       {
+         elf_link_hash_traverse (elf_hash_table (info),
+                                 _bfd_elf_export_symbol,
+                                 &eif);
+         if (eif.failed)
+           return FALSE;
+       }
+
+      /* Make all global versions with definition.  */
+      for (t = verdefs; t != NULL; t = t->next)
+       for (d = t->globals.list; d != NULL; d = d->next)
+         if (!d->symver && d->symbol)
+           {
+             const char *verstr, *name;
+             size_t namelen, verlen, newlen;
+             char *newname, *p;
+             struct elf_link_hash_entry *newh;
+
+             name = d->symbol;
+             namelen = strlen (name);
+             verstr = t->name;
+             verlen = strlen (verstr);
+             newlen = namelen + verlen + 3;
+
+             newname = bfd_malloc (newlen);
+             if (newname == NULL)
+               return FALSE;
+             memcpy (newname, name, namelen);
+
+             /* Check the hidden versioned definition.  */
+             p = newname + namelen;
+             *p++ = ELF_VER_CHR;
+             memcpy (p, verstr, verlen + 1);
+             newh = elf_link_hash_lookup (elf_hash_table (info),
+                                          newname, FALSE, FALSE,
+                                          FALSE);
+             if (newh == NULL
+                 || (newh->root.type != bfd_link_hash_defined
+                     && newh->root.type != bfd_link_hash_defweak))
+               {
+                 /* Check the default versioned definition.  */
+                 *p++ = ELF_VER_CHR;
+                 memcpy (p, verstr, verlen + 1);
+                 newh = elf_link_hash_lookup (elf_hash_table (info),
+                                              newname, FALSE, FALSE,
+                                              FALSE);
+               }
+             free (newname);
+
+             /* Mark this version if there is a definition and it is
+                not defined in a shared object.  */
+             if (newh != NULL
+                 && ((newh->elf_link_hash_flags
+                      & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
+                 && (newh->root.type == bfd_link_hash_defined
+                     || newh->root.type == bfd_link_hash_defweak))
+               d->symver = 1;
+           }
+
+      /* Attach all the symbols to their version information.  */
+      asvinfo.output_bfd = output_bfd;
+      asvinfo.info = info;
+      asvinfo.verdefs = verdefs;
+      asvinfo.failed = FALSE;
+
+      elf_link_hash_traverse (elf_hash_table (info),
+                             _bfd_elf_link_assign_sym_version,
+                             &asvinfo);
+      if (asvinfo.failed)
+       return FALSE;
+
+      if (!info->allow_undefined_version)
+       {
+         /* Check if all global versions have a definition.  */
+         all_defined = TRUE;
+         for (t = verdefs; t != NULL; t = t->next)
+           for (d = t->globals.list; d != NULL; d = d->next)
+             if (!d->symver && !d->script)
+               {
+                 (*_bfd_error_handler)
+                   (_("%s: undefined version: %s"),
+                    d->pattern, t->name);
+                 all_defined = FALSE;
+               }
+
+         if (!all_defined)
+           {
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+       }
+
+      /* Find all symbols which were defined in a dynamic object and make
+        the backend pick a reasonable value for them.  */
+      elf_link_hash_traverse (elf_hash_table (info),
+                             _bfd_elf_adjust_dynamic_symbol,
+                             &eif);
+      if (eif.failed)
+       return FALSE;
+
+      /* Add some entries to the .dynamic section.  We fill in some of the
+        values later, in elf_bfd_final_link, but we must add the entries
+        now so that we know the final size of the .dynamic section.  */
+
+      /* If there are initialization and/or finalization functions to
+        call then add the corresponding DT_INIT/DT_FINI entries.  */
+      h = (info->init_function
+          ? elf_link_hash_lookup (elf_hash_table (info),
+                                  info->init_function, FALSE,
+                                  FALSE, FALSE)
+          : NULL);
+      if (h != NULL
+         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
+           return FALSE;
+       }
+      h = (info->fini_function
+          ? elf_link_hash_lookup (elf_hash_table (info),
+                                  info->fini_function, FALSE,
+                                  FALSE, FALSE)
+          : NULL);
+      if (h != NULL
+         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
+           return FALSE;
+       }
+
+      if (bfd_get_section_by_name (output_bfd, ".preinit_array") != NULL)
+       {
+         /* DT_PREINIT_ARRAY is not allowed in shared library.  */
+         if (! info->executable)
+           {
+             bfd *sub;
+             asection *o;
+
+             for (sub = info->input_bfds; sub != NULL;
+                  sub = sub->link_next)
+               for (o = sub->sections; o != NULL; o = o->next)
+                 if (elf_section_data (o)->this_hdr.sh_type
+                     == SHT_PREINIT_ARRAY)
+                   {
+                     (*_bfd_error_handler)
+                       (_("%s: .preinit_array section is not allowed in DSO"),
+                        bfd_archive_filename (sub));
+                     break;
+                   }
+
+             bfd_set_error (bfd_error_nonrepresentable_section);
+             return FALSE;
+           }
+
+         if (!_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAY, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
+           return FALSE;
+       }
+      if (bfd_get_section_by_name (output_bfd, ".init_array") != NULL)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
+           return FALSE;
+       }
+      if (bfd_get_section_by_name (output_bfd, ".fini_array") != NULL)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
+           return FALSE;
+       }
+
+      dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
+      /* If .dynstr is excluded from the link, we don't want any of
+        these tags.  Strictly, we should be checking each section
+        individually;  This quick check covers for the case where
+        someone does a /DISCARD/ : { *(*) }.  */
+      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
+       {
+         bfd_size_type strsize;
+
+         strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+         if (!_bfd_elf_add_dynamic_entry (info, DT_HASH, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+             || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
+                                             bed->s->sizeof_sym))
+           return FALSE;
+       }
+    }
+
+  /* The backend must work out the sizes of all the other dynamic
+     sections.  */
+  if (bed->elf_backend_size_dynamic_sections
+      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
+    return FALSE;
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      bfd_size_type dynsymcount;
+      asection *s;
+      size_t bucketcount = 0;
+      size_t hash_entry_size;
+      unsigned int dtagcount;
+
+      /* Set up the version definition section.  */
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
+      BFD_ASSERT (s != NULL);
+
+      /* We may have created additional version definitions if we are
+        just linking a regular application.  */
+      verdefs = asvinfo.verdefs;
+
+      /* Skip anonymous version tag.  */
+      if (verdefs != NULL && verdefs->vernum == 0)
+       verdefs = verdefs->next;
+
+      if (verdefs == NULL)
+       _bfd_strip_section_from_output (info, s);
+      else
+       {
+         unsigned int cdefs;
+         bfd_size_type size;
+         struct bfd_elf_version_tree *t;
+         bfd_byte *p;
+         Elf_Internal_Verdef def;
+         Elf_Internal_Verdaux defaux;
+
+         cdefs = 0;
+         size = 0;
+
+         /* Make space for the base version.  */
+         size += sizeof (Elf_External_Verdef);
+         size += sizeof (Elf_External_Verdaux);
+         ++cdefs;
+
+         for (t = verdefs; t != NULL; t = t->next)
+           {
+             struct bfd_elf_version_deps *n;
+
+             size += sizeof (Elf_External_Verdef);
+             size += sizeof (Elf_External_Verdaux);
+             ++cdefs;
+
+             for (n = t->deps; n != NULL; n = n->next)
+               size += sizeof (Elf_External_Verdaux);
+           }
+
+         s->_raw_size = size;
+         s->contents = bfd_alloc (output_bfd, s->_raw_size);
+         if (s->contents == NULL && s->_raw_size != 0)
+           return FALSE;
+
+         /* Fill in the version definition section.  */
+
+         p = s->contents;
+
+         def.vd_version = VER_DEF_CURRENT;
+         def.vd_flags = VER_FLG_BASE;
+         def.vd_ndx = 1;
+         def.vd_cnt = 1;
+         def.vd_aux = sizeof (Elf_External_Verdef);
+         def.vd_next = (sizeof (Elf_External_Verdef)
+                        + sizeof (Elf_External_Verdaux));
+
+         if (soname_indx != (bfd_size_type) -1)
+           {
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                     soname_indx);
+             def.vd_hash = bfd_elf_hash (soname);
+             defaux.vda_name = soname_indx;
+           }
+         else
+           {
+             const char *name;
+             bfd_size_type indx;
+
+             name = basename (output_bfd->filename);
+             def.vd_hash = bfd_elf_hash (name);
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         name, FALSE);
+             if (indx == (bfd_size_type) -1)
+               return FALSE;
+             defaux.vda_name = indx;
+           }
+         defaux.vda_next = 0;
+
+         _bfd_elf_swap_verdef_out (output_bfd, &def,
+                                   (Elf_External_Verdef *) p);
+         p += sizeof (Elf_External_Verdef);
+         _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
+                                    (Elf_External_Verdaux *) p);
+         p += sizeof (Elf_External_Verdaux);
+
+         for (t = verdefs; t != NULL; t = t->next)
+           {
+             unsigned int cdeps;
+             struct bfd_elf_version_deps *n;
+             struct elf_link_hash_entry *h;
+             struct bfd_link_hash_entry *bh;
+
+             cdeps = 0;
+             for (n = t->deps; n != NULL; n = n->next)
+               ++cdeps;
+
+             /* Add a symbol representing this version.  */
+             bh = NULL;
+             if (! (_bfd_generic_link_add_one_symbol
+                    (info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
+                     0, NULL, FALSE,
+                     get_elf_backend_data (dynobj)->collect, &bh)))
+               return FALSE;
+             h = (struct elf_link_hash_entry *) bh;
+             h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
+             h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+             h->type = STT_OBJECT;
+             h->verinfo.vertree = t;
+
+             if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+
+             def.vd_version = VER_DEF_CURRENT;
+             def.vd_flags = 0;
+             if (t->globals.list == NULL
+                 && t->locals.list == NULL
+                 && ! t->used)
+               def.vd_flags |= VER_FLG_WEAK;
+             def.vd_ndx = t->vernum + 1;
+             def.vd_cnt = cdeps + 1;
+             def.vd_hash = bfd_elf_hash (t->name);
+             def.vd_aux = sizeof (Elf_External_Verdef);
+             def.vd_next = 0;
+             if (t->next != NULL)
+               def.vd_next = (sizeof (Elf_External_Verdef)
+                              + (cdeps + 1) * sizeof (Elf_External_Verdaux));
+
+             _bfd_elf_swap_verdef_out (output_bfd, &def,
+                                       (Elf_External_Verdef *) p);
+             p += sizeof (Elf_External_Verdef);
+
+             defaux.vda_name = h->dynstr_index;
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                     h->dynstr_index);
+             defaux.vda_next = 0;
+             if (t->deps != NULL)
+               defaux.vda_next = sizeof (Elf_External_Verdaux);
+             t->name_indx = defaux.vda_name;
+
+             _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
+                                        (Elf_External_Verdaux *) p);
+             p += sizeof (Elf_External_Verdaux);
+
+             for (n = t->deps; n != NULL; n = n->next)
+               {
+                 if (n->version_needed == NULL)
+                   {
+                     /* This can happen if there was an error in the
+                        version script.  */
+                     defaux.vda_name = 0;
+                   }
+                 else
+                   {
+                     defaux.vda_name = n->version_needed->name_indx;
+                     _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                             defaux.vda_name);
+                   }
+                 if (n->next == NULL)
+                   defaux.vda_next = 0;
+                 else
+                   defaux.vda_next = sizeof (Elf_External_Verdaux);
+
+                 _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
+                                            (Elf_External_Verdaux *) p);
+                 p += sizeof (Elf_External_Verdaux);
+               }
+           }
+
+         if (!_bfd_elf_add_dynamic_entry (info, DT_VERDEF, 0)
+             || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, cdefs))
+           return FALSE;
+
+         elf_tdata (output_bfd)->cverdefs = cdefs;
+       }
+
+      if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS, info->flags))
+           return FALSE;
+       }
+      else if (info->flags & DF_BIND_NOW)
+       {
+         if (!_bfd_elf_add_dynamic_entry (info, DT_BIND_NOW, 0))
+           return FALSE;
+       }
+
+      if (info->flags_1)
+       {
+         if (info->executable)
+           info->flags_1 &= ~ (DF_1_INITFIRST
+                               | DF_1_NODELETE
+                               | DF_1_NOOPEN);
+         if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS_1, info->flags_1))
+           return FALSE;
+       }
+
+      /* Work out the size of the version reference section.  */
+
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
+      BFD_ASSERT (s != NULL);
+      {
+       struct elf_find_verdep_info sinfo;
+
+       sinfo.output_bfd = output_bfd;
+       sinfo.info = info;
+       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+       if (sinfo.vers == 0)
+         sinfo.vers = 1;
+       sinfo.failed = FALSE;
+
+       elf_link_hash_traverse (elf_hash_table (info),
+                               _bfd_elf_link_find_version_dependencies,
+                               &sinfo);
+
+       if (elf_tdata (output_bfd)->verref == NULL)
+         _bfd_strip_section_from_output (info, s);
+       else
+         {
+           Elf_Internal_Verneed *t;
+           unsigned int size;
+           unsigned int crefs;
+           bfd_byte *p;
+
+           /* Build the version definition section.  */
+           size = 0;
+           crefs = 0;
+           for (t = elf_tdata (output_bfd)->verref;
+                t != NULL;
+                t = t->vn_nextref)
+             {
+               Elf_Internal_Vernaux *a;
+
+               size += sizeof (Elf_External_Verneed);
+               ++crefs;
+               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 size += sizeof (Elf_External_Vernaux);
+             }
+
+           s->_raw_size = size;
+           s->contents = bfd_alloc (output_bfd, s->_raw_size);
+           if (s->contents == NULL)
+             return FALSE;
+
+           p = s->contents;
+           for (t = elf_tdata (output_bfd)->verref;
+                t != NULL;
+                t = t->vn_nextref)
+             {
+               unsigned int caux;
+               Elf_Internal_Vernaux *a;
+               bfd_size_type indx;
+
+               caux = 0;
+               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 ++caux;
+
+               t->vn_version = VER_NEED_CURRENT;
+               t->vn_cnt = caux;
+               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                           elf_dt_name (t->vn_bfd) != NULL
+                                           ? elf_dt_name (t->vn_bfd)
+                                           : basename (t->vn_bfd->filename),
+                                           FALSE);
+               if (indx == (bfd_size_type) -1)
+                 return FALSE;
+               t->vn_file = indx;
+               t->vn_aux = sizeof (Elf_External_Verneed);
+               if (t->vn_nextref == NULL)
+                 t->vn_next = 0;
+               else
+                 t->vn_next = (sizeof (Elf_External_Verneed)
+                               + caux * sizeof (Elf_External_Vernaux));
+
+               _bfd_elf_swap_verneed_out (output_bfd, t,
+                                          (Elf_External_Verneed *) p);
+               p += sizeof (Elf_External_Verneed);
+
+               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+                 {
+                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
+                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                               a->vna_nodename, FALSE);
+                   if (indx == (bfd_size_type) -1)
+                     return FALSE;
+                   a->vna_name = indx;
+                   if (a->vna_nextptr == NULL)
+                     a->vna_next = 0;
+                   else
+                     a->vna_next = sizeof (Elf_External_Vernaux);
+
+                   _bfd_elf_swap_vernaux_out (output_bfd, a,
+                                              (Elf_External_Vernaux *) p);
+                   p += sizeof (Elf_External_Vernaux);
+                 }
+             }
+
+           if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
+               || !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
+             return FALSE;
+
+           elf_tdata (output_bfd)->cverrefs = crefs;
+         }
+      }
+
+      /* Assign dynsym indicies.  In a shared library we generate a
+        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.  */
+
+      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
+
+      /* Work out the size of the symbol version section.  */
+      s = bfd_get_section_by_name (dynobj, ".gnu.version");
+      BFD_ASSERT (s != NULL);
+      if (dynsymcount == 0
+         || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
+       {
+         _bfd_strip_section_from_output (info, s);
+         /* The DYNSYMCOUNT might have changed if we were going to
+            output a dynamic symbol table entry for S.  */
+         dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
+       }
+      else
+       {
+         s->_raw_size = dynsymcount * sizeof (Elf_External_Versym);
+         s->contents = bfd_zalloc (output_bfd, s->_raw_size);
+         if (s->contents == NULL)
+           return FALSE;
+
+         if (!_bfd_elf_add_dynamic_entry (info, DT_VERSYM, 0))
+           return FALSE;
+       }
+
+      /* Set the size of the .dynsym and .hash sections.  We counted
+        the number of dynamic symbols in elf_link_add_object_symbols.
+        We will build the contents of .dynsym and .hash when we build
+        the final symbol table, because until then we do not know the
+        correct value to give the symbols.  We built the .dynstr
+        section as we went along in elf_link_add_object_symbols.  */
+      s = bfd_get_section_by_name (dynobj, ".dynsym");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size = dynsymcount * bed->s->sizeof_sym;
+      s->contents = bfd_alloc (output_bfd, s->_raw_size);
+      if (s->contents == NULL && s->_raw_size != 0)
+       return FALSE;
+
+      if (dynsymcount != 0)
+       {
+         Elf_Internal_Sym isym;
+
+         /* The first entry in .dynsym is a dummy symbol.  */
+         isym.st_value = 0;
+         isym.st_size = 0;
+         isym.st_name = 0;
+         isym.st_info = 0;
+         isym.st_other = 0;
+         isym.st_shndx = 0;
+         bed->s->swap_symbol_out (output_bfd, &isym, s->contents, 0);
+       }
+
+      /* Compute the size of the hashing table.  As a side effect this
+        computes the hash values for all the names we export.  */
+      bucketcount = compute_bucket_count (info);
+
+      s = bfd_get_section_by_name (dynobj, ".hash");
+      BFD_ASSERT (s != NULL);
+      hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
+      s->_raw_size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
+      s->contents = bfd_zalloc (output_bfd, s->_raw_size);
+      if (s->contents == NULL)
+       return FALSE;
+
+      bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
+      bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
+              s->contents + hash_entry_size);
+
+      elf_hash_table (info)->bucketcount = bucketcount;
+
+      s = bfd_get_section_by_name (dynobj, ".dynstr");
+      BFD_ASSERT (s != NULL);
+
+      _bfd_elf_finalize_dynstr (output_bfd, info);
+
+      s->_raw_size = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+
+      for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
+       if (!_bfd_elf_add_dynamic_entry (info, DT_NULL, 0))
+         return FALSE;
+    }
+
+  return TRUE;
+}
index adecd80..082db5c 100644 (file)
@@ -23,9 +23,6 @@
 #include "safe-ctype.h"
 
 static bfd_boolean elf_link_add_object_symbols (bfd *, struct bfd_link_info *);
-static bfd_boolean elf_finalize_dynstr (bfd *, struct bfd_link_info *);
-static bfd_boolean elf_collect_hash_codes (struct elf_link_hash_entry *,
-                                          void *);
 static bfd_boolean elf_section_ignore_discarded_relocs (asection *);
 
 /* Given an ELF BFD, add symbols to the global hash table as
@@ -45,81 +42,6 @@ elf_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
       return FALSE;
     }
 }
-\f
-/* Sort symbol by value and section.  */
-static int
-sort_symbol (const void *arg1, const void *arg2)
-{
-  const struct elf_link_hash_entry *h1
-    = *(const struct elf_link_hash_entry **) arg1;
-  const struct elf_link_hash_entry *h2
-    = *(const struct elf_link_hash_entry **) arg2;
-  bfd_signed_vma vdiff = h1->root.u.def.value - h2->root.u.def.value;
-
-  if (vdiff)
-    return vdiff > 0 ? 1 : -1;
-  else
-    {
-      long sdiff = h1->root.u.def.section - h2->root.u.def.section;
-      if (sdiff)
-       return sdiff > 0 ? 1 : -1;
-      else
-       return 0;
-    }
-}
-
-/* Add a DT_NEEDED entry for this dynamic object.  Returns -1 on error,
-   1 if a DT_NEEDED tag already exists, and 0 on success.  */
-
-static int
-add_dt_needed_tag (struct bfd_link_info *info, const char *soname,
-                  bfd_boolean do_it)
-{
-  struct elf_link_hash_table *hash_table;
-  bfd_size_type oldsize;
-  bfd_size_type strindex;
-
-  hash_table = elf_hash_table (info);
-  oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
-  strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE);
-  if (strindex == (bfd_size_type) -1)
-    return -1;
-
-  if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
-    {
-      asection *sdyn;
-      Elf_External_Dyn *dyncon, *dynconend;
-
-      sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
-      BFD_ASSERT (sdyn != NULL);
-
-      dyncon = (Elf_External_Dyn *) sdyn->contents;
-      dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
-      for (; dyncon < dynconend; dyncon++)
-       {
-         Elf_Internal_Dyn dyn;
-
-         elf_swap_dyn_in (hash_table->dynobj, dyncon, & dyn);
-         if (dyn.d_tag == DT_NEEDED
-             && dyn.d_un.d_val == strindex)
-           {
-             _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
-             return 1;
-           }
-       }
-    }
-
-  if (do_it)
-    {
-      if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
-       return -1;
-    }
-  else
-    /* We were just checking for existence of the tag.  */
-    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
-
-  return 0;
-}
 
 /* Add symbols from an ELF object file to the linker hash table.  */
 
@@ -457,7 +379,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
         will need to know it.  */
       elf_dt_name (abfd) = soname;
 
-      ret = add_dt_needed_tag (info, soname, add_needed);
+      ret = _bfd_elf_add_dt_needed_tag (info, soname, add_needed);
       if (ret < 0)
        goto error_return;
 
@@ -1061,20 +983,24 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              case STV_INTERNAL:
              case STV_HIDDEN:
                (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+               dynsym = FALSE;
                break;
              }
 
-         if (!add_needed && definition
+         if (!add_needed
+             && definition
+             && dynsym
              && (h->elf_link_hash_flags
                  & ELF_LINK_HASH_REF_REGULAR) != 0)
            {
              int ret;
+             const char *soname = elf_dt_name (abfd);
 
              /* A symbol from a library loaded via DT_NEEDED of some
                 other library is referenced by a regular object.
                 Add a DT_NEEDED entry for it.  */
              add_needed = TRUE;
-             ret = add_dt_needed_tag (info, elf_dt_name (abfd), add_needed);
+             ret = _bfd_elf_add_dt_needed_tag (info, soname, add_needed);
              if (ret < 0)
                goto error_free_vers;
 
@@ -1189,7 +1115,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
       qsort (sorted_sym_hash, sym_count,
             sizeof (struct elf_link_hash_entry *),
-            sort_symbol);
+            _bfd_elf_sort_symbol);
 
       while (weaks != NULL)
        {
@@ -1420,1103 +1346,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
  error_return:
   return FALSE;
 }
-
-/* Add an entry to the .dynamic table.  */
-
-bfd_boolean
-elf_add_dynamic_entry (struct bfd_link_info *info, bfd_vma tag, bfd_vma val)
-{
-  Elf_Internal_Dyn dyn;
-  bfd *dynobj;
-  asection *s;
-  bfd_size_type newsize;
-  bfd_byte *newcontents;
-
-  if (! is_elf_hash_table (info->hash))
-    return FALSE;
-
-  dynobj = elf_hash_table (info)->dynobj;
-
-  s = bfd_get_section_by_name (dynobj, ".dynamic");
-  BFD_ASSERT (s != NULL);
-
-  newsize = s->_raw_size + sizeof (Elf_External_Dyn);
-  newcontents = bfd_realloc (s->contents, newsize);
-  if (newcontents == NULL)
-    return FALSE;
-
-  dyn.d_tag = tag;
-  dyn.d_un.d_val = val;
-  elf_swap_dyn_out (dynobj, &dyn,
-                   (Elf_External_Dyn *) (newcontents + s->_raw_size));
-
-  s->_raw_size = newsize;
-  s->contents = newcontents;
-
-  return TRUE;
-}
-\f
-/* Array used to determine the number of hash table buckets to use
-   based on the number of symbols there are.  If there are fewer than
-   3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets,
-   fewer than 37 we use 17 buckets, and so forth.  We never use more
-   than 32771 buckets.  */
-
-static const size_t elf_buckets[] =
-{
-  1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
-  16411, 32771, 0
-};
-
-/* Compute bucket count for hashing table.  We do not use a static set
-   of possible tables sizes anymore.  Instead we determine for all
-   possible reasonable sizes of the table the outcome (i.e., the
-   number of collisions etc) and choose the best solution.  The
-   weighting functions are not too simple to allow the table to grow
-   without bounds.  Instead one of the weighting factors is the size.
-   Therefore the result is always a good payoff between few collisions
-   (= short chain lengths) and table size.  */
-static size_t
-compute_bucket_count (struct bfd_link_info *info)
-{
-  size_t dynsymcount = elf_hash_table (info)->dynsymcount;
-  size_t best_size = 0;
-  unsigned long int *hashcodes;
-  unsigned long int *hashcodesp;
-  unsigned long int i;
-  bfd_size_type amt;
-
-  /* Compute the hash values for all exported symbols.  At the same
-     time store the values in an array so that we could use them for
-     optimizations.  */
-  amt = dynsymcount;
-  amt *= sizeof (unsigned long int);
-  hashcodes = bfd_malloc (amt);
-  if (hashcodes == NULL)
-    return 0;
-  hashcodesp = hashcodes;
-
-  /* Put all hash values in HASHCODES.  */
-  elf_link_hash_traverse (elf_hash_table (info),
-                         elf_collect_hash_codes, &hashcodesp);
-
-  /* We have a problem here.  The following code to optimize the table
-     size requires an integer type with more the 32 bits.  If
-     BFD_HOST_U_64_BIT is set we know about such a type.  */
-#ifdef BFD_HOST_U_64_BIT
-  if (info->optimize)
-    {
-      unsigned long int nsyms = hashcodesp - hashcodes;
-      size_t minsize;
-      size_t maxsize;
-      BFD_HOST_U_64_BIT best_chlen = ~((BFD_HOST_U_64_BIT) 0);
-      unsigned long int *counts ;
-
-      /* Possible optimization parameters: if we have NSYMS symbols we say
-        that the hashing table must at least have NSYMS/4 and at most
-        2*NSYMS buckets.  */
-      minsize = nsyms / 4;
-      if (minsize == 0)
-       minsize = 1;
-      best_size = maxsize = nsyms * 2;
-
-      /* Create array where we count the collisions in.  We must use bfd_malloc
-        since the size could be large.  */
-      amt = maxsize;
-      amt *= sizeof (unsigned long int);
-      counts = bfd_malloc (amt);
-      if (counts == NULL)
-       {
-         free (hashcodes);
-         return 0;
-       }
-
-      /* Compute the "optimal" size for the hash table.  The criteria is a
-        minimal chain length.  The minor criteria is (of course) the size
-        of the table.  */
-      for (i = minsize; i < maxsize; ++i)
-       {
-         /* Walk through the array of hashcodes and count the collisions.  */
-         BFD_HOST_U_64_BIT max;
-         unsigned long int j;
-         unsigned long int fact;
-
-         memset (counts, '\0', i * sizeof (unsigned long int));
-
-         /* Determine how often each hash bucket is used.  */
-         for (j = 0; j < nsyms; ++j)
-           ++counts[hashcodes[j] % i];
-
-         /* For the weight function we need some information about the
-            pagesize on the target.  This is information need not be 100%
-            accurate.  Since this information is not available (so far) we
-            define it here to a reasonable default value.  If it is crucial
-            to have a better value some day simply define this value.  */
-# ifndef BFD_TARGET_PAGESIZE
-#  define BFD_TARGET_PAGESIZE  (4096)
-# endif
-
-         /* We in any case need 2 + NSYMS entries for the size values and
-            the chains.  */
-         max = (2 + nsyms) * (ARCH_SIZE / 8);
-
-# if 1
-         /* Variant 1: optimize for short chains.  We add the squares
-            of all the chain lengths (which favors many small chain
-            over a few long chains).  */
-         for (j = 0; j < i; ++j)
-           max += counts[j] * counts[j];
-
-         /* This adds penalties for the overall size of the table.  */
-         fact = i / (BFD_TARGET_PAGESIZE / (ARCH_SIZE / 8)) + 1;
-         max *= fact * fact;
-# else
-         /* Variant 2: Optimize a lot more for small table.  Here we
-            also add squares of the size but we also add penalties for
-            empty slots (the +1 term).  */
-         for (j = 0; j < i; ++j)
-           max += (1 + counts[j]) * (1 + counts[j]);
-
-         /* The overall size of the table is considered, but not as
-            strong as in variant 1, where it is squared.  */
-         fact = i / (BFD_TARGET_PAGESIZE / (ARCH_SIZE / 8)) + 1;
-         max *= fact;
-# endif
-
-         /* Compare with current best results.  */
-         if (max < best_chlen)
-           {
-             best_chlen = max;
-             best_size = i;
-           }
-       }
-
-      free (counts);
-    }
-  else
-#endif /* defined (BFD_HOST_U_64_BIT) */
-    {
-      /* This is the fallback solution if no 64bit type is available or if we
-        are not supposed to spend much time on optimizations.  We select the
-        bucket count using a fixed set of numbers.  */
-      for (i = 0; elf_buckets[i] != 0; i++)
-       {
-         best_size = elf_buckets[i];
-         if (dynsymcount < elf_buckets[i + 1])
-           break;
-       }
-    }
-
-  /* Free the arrays we needed.  */
-  free (hashcodes);
-
-  return best_size;
-}
-
-/* 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
-   addresses of the various sections.  */
-
-bfd_boolean
-NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
-                                    const char *soname,
-                                    const char *rpath,
-                                    const char *filter_shlib,
-                                    const char * const *auxiliary_filters,
-                                    struct bfd_link_info *info,
-                                    asection **sinterpptr,
-                                    struct bfd_elf_version_tree *verdefs)
-{
-  bfd_size_type soname_indx;
-  bfd *dynobj;
-  const struct elf_backend_data *bed;
-  struct elf_assign_sym_version_info asvinfo;
-
-  *sinterpptr = NULL;
-
-  soname_indx = (bfd_size_type) -1;
-
-  if (!is_elf_hash_table (info->hash))
-    return TRUE;
-
-  if (info->execstack)
-    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
-  else if (info->noexecstack)
-    elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
-  else
-    {
-      bfd *inputobj;
-      asection *notesec = NULL;
-      int exec = 0;
-
-      for (inputobj = info->input_bfds;
-          inputobj;
-          inputobj = inputobj->link_next)
-       {
-         asection *s;
-
-         if (inputobj->flags & DYNAMIC)
-           continue;
-         s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
-         if (s)
-           {
-             if (s->flags & SEC_CODE)
-               exec = PF_X;
-             notesec = s;
-           }
-         else
-           exec = PF_X;
-       }
-      if (notesec)
-       {
-         elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
-         if (exec && info->relocatable
-             && notesec->output_section != bfd_abs_section_ptr)
-           notesec->output_section->flags |= SEC_CODE;
-       }
-    }
-
-  /* Any syms created from now on start with -1 in
-     got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset;
-
-  /* The backend may have to create some sections regardless of whether
-     we're dynamic or not.  */
-  bed = get_elf_backend_data (output_bfd);
-  if (bed->elf_backend_always_size_sections
-      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
-    return FALSE;
-
-  dynobj = elf_hash_table (info)->dynobj;
-
-  /* If there were no dynamic objects in the link, there is nothing to
-     do here.  */
-  if (dynobj == NULL)
-    return TRUE;
-
-  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    return FALSE;
-
-  if (elf_hash_table (info)->dynamic_sections_created)
-    {
-      struct elf_info_failed eif;
-      struct elf_link_hash_entry *h;
-      asection *dynstr;
-      struct bfd_elf_version_tree *t;
-      struct bfd_elf_version_expr *d;
-      bfd_boolean all_defined;
-
-      *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !info->executable);
-
-      if (soname != NULL)
-       {
-         soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                            soname, TRUE);
-         if (soname_indx == (bfd_size_type) -1
-             || ! elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
-           return FALSE;
-       }
-
-      if (info->symbolic)
-       {
-         if (! elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
-           return FALSE;
-         info->flags |= DF_SYMBOLIC;
-       }
-
-      if (rpath != NULL)
-       {
-         bfd_size_type indx;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
-                                     TRUE);
-         if (info->new_dtags)
-           _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
-         if (indx == (bfd_size_type) -1
-             || ! elf_add_dynamic_entry (info, DT_RPATH, indx)
-             || (info->new_dtags
-                 && ! elf_add_dynamic_entry (info, DT_RUNPATH, indx)))
-           return FALSE;
-       }
-
-      if (filter_shlib != NULL)
-       {
-         bfd_size_type indx;
-
-         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                     filter_shlib, TRUE);
-         if (indx == (bfd_size_type) -1
-             || ! elf_add_dynamic_entry (info, DT_FILTER, indx))
-           return FALSE;
-       }
-
-      if (auxiliary_filters != NULL)
-       {
-         const char * const *p;
-
-         for (p = auxiliary_filters; *p != NULL; p++)
-           {
-             bfd_size_type indx;
-
-             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                         *p, TRUE);
-             if (indx == (bfd_size_type) -1
-                 || ! elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
-               return FALSE;
-           }
-       }
-
-      eif.info = info;
-      eif.verdefs = verdefs;
-      eif.failed = FALSE;
-
-      /* If we are supposed to export all symbols into the dynamic symbol
-        table (this is not the normal case), then do so.  */
-      if (info->export_dynamic)
-       {
-         elf_link_hash_traverse (elf_hash_table (info),
-                                 _bfd_elf_export_symbol,
-                                 &eif);
-         if (eif.failed)
-           return FALSE;
-       }
-
-      /* Make all global versions with definition.  */
-      for (t = verdefs; t != NULL; t = t->next)
-       for (d = t->globals.list; d != NULL; d = d->next)
-         if (!d->symver && d->symbol)
-           {
-             const char *verstr, *name;
-             size_t namelen, verlen, newlen;
-             char *newname, *p;
-             struct elf_link_hash_entry *newh;
-
-             name = d->symbol;
-             namelen = strlen (name);
-             verstr = t->name;
-             verlen = strlen (verstr);
-             newlen = namelen + verlen + 3;
-
-             newname = bfd_malloc (newlen);
-             if (newname == NULL)
-               return FALSE;
-             memcpy (newname, name, namelen);
-
-             /* Check the hidden versioned definition.  */
-             p = newname + namelen;
-             *p++ = ELF_VER_CHR;
-             memcpy (p, verstr, verlen + 1);
-             newh = elf_link_hash_lookup (elf_hash_table (info),
-                                          newname, FALSE, FALSE,
-                                          FALSE);
-             if (newh == NULL
-                 || (newh->root.type != bfd_link_hash_defined
-                     && newh->root.type != bfd_link_hash_defweak))
-               {
-                 /* Check the default versioned definition.  */
-                 *p++ = ELF_VER_CHR;
-                 memcpy (p, verstr, verlen + 1);
-                 newh = elf_link_hash_lookup (elf_hash_table (info),
-                                              newname, FALSE, FALSE,
-                                              FALSE);
-               }
-             free (newname);
-
-             /* Mark this version if there is a definition and it is
-                not defined in a shared object.  */
-             if (newh != NULL
-                 && ((newh->elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
-                 && (newh->root.type == bfd_link_hash_defined
-                     || newh->root.type == bfd_link_hash_defweak))
-               d->symver = 1;
-           }
-
-      /* Attach all the symbols to their version information.  */
-      asvinfo.output_bfd = output_bfd;
-      asvinfo.info = info;
-      asvinfo.verdefs = verdefs;
-      asvinfo.failed = FALSE;
-
-      elf_link_hash_traverse (elf_hash_table (info),
-                             _bfd_elf_link_assign_sym_version,
-                             &asvinfo);
-      if (asvinfo.failed)
-       return FALSE;
-
-      if (!info->allow_undefined_version)
-       {
-         /* Check if all global versions have a definition.  */
-         all_defined = TRUE;
-         for (t = verdefs; t != NULL; t = t->next)
-           for (d = t->globals.list; d != NULL; d = d->next)
-             if (!d->symver && !d->script)
-               {
-                 (*_bfd_error_handler)
-                   (_("%s: undefined version: %s"),
-                    d->pattern, t->name);
-                 all_defined = FALSE;
-               }
-
-         if (!all_defined)
-           {
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-       }
-
-      /* Find all symbols which were defined in a dynamic object and make
-        the backend pick a reasonable value for them.  */
-      elf_link_hash_traverse (elf_hash_table (info),
-                             _bfd_elf_adjust_dynamic_symbol,
-                             &eif);
-      if (eif.failed)
-       return FALSE;
-
-      /* Add some entries to the .dynamic section.  We fill in some of the
-        values later, in elf_bfd_final_link, but we must add the entries
-        now so that we know the final size of the .dynamic section.  */
-
-      /* If there are initialization and/or finalization functions to
-        call then add the corresponding DT_INIT/DT_FINI entries.  */
-      h = (info->init_function
-          ? elf_link_hash_lookup (elf_hash_table (info),
-                                  info->init_function, FALSE,
-                                  FALSE, FALSE)
-          : NULL);
-      if (h != NULL
-         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
-                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
-       {
-         if (! elf_add_dynamic_entry (info, DT_INIT, 0))
-           return FALSE;
-       }
-      h = (info->fini_function
-          ? elf_link_hash_lookup (elf_hash_table (info),
-                                  info->fini_function, FALSE,
-                                  FALSE, FALSE)
-          : NULL);
-      if (h != NULL
-         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
-                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
-       {
-         if (! elf_add_dynamic_entry (info, DT_FINI, 0))
-           return FALSE;
-       }
-
-      if (bfd_get_section_by_name (output_bfd, ".preinit_array") != NULL)
-       {
-         /* DT_PREINIT_ARRAY is not allowed in shared library.  */
-         if (! info->executable)
-           {
-             bfd *sub;
-             asection *o;
-
-             for (sub = info->input_bfds; sub != NULL;
-                  sub = sub->link_next)
-               for (o = sub->sections; o != NULL; o = o->next)
-                 if (elf_section_data (o)->this_hdr.sh_type
-                     == SHT_PREINIT_ARRAY)
-                   {
-                     (*_bfd_error_handler)
-                       (_("%s: .preinit_array section is not allowed in DSO"),
-                        bfd_archive_filename (sub));
-                     break;
-                   }
-
-             bfd_set_error (bfd_error_nonrepresentable_section);
-             return FALSE;
-           }
-
-         if (!elf_add_dynamic_entry (info, DT_PREINIT_ARRAY, 0)
-             || !elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
-           return FALSE;
-       }
-      if (bfd_get_section_by_name (output_bfd, ".init_array") != NULL)
-       {
-         if (!elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
-             || !elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
-           return FALSE;
-       }
-      if (bfd_get_section_by_name (output_bfd, ".fini_array") != NULL)
-       {
-         if (!elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
-             || !elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
-           return FALSE;
-       }
-
-      dynstr = bfd_get_section_by_name (dynobj, ".dynstr");
-      /* If .dynstr is excluded from the link, we don't want any of
-        these tags.  Strictly, we should be checking each section
-        individually;  This quick check covers for the case where
-        someone does a /DISCARD/ : { *(*) }.  */
-      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
-       {
-         bfd_size_type strsize;
-
-         strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
-         if (! elf_add_dynamic_entry (info, DT_HASH, 0)
-             || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
-             || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
-             || ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
-             || ! elf_add_dynamic_entry (info, DT_SYMENT,
-                                         sizeof (Elf_External_Sym)))
-           return FALSE;
-       }
-    }
-
-  /* The backend must work out the sizes of all the other dynamic
-     sections.  */
-  if (bed->elf_backend_size_dynamic_sections
-      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
-    return FALSE;
-
-  if (elf_hash_table (info)->dynamic_sections_created)
-    {
-      bfd_size_type dynsymcount;
-      asection *s;
-      size_t bucketcount = 0;
-      size_t hash_entry_size;
-      unsigned int dtagcount;
-
-      /* Set up the version definition section.  */
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
-      BFD_ASSERT (s != NULL);
-
-      /* We may have created additional version definitions if we are
-        just linking a regular application.  */
-      verdefs = asvinfo.verdefs;
-
-      /* Skip anonymous version tag.  */
-      if (verdefs != NULL && verdefs->vernum == 0)
-       verdefs = verdefs->next;
-
-      if (verdefs == NULL)
-       _bfd_strip_section_from_output (info, s);
-      else
-       {
-         unsigned int cdefs;
-         bfd_size_type size;
-         struct bfd_elf_version_tree *t;
-         bfd_byte *p;
-         Elf_Internal_Verdef def;
-         Elf_Internal_Verdaux defaux;
-
-         cdefs = 0;
-         size = 0;
-
-         /* Make space for the base version.  */
-         size += sizeof (Elf_External_Verdef);
-         size += sizeof (Elf_External_Verdaux);
-         ++cdefs;
-
-         for (t = verdefs; t != NULL; t = t->next)
-           {
-             struct bfd_elf_version_deps *n;
-
-             size += sizeof (Elf_External_Verdef);
-             size += sizeof (Elf_External_Verdaux);
-             ++cdefs;
-
-             for (n = t->deps; n != NULL; n = n->next)
-               size += sizeof (Elf_External_Verdaux);
-           }
-
-         s->_raw_size = size;
-         s->contents = bfd_alloc (output_bfd, s->_raw_size);
-         if (s->contents == NULL && s->_raw_size != 0)
-           return FALSE;
-
-         /* Fill in the version definition section.  */
-
-         p = s->contents;
-
-         def.vd_version = VER_DEF_CURRENT;
-         def.vd_flags = VER_FLG_BASE;
-         def.vd_ndx = 1;
-         def.vd_cnt = 1;
-         def.vd_aux = sizeof (Elf_External_Verdef);
-         def.vd_next = (sizeof (Elf_External_Verdef)
-                        + sizeof (Elf_External_Verdaux));
-
-         if (soname_indx != (bfd_size_type) -1)
-           {
-             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
-                                     soname_indx);
-             def.vd_hash = bfd_elf_hash (soname);
-             defaux.vda_name = soname_indx;
-           }
-         else
-           {
-             const char *name;
-             bfd_size_type indx;
-
-             name = basename (output_bfd->filename);
-             def.vd_hash = bfd_elf_hash (name);
-             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                         name, FALSE);
-             if (indx == (bfd_size_type) -1)
-               return FALSE;
-             defaux.vda_name = indx;
-           }
-         defaux.vda_next = 0;
-
-         _bfd_elf_swap_verdef_out (output_bfd, &def,
-                                   (Elf_External_Verdef *) p);
-         p += sizeof (Elf_External_Verdef);
-         _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
-                                    (Elf_External_Verdaux *) p);
-         p += sizeof (Elf_External_Verdaux);
-
-         for (t = verdefs; t != NULL; t = t->next)
-           {
-             unsigned int cdeps;
-             struct bfd_elf_version_deps *n;
-             struct elf_link_hash_entry *h;
-             struct bfd_link_hash_entry *bh;
-
-             cdeps = 0;
-             for (n = t->deps; n != NULL; n = n->next)
-               ++cdeps;
-
-             /* Add a symbol representing this version.  */
-             bh = NULL;
-             if (! (_bfd_generic_link_add_one_symbol
-                    (info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
-                     0, NULL, FALSE,
-                     get_elf_backend_data (dynobj)->collect, &bh)))
-               return FALSE;
-             h = (struct elf_link_hash_entry *) bh;
-             h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
-             h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
-             h->type = STT_OBJECT;
-             h->verinfo.vertree = t;
-
-             if (! _bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
-
-             def.vd_version = VER_DEF_CURRENT;
-             def.vd_flags = 0;
-             if (t->globals.list == NULL && t->locals.list == NULL && ! t->used)
-               def.vd_flags |= VER_FLG_WEAK;
-             def.vd_ndx = t->vernum + 1;
-             def.vd_cnt = cdeps + 1;
-             def.vd_hash = bfd_elf_hash (t->name);
-             def.vd_aux = sizeof (Elf_External_Verdef);
-             if (t->next != NULL)
-               def.vd_next = (sizeof (Elf_External_Verdef)
-                              + (cdeps + 1) * sizeof (Elf_External_Verdaux));
-             else
-               def.vd_next = 0;
-
-             _bfd_elf_swap_verdef_out (output_bfd, &def,
-                                       (Elf_External_Verdef *) p);
-             p += sizeof (Elf_External_Verdef);
-
-             defaux.vda_name = h->dynstr_index;
-             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
-                                     h->dynstr_index);
-             if (t->deps == NULL)
-               defaux.vda_next = 0;
-             else
-               defaux.vda_next = sizeof (Elf_External_Verdaux);
-             t->name_indx = defaux.vda_name;
-
-             _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
-                                        (Elf_External_Verdaux *) p);
-             p += sizeof (Elf_External_Verdaux);
-
-             for (n = t->deps; n != NULL; n = n->next)
-               {
-                 if (n->version_needed == NULL)
-                   {
-                     /* This can happen if there was an error in the
-                        version script.  */
-                     defaux.vda_name = 0;
-                   }
-                 else
-                   {
-                     defaux.vda_name = n->version_needed->name_indx;
-                     _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
-                                             defaux.vda_name);
-                   }
-                 if (n->next == NULL)
-                   defaux.vda_next = 0;
-                 else
-                   defaux.vda_next = sizeof (Elf_External_Verdaux);
-
-                 _bfd_elf_swap_verdaux_out (output_bfd, &defaux,
-                                            (Elf_External_Verdaux *) p);
-                 p += sizeof (Elf_External_Verdaux);
-               }
-           }
-
-         if (! elf_add_dynamic_entry (info, DT_VERDEF, 0)
-             || ! elf_add_dynamic_entry (info, DT_VERDEFNUM, cdefs))
-           return FALSE;
-
-         elf_tdata (output_bfd)->cverdefs = cdefs;
-       }
-
-      if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
-       {
-         if (! elf_add_dynamic_entry (info, DT_FLAGS, info->flags))
-           return FALSE;
-       }
-      else if (info->flags & DF_BIND_NOW)
-       {
-         if (! elf_add_dynamic_entry (info, DT_BIND_NOW, 0))
-           return FALSE;
-       }
-
-      if (info->flags_1)
-       {
-         if (info->executable)
-           info->flags_1 &= ~ (DF_1_INITFIRST
-                               | DF_1_NODELETE
-                               | DF_1_NOOPEN);
-         if (! elf_add_dynamic_entry (info, DT_FLAGS_1, info->flags_1))
-           return FALSE;
-       }
-
-      /* Work out the size of the version reference section.  */
-
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
-      BFD_ASSERT (s != NULL);
-      {
-       struct elf_find_verdep_info sinfo;
-
-       sinfo.output_bfd = output_bfd;
-       sinfo.info = info;
-       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
-       if (sinfo.vers == 0)
-         sinfo.vers = 1;
-       sinfo.failed = FALSE;
-
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_link_find_version_dependencies,
-                               &sinfo);
-
-       if (elf_tdata (output_bfd)->verref == NULL)
-         _bfd_strip_section_from_output (info, s);
-       else
-         {
-           Elf_Internal_Verneed *t;
-           unsigned int size;
-           unsigned int crefs;
-           bfd_byte *p;
-
-           /* Build the version definition section.  */
-           size = 0;
-           crefs = 0;
-           for (t = elf_tdata (output_bfd)->verref;
-                t != NULL;
-                t = t->vn_nextref)
-             {
-               Elf_Internal_Vernaux *a;
-
-               size += sizeof (Elf_External_Verneed);
-               ++crefs;
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 size += sizeof (Elf_External_Vernaux);
-             }
-
-           s->_raw_size = size;
-           s->contents = bfd_alloc (output_bfd, s->_raw_size);
-           if (s->contents == NULL)
-             return FALSE;
-
-           p = s->contents;
-           for (t = elf_tdata (output_bfd)->verref;
-                t != NULL;
-                t = t->vn_nextref)
-             {
-               unsigned int caux;
-               Elf_Internal_Vernaux *a;
-               bfd_size_type indx;
-
-               caux = 0;
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 ++caux;
-
-               t->vn_version = VER_NEED_CURRENT;
-               t->vn_cnt = caux;
-               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                           elf_dt_name (t->vn_bfd) != NULL
-                                           ? elf_dt_name (t->vn_bfd)
-                                           : basename (t->vn_bfd->filename),
-                                           FALSE);
-               if (indx == (bfd_size_type) -1)
-                 return FALSE;
-               t->vn_file = indx;
-               t->vn_aux = sizeof (Elf_External_Verneed);
-               if (t->vn_nextref == NULL)
-                 t->vn_next = 0;
-               else
-                 t->vn_next = (sizeof (Elf_External_Verneed)
-                               + caux * sizeof (Elf_External_Vernaux));
-
-               _bfd_elf_swap_verneed_out (output_bfd, t,
-                                          (Elf_External_Verneed *) p);
-               p += sizeof (Elf_External_Verneed);
-
-               for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 {
-                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
-                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                               a->vna_nodename, FALSE);
-                   if (indx == (bfd_size_type) -1)
-                     return FALSE;
-                   a->vna_name = indx;
-                   if (a->vna_nextptr == NULL)
-                     a->vna_next = 0;
-                   else
-                     a->vna_next = sizeof (Elf_External_Vernaux);
-
-                   _bfd_elf_swap_vernaux_out (output_bfd, a,
-                                              (Elf_External_Vernaux *) p);
-                   p += sizeof (Elf_External_Vernaux);
-                 }
-             }
-
-           if (! elf_add_dynamic_entry (info, DT_VERNEED, 0)
-               || ! elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
-             return FALSE;
-
-           elf_tdata (output_bfd)->cverrefs = crefs;
-         }
-      }
-
-      /* Assign dynsym indicies.  In a shared library we generate a
-        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.  */
-
-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
-
-      /* Work out the size of the symbol version section.  */
-      s = bfd_get_section_by_name (dynobj, ".gnu.version");
-      BFD_ASSERT (s != NULL);
-      if (dynsymcount == 0
-         || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
-       {
-         _bfd_strip_section_from_output (info, s);
-         /* The DYNSYMCOUNT might have changed if we were going to
-            output a dynamic symbol table entry for S.  */
-         dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
-       }
-      else
-       {
-         s->_raw_size = dynsymcount * sizeof (Elf_External_Versym);
-         s->contents = bfd_zalloc (output_bfd, s->_raw_size);
-         if (s->contents == NULL)
-           return FALSE;
-
-         if (! elf_add_dynamic_entry (info, DT_VERSYM, 0))
-           return FALSE;
-       }
-
-      /* Set the size of the .dynsym and .hash sections.  We counted
-        the number of dynamic symbols in elf_link_add_object_symbols.
-        We will build the contents of .dynsym and .hash when we build
-        the final symbol table, because until then we do not know the
-        correct value to give the symbols.  We built the .dynstr
-        section as we went along in elf_link_add_object_symbols.  */
-      s = bfd_get_section_by_name (dynobj, ".dynsym");
-      BFD_ASSERT (s != NULL);
-      s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
-      s->contents = bfd_alloc (output_bfd, s->_raw_size);
-      if (s->contents == NULL && s->_raw_size != 0)
-       return FALSE;
-
-      if (dynsymcount != 0)
-       {
-         Elf_Internal_Sym isym;
-
-         /* The first entry in .dynsym is a dummy symbol.  */
-         isym.st_value = 0;
-         isym.st_size = 0;
-         isym.st_name = 0;
-         isym.st_info = 0;
-         isym.st_other = 0;
-         isym.st_shndx = 0;
-         elf_swap_symbol_out (output_bfd, &isym, s->contents, 0);
-       }
-
-      /* Compute the size of the hashing table.  As a side effect this
-        computes the hash values for all the names we export.  */
-      bucketcount = compute_bucket_count (info);
-
-      s = bfd_get_section_by_name (dynobj, ".hash");
-      BFD_ASSERT (s != NULL);
-      hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
-      s->_raw_size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
-      s->contents = bfd_zalloc (output_bfd, s->_raw_size);
-      if (s->contents == NULL)
-       return FALSE;
-
-      bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
-      bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
-              s->contents + hash_entry_size);
-
-      elf_hash_table (info)->bucketcount = bucketcount;
-
-      s = bfd_get_section_by_name (dynobj, ".dynstr");
-      BFD_ASSERT (s != NULL);
-
-      elf_finalize_dynstr (output_bfd, info);
-
-      s->_raw_size = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
-
-      for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
-       if (! elf_add_dynamic_entry (info, DT_NULL, 0))
-         return FALSE;
-    }
-
-  return TRUE;
-}
-\f
-/* This function is used to adjust offsets into .dynstr for
-   dynamic symbols.  This is called via elf_link_hash_traverse.  */
-
-static bfd_boolean
-elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
-{
-  struct elf_strtab_hash *dynstr = data;
-
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-  if (h->dynindx != -1)
-    h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index);
-  return TRUE;
-}
-
-/* Assign string offsets in .dynstr, update all structures referencing
-   them.  */
-
-static bfd_boolean
-elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
-{
-  struct elf_link_local_dynamic_entry *entry;
-  struct elf_strtab_hash *dynstr = elf_hash_table (info)->dynstr;
-  bfd *dynobj = elf_hash_table (info)->dynobj;
-  asection *sdyn;
-  bfd_size_type size;
-  Elf_External_Dyn *dyncon, *dynconend;
-
-  _bfd_elf_strtab_finalize (dynstr);
-  size = _bfd_elf_strtab_size (dynstr);
-
-  /* Update all .dynamic entries referencing .dynstr strings.  */
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
-  BFD_ASSERT (sdyn != NULL);
-
-  dyncon = (Elf_External_Dyn *) sdyn->contents;
-  dynconend = (Elf_External_Dyn *) (sdyn->contents +
-                                   sdyn->_raw_size);
-  for (; dyncon < dynconend; dyncon++)
-    {
-      Elf_Internal_Dyn dyn;
-
-      elf_swap_dyn_in (dynobj, dyncon, & dyn);
-      switch (dyn.d_tag)
-       {
-       case DT_STRSZ:
-         dyn.d_un.d_val = size;
-         elf_swap_dyn_out (dynobj, & dyn, dyncon);
-         break;
-       case DT_NEEDED:
-       case DT_SONAME:
-       case DT_RPATH:
-       case DT_RUNPATH:
-       case DT_FILTER:
-       case DT_AUXILIARY:
-         dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val);
-         elf_swap_dyn_out (dynobj, & dyn, dyncon);
-         break;
-       default:
-         break;
-       }
-    }
-
-  /* Now update local dynamic symbols.  */
-  for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
-    entry->isym.st_name = _bfd_elf_strtab_offset (dynstr,
-                                                 entry->isym.st_name);
-
-  /* And the rest of dynamic symbols.  */
-  elf_link_hash_traverse (elf_hash_table (info),
-                         elf_adjust_dynstr_offsets, dynstr);
-
-  /* Adjust version definitions.  */
-  if (elf_tdata (output_bfd)->cverdefs)
-    {
-      asection *s;
-      bfd_byte *p;
-      bfd_size_type i;
-      Elf_Internal_Verdef def;
-      Elf_Internal_Verdaux defaux;
-
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
-      p = (bfd_byte *) s->contents;
-      do
-       {
-         _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
-                                  &def);
-         p += sizeof (Elf_External_Verdef);
-         for (i = 0; i < def.vd_cnt; ++i)
-           {
-             _bfd_elf_swap_verdaux_in (output_bfd,
-                                       (Elf_External_Verdaux *) p, &defaux);
-             defaux.vda_name = _bfd_elf_strtab_offset (dynstr,
-                                                       defaux.vda_name);
-             _bfd_elf_swap_verdaux_out (output_bfd,
-                                        &defaux, (Elf_External_Verdaux *) p);
-             p += sizeof (Elf_External_Verdaux);
-           }
-       }
-      while (def.vd_next);
-    }
-
-  /* Adjust version references.  */
-  if (elf_tdata (output_bfd)->verref)
-    {
-      asection *s;
-      bfd_byte *p;
-      bfd_size_type i;
-      Elf_Internal_Verneed need;
-      Elf_Internal_Vernaux needaux;
-
-      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
-      p = (bfd_byte *) s->contents;
-      do
-       {
-         _bfd_elf_swap_verneed_in (output_bfd, (Elf_External_Verneed *) p,
-                                   &need);
-         need.vn_file = _bfd_elf_strtab_offset (dynstr, need.vn_file);
-         _bfd_elf_swap_verneed_out (output_bfd, &need,
-                                    (Elf_External_Verneed *) p);
-         p += sizeof (Elf_External_Verneed);
-         for (i = 0; i < need.vn_cnt; ++i)
-           {
-             _bfd_elf_swap_vernaux_in (output_bfd,
-                                       (Elf_External_Vernaux *) p, &needaux);
-             needaux.vna_name = _bfd_elf_strtab_offset (dynstr,
-                                                        needaux.vna_name);
-             _bfd_elf_swap_vernaux_out (output_bfd,
-                                        &needaux,
-                                        (Elf_External_Vernaux *) p);
-             p += sizeof (Elf_External_Vernaux);
-           }
-       }
-      while (need.vn_next);
-    }
-
-  return TRUE;
-}
 \f
 /* Final phase of ELF linker.  */
 
@@ -5800,51 +4629,6 @@ elf_gc_common_final_link (bfd *abfd, struct bfd_link_info *info)
   return elf_bfd_final_link (abfd, info);
 }
 
-/* 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;
-  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)
-    {
-      alc = bfd_malloc (p - name + 1);
-      memcpy (alc, name, p - name);
-      alc[p - name] = '\0';
-      name = alc;
-    }
-
-  /* Compute the hash value.  */
-  ha = bfd_elf_hash (name);
-
-  /* Store the found hash value in the array given as the argument.  */
-  *(*valuep)++ = ha;
-
-  /* And store it in the struct so that we can put it in the hash table
-     later.  */
-  h->elf_hash_value = ha;
-
-  if (alc != NULL)
-    free (alc);
-
-  return TRUE;
-}
-
 bfd_boolean
 elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
 {
index 47b4eae..27b5aa5 100644 (file)
@@ -3083,7 +3083,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
          /* The DT_DEBUG entry is filled in by the dynamic linker and used
             by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
index 76b3732..b82e109 100644 (file)
@@ -564,17 +564,8 @@ static bfd *reldyn_sorting_bfd;
    : bfd_put_32 (abfd, val, ptr))
 
 /* Add a dynamic symbol table-entry.  */
-#ifdef BFD64
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)     \
-  (ABI_64_P (elf_hash_table (info)->dynobj)            \
-   ? bfd_elf64_add_dynamic_entry (info, tag, val)      \
-   : bfd_elf32_add_dynamic_entry (info, tag, val))
-#else
 #define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val)     \
-  (ABI_64_P (elf_hash_table (info)->dynobj)            \
-   ? (abort (), FALSE)                                 \
-   : bfd_elf32_add_dynamic_entry (info, tag, val))
-#endif
+  _bfd_elf_add_dynamic_entry (info, tag, val)
 
 #define MIPS_ELF_RTYPE_TO_HOWTO(abfd, rtype, rela)                     \
   (get_elf_backend_data (abfd)->elf_backend_mips_rtype_to_howto (rtype, rela))
index f962891..51e5ebb 100644 (file)
@@ -1,3 +1,8 @@
+2004-03-25  Alan Modra  <amodra@bigpond.net.au>
+
+       * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Update
+       size_dynamic_sections call.
+
 2004-03-23  Alan Modra  <amodra@bigpond.net.au>
 
        PR 51.
index e95b3a9..a86434a 100644 (file)
@@ -871,7 +871,7 @@ gld${EMULATION_NAME}_before_allocation (void)
   rpath = command_line.rpath;
   if (rpath == NULL)
     rpath = (const char *) getenv ("LD_RUN_PATH");
-  if (! (bfd_elf${ELFSIZE}_size_dynamic_sections
+  if (! (bfd_elf_size_dynamic_sections
         (output_bfd, command_line.soname, rpath,
          command_line.filter_shlib,
          (const char * const *) command_line.auxiliary_filters,