move elflink.h code to elflink.c

Alan Modra amodra@bigpond.net.au
Thu Mar 25 14:30:00 GMT 2004


This moves 1200 lines of code from elflink.h (where it is compiled
twice if configuring both 32 and 64 bit targets) to elflink.c (where it
is only compiled once).  I've also fixed a couple of minor bugs, one in
elf_link_add_object_symbols, the other in bfd_elf_size_dynamic_sections.

elflink.h is now smaller than it was in binutils-2.8.  With a bit more
work, it can hopefully disappear altogether.

bfd/ChangeLog
	* 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.

	* bfd-in.h (bfd_elf32_size_dynamic_sections): Delete.
	(bfd_elf64_size_dynamic_sections): Delete.
	(bfd_elf_size_dynamic_sections): Declare.
	* bfd-in2.h: Regenerate.
	* 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/ChangeLog
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Update
	size_dynamic_sections call.


Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.75
diff -u -p -r1.75 bfd-in.h
--- bfd/bfd-in.h	18 Mar 2004 12:50:19 -0000	1.75
+++ bfd/bfd-in.h	25 Mar 2004 10:45:39 -0000
@@ -611,10 +611,7 @@ extern struct bfd_link_needed_list *bfd_
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf_get_bfd_needed_list
   (bfd *, struct bfd_link_needed_list **);
-extern bfd_boolean bfd_elf32_size_dynamic_sections
-  (bfd *, const char *, const char *, const char *, const char * const *,
-   struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
-extern bfd_boolean bfd_elf64_size_dynamic_sections
+extern bfd_boolean bfd_elf_size_dynamic_sections
   (bfd *, const char *, const char *, const char *, const char * const *,
    struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
 extern void bfd_elf_set_dt_needed_name
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.262
diff -u -p -r1.262 bfd-in2.h
--- bfd/bfd-in2.h	18 Mar 2004 12:50:19 -0000	1.262
+++ bfd/bfd-in2.h	25 Mar 2004 10:45:42 -0000
@@ -618,10 +618,7 @@ extern struct bfd_link_needed_list *bfd_
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean bfd_elf_get_bfd_needed_list
   (bfd *, struct bfd_link_needed_list **);
-extern bfd_boolean bfd_elf32_size_dynamic_sections
-  (bfd *, const char *, const char *, const char *, const char * const *,
-   struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
-extern bfd_boolean bfd_elf64_size_dynamic_sections
+extern bfd_boolean bfd_elf_size_dynamic_sections
   (bfd *, const char *, const char *, const char *, const char * const *,
    struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
 extern void bfd_elf_set_dt_needed_name
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.131
diff -u -p -r1.131 elf-bfd.h
--- bfd/elf-bfd.h	22 Mar 2004 02:28:12 -0000	1.131
+++ bfd/elf-bfd.h	25 Mar 2004 10:45:46 -0000
@@ -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
 	;								\
       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: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.50
diff -u -p -r1.50 elfcode.h
--- bfd/elfcode.h	16 Oct 2003 04:11:06 -0000	1.50
+++ bfd/elfcode.h	25 Mar 2004 10:46:32 -0000
@@ -116,7 +116,6 @@ Foundation, Inc., 59 Temple Place - Suit
 #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: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.59
diff -u -p -r1.59 elflink.c
--- bfd/elflink.c	19 Mar 2004 01:36:45 -0000	1.59
+++ bfd/elflink.c	25 Mar 2004 10:46:35 -0000
@@ -2585,6 +2585,262 @@ elf_link_is_defined_archive_symbol (bfd 
   return result;
 }
 
+/* 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;
+}
+
+/* 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;
+}
+
 /* 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
@@ -2808,4 +3064,976 @@ _bfd_elf_link_add_archive_symbols (bfd *
   if (included != NULL)
     free (included);
   return FALSE;
+}
+
+/* This function will be called though elf_link_hash_traverse to store
+   all hash value of the exported symbols in an array.  */
+
+static bfd_boolean
+elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
+{
+  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: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.257
diff -u -p -r1.257 elflink.h
--- bfd/elflink.h	19 Mar 2004 01:36:45 -0000	1.257
+++ bfd/elflink.h	25 Mar 2004 10:46:37 -0000
@@ -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, str
       return FALSE;
     }
 }
-
-/* 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, 
 	 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, 
 	      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, 
 
       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, 
  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;
-}
-
-/* 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;
-}
-
-/* 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;
-}
 
 /* Final phase of ELF linker.  */
 
@@ -5798,51 +4627,6 @@ elf_gc_common_final_link (bfd *abfd, str
 
   /* Invoke the regular ELF backend linker to do all the work.  */
   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
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.47
diff -u -p -r1.47 elf-m10300.c
--- bfd/elf-m10300.c	22 Mar 2004 02:28:15 -0000	1.47
+++ bfd/elf-m10300.c	25 Mar 2004 10:45:46 -0000
@@ -4491,31 +4491,31 @@ _bfd_mn10300_elf_size_dynamic_sections (
 	 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: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.123
diff -u -p -r1.123 elf32-arm.h
--- bfd/elf32-arm.h	23 Mar 2004 23:05:50 -0000	1.123
+++ bfd/elf32-arm.h	25 Mar 2004 10:45:48 -0000
@@ -3665,7 +3665,7 @@ elf32_arm_size_dynamic_sections (output_
 	 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: bfd/elf32-cris.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-cris.c,v
retrieving revision 1.49
diff -u -p -r1.49 elf32-cris.c
--- bfd/elf32-cris.c	22 Mar 2004 04:08:39 -0000	1.49
+++ bfd/elf32-cris.c	25 Mar 2004 10:45:49 -0000
@@ -2809,7 +2809,7 @@ elf_cris_size_dynamic_sections (output_b
 	 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: bfd/elf32-frv.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-frv.c,v
retrieving revision 1.18
diff -u -p -r1.18 elf32-frv.c
--- bfd/elf32-frv.c	20 Mar 2004 23:16:39 -0000	1.18
+++ bfd/elf32-frv.c	25 Mar 2004 10:45:52 -0000
@@ -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 *ou
   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: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.114
diff -u -p -r1.114 elf32-hppa.c
--- bfd/elf32-hppa.c	22 Mar 2004 02:28:15 -0000	1.114
+++ bfd/elf32-hppa.c	25 Mar 2004 10:45:54 -0000
@@ -2241,7 +2241,7 @@ elf32_hppa_size_dynamic_sections (bfd *o
 	 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: bfd/elf32-i370.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i370.c,v
retrieving revision 1.33
diff -u -p -r1.33 elf32-i370.c
--- bfd/elf32-i370.c	20 Mar 2004 23:16:39 -0000	1.33
+++ bfd/elf32-i370.c	25 Mar 2004 10:45:55 -0000
@@ -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_b
 	 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: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.118
diff -u -p -r1.118 elf32-i386.c
--- bfd/elf32-i386.c	22 Mar 2004 02:28:16 -0000	1.118
+++ bfd/elf32-i386.c	25 Mar 2004 10:45:57 -0000
@@ -1895,7 +1895,7 @@ elf_i386_size_dynamic_sections (bfd *out
 	 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: bfd/elf32-m32r.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m32r.c,v
retrieving revision 1.41
diff -u -p -r1.41 elf32-m32r.c
--- bfd/elf32-m32r.c	20 Mar 2004 23:16:39 -0000	1.41
+++ bfd/elf32-m32r.c	25 Mar 2004 10:46:00 -0000
@@ -2442,7 +2442,7 @@ printf("m32r_elf_size_dynamic_sections()
 	 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: bfd/elf32-m68k.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-m68k.c,v
retrieving revision 1.62
diff -u -p -r1.62 elf32-m68k.c
--- bfd/elf32-m68k.c	22 Mar 2004 02:28:16 -0000	1.62
+++ bfd/elf32-m68k.c	25 Mar 2004 10:46:01 -0000
@@ -1247,7 +1247,7 @@ elf_m68k_size_dynamic_sections (output_b
 	 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: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.114
diff -u -p -r1.114 elf32-ppc.c
--- bfd/elf32-ppc.c	22 Mar 2004 02:28:16 -0000	1.114
+++ bfd/elf32-ppc.c	25 Mar 2004 10:46:04 -0000
@@ -3470,7 +3470,7 @@ ppc_elf_size_dynamic_sections (bfd *outp
 	 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: bfd/elf32-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-s390.c,v
retrieving revision 1.58
diff -u -p -r1.58 elf32-s390.c
--- bfd/elf32-s390.c	22 Mar 2004 02:28:16 -0000	1.58
+++ bfd/elf32-s390.c	25 Mar 2004 10:46:05 -0000
@@ -2157,7 +2157,7 @@ elf_s390_size_dynamic_sections (output_b
 	 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: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.102
diff -u -p -r1.102 elf32-sh.c
--- bfd/elf32-sh.c	20 Mar 2004 23:16:41 -0000	1.102
+++ bfd/elf32-sh.c	25 Mar 2004 10:46:09 -0000
@@ -4620,7 +4620,7 @@ sh_elf_size_dynamic_sections (bfd *outpu
 	 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: bfd/elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.63
diff -u -p -r1.63 elf32-sparc.c
--- bfd/elf32-sparc.c	22 Mar 2004 02:28:16 -0000	1.63
+++ bfd/elf32-sparc.c	25 Mar 2004 10:46:10 -0000
@@ -2027,7 +2027,7 @@ elf32_sparc_size_dynamic_sections (outpu
 	 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: bfd/elf32-vax.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-vax.c,v
retrieving revision 1.19
diff -u -p -r1.19 elf32-vax.c
--- bfd/elf32-vax.c	22 Mar 2004 02:28:17 -0000	1.19
+++ bfd/elf32-vax.c	25 Mar 2004 10:46:12 -0000
@@ -1297,7 +1297,7 @@ elf_vax_size_dynamic_sections (output_bf
 	 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: bfd/elf32-xtensa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xtensa.c,v
retrieving revision 1.22
diff -u -p -r1.22 elf32-xtensa.c
--- bfd/elf32-xtensa.c	23 Mar 2004 01:36:59 -0000	1.22
+++ bfd/elf32-xtensa.c	25 Mar 2004 10:46:15 -0000
@@ -1334,7 +1334,7 @@ elf_xtensa_size_dynamic_sections (output
 	 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: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.114
diff -u -p -r1.114 elf64-alpha.c
--- bfd/elf64-alpha.c	22 Mar 2004 02:28:17 -0000	1.114
+++ bfd/elf64-alpha.c	25 Mar 2004 10:46:18 -0000
@@ -4094,7 +4094,7 @@ elf64_alpha_size_dynamic_sections (outpu
 	 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: bfd/elf64-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-hppa.c,v
retrieving revision 1.46
diff -u -p -r1.46 elf64-hppa.c
--- bfd/elf64-hppa.c	15 Mar 2004 17:53:45 -0000	1.46
+++ bfd/elf64-hppa.c	25 Mar 2004 10:46:19 -0000
@@ -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
 	 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: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.144
diff -u -p -r1.144 elf64-ppc.c
--- bfd/elf64-ppc.c	22 Mar 2004 02:28:17 -0000	1.144
+++ bfd/elf64-ppc.c	25 Mar 2004 10:46:24 -0000
@@ -6065,7 +6065,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
 	 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: bfd/elf64-s390.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-s390.c,v
retrieving revision 1.58
diff -u -p -r1.58 elf64-s390.c
--- bfd/elf64-s390.c	22 Mar 2004 02:28:17 -0000	1.58
+++ bfd/elf64-s390.c	25 Mar 2004 10:46:25 -0000
@@ -2127,7 +2127,7 @@ elf_s390_size_dynamic_sections (output_b
 	 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: bfd/elf64-sh64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sh64.c,v
retrieving revision 1.43
diff -u -p -r1.43 elf64-sh64.c
--- bfd/elf64-sh64.c	20 Mar 2004 23:16:42 -0000	1.43
+++ bfd/elf64-sh64.c	25 Mar 2004 10:46:27 -0000
@@ -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 *o
 	 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: bfd/elf64-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sparc.c,v
retrieving revision 1.83
diff -u -p -r1.83 elf64-sparc.c
--- bfd/elf64-sparc.c	22 Mar 2004 02:28:17 -0000	1.83
+++ bfd/elf64-sparc.c	25 Mar 2004 10:46:30 -0000
@@ -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 (outpu
 	 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: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.73
diff -u -p -r1.73 elf64-x86-64.c
--- bfd/elf64-x86-64.c	22 Mar 2004 02:28:17 -0000	1.73
+++ bfd/elf64-x86-64.c	25 Mar 2004 10:46:31 -0000
@@ -1683,7 +1683,7 @@ elf64_x86_64_size_dynamic_sections (bfd 
 	 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: bfd/elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.121
diff -u -p -r1.121 elfxx-ia64.c
--- bfd/elfxx-ia64.c	22 Mar 2004 02:28:17 -0000	1.121
+++ bfd/elfxx-ia64.c	25 Mar 2004 10:46:43 -0000
@@ -3083,7 +3083,7 @@ elfNN_ia64_size_dynamic_sections (output
 	  /* 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: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.93
diff -u -p -r1.93 elfxx-mips.c
--- bfd/elfxx-mips.c	20 Mar 2004 23:16:42 -0000	1.93
+++ bfd/elfxx-mips.c	25 Mar 2004 10:46:46 -0000
@@ -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: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.109
diff -u -p -r1.109 elf32.em
--- ld/emultempl/elf32.em	18 Mar 2004 12:50:20 -0000	1.109
+++ ld/emultempl/elf32.em	25 Mar 2004 10:47:04 -0000
@@ -871,7 +871,7 @@ gld${EMULATION_NAME}_before_allocation (
   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,

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list