This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Move section_already_linked from ld to bfd target vector


On Mon, Jun 28, 2004 at 06:22:42PM -0700, H. J. Lu wrote:
> section_already_linked in ldlang.c has some code to deal with PE's
> comdat, which isn't use by any other targets. Also there is
> bfd_comdat_info in bfd_section for it. I suggest we move
> bfd_comdat_info to PE target and move section_already_linked into
> bfd target vector. We can have a special section_already_linked
> function for PE and a generic one for others. With those changes, we
> can remove PE specifc code from linker as well as bfd_section. Any
> comments?
> 
> 
> 

Here is the proposed patch. It moves bfd_comdat_info from bfd_section
to coff_section_data.


H.J.
---
--- binutils/bfd/aout-adobe.c.comdat	2004-06-28 19:01:58.559534610 -0700
+++ binutils/bfd/aout-adobe.c	2004-06-28 21:29:04.060031807 -0700
@@ -518,6 +518,8 @@ aout_adobe_sizeof_headers (ignore_abfd, 
 #define aout_32_bfd_merge_sections	bfd_generic_merge_sections
 #define aout_32_bfd_is_group_section	bfd_generic_is_group_section
 #define aout_32_bfd_discard_group	bfd_generic_discard_group
+#define aout_32_section_already_linked \
+  _bfd_generic_section_already_linked
 #define aout_32_bfd_link_hash_table_create \
   _bfd_generic_link_hash_table_create
 #define aout_32_bfd_link_hash_table_free \
--- binutils/bfd/aout-target.h.comdat	2004-06-28 19:01:58.565533835 -0700
+++ binutils/bfd/aout-target.h	2004-06-28 21:29:04.061031677 -0700
@@ -519,6 +519,10 @@ MY_bfd_final_link (abfd, info)
 #ifndef MY_bfd_discard_group
 #define MY_bfd_discard_group bfd_generic_discard_group
 #endif
+#ifndef MY_section_already_linked
+#define MY_section_already_linked \
+  _bfd_generic_section_already_linked
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
 #endif
--- binutils/bfd/aout-tic30.c.comdat	2004-06-28 19:01:58.602529050 -0700
+++ binutils/bfd/aout-tic30.c	2004-06-28 21:29:04.063031418 -0700
@@ -978,6 +978,10 @@ tic30_aout_set_arch_mach (abfd, arch, ma
 #ifndef MY_bfd_discard_group
 #define MY_bfd_discard_group bfd_generic_discard_group
 #endif
+#ifndef MY_section_already_linked
+#define MY_section_already_linked \
+  _bfd_generic_section_already_linked
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
 #endif
--- binutils/bfd/bfd-in.h.comdat	2004-06-29 00:37:18.181810072 -0700
+++ binutils/bfd/bfd-in.h	2004-06-29 00:46:31.252197963 -0700
@@ -555,6 +555,9 @@ void bfd_putl16 (bfd_vma, void *);
 
 bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
 void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
 
 /* Externally visible ECOFF routines.  */
 
@@ -839,3 +842,21 @@ extern void bfd_elf32_ia64_after_parse
 extern void bfd_elf64_ia64_after_parse
   (int);
 
+/* This structure is used for a comdat section, as in PE.  A comdat
+   section is associated with a particular symbol.  When the linker
+   sees a comdat section, it keeps only one of the sections with a
+   given name and associated with a given symbol.  */
+
+struct coff_comdat_info
+{
+  /* The name of the symbol associated with a comdat section.  */
+  const char *name;
+
+  /* The local symbol table index of the symbol associated with a
+     comdat section.  This is only meaningful to the object file format
+     specific code; it is not an index into the list returned by
+     bfd_canonicalize_symtab.  */
+  long symbol;
+};
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+  (bfd *, struct bfd_section *);
--- binutils/bfd/binary.c.comdat	2004-06-28 19:01:59.103464268 -0700
+++ binutils/bfd/binary.c	2004-06-28 21:29:04.065031160 -0700
@@ -341,6 +341,8 @@ binary_sizeof_headers (abfd, exec)
 #define binary_bfd_merge_sections bfd_generic_merge_sections
 #define binary_bfd_is_group_section bfd_generic_is_group_section
 #define binary_bfd_discard_group bfd_generic_discard_group
+#define binary_section_already_linked \
+  _bfd_generic_section_already_linked
 #define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define binary_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define binary_bfd_link_just_syms _bfd_generic_link_just_syms
--- binutils/bfd/bout.c.comdat	2004-06-28 19:01:59.176454829 -0700
+++ binutils/bfd/bout.c	2004-06-28 21:29:04.066031030 -0700
@@ -1487,6 +1487,8 @@ b_out_bfd_get_relocated_section_contents
 #define b_out_bfd_merge_sections  bfd_generic_merge_sections
 #define b_out_bfd_is_group_section bfd_generic_is_group_section
 #define b_out_bfd_discard_group bfd_generic_discard_group
+#define b_out_section_already_linked \
+  _bfd_generic_section_already_linked
 
 #define aout_32_get_section_contents_in_window \
   _bfd_generic_get_section_contents_in_window
--- binutils/bfd/coff-alpha.c.comdat	2004-06-28 19:01:59.302438536 -0700
+++ binutils/bfd/coff-alpha.c	2004-06-28 21:29:04.069030642 -0700
@@ -2356,6 +2356,8 @@ static const struct ecoff_backend_data a
 #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_ecoff_section_already_linked \
+  _bfd_generic_section_already_linked
 
 const bfd_target ecoffalpha_little_vec =
 {
--- binutils/bfd/coff-mips.c.comdat	2004-06-28 19:01:59.536408279 -0700
+++ binutils/bfd/coff-mips.c	2004-06-28 21:29:04.071030383 -0700
@@ -1399,6 +1399,8 @@ static const struct ecoff_backend_data m
 
 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_ecoff_section_already_linked \
+  _bfd_generic_section_already_linked
 
 extern const bfd_target ecoff_big_vec;
 
--- binutils/bfd/coff-rs6000.c.comdat	2004-06-28 19:01:59.778376987 -0700
+++ binutils/bfd/coff-rs6000.c	2004-06-28 21:29:04.075029865 -0700
@@ -4198,6 +4198,7 @@ const bfd_target rs6000coff_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -4443,6 +4444,7 @@ const bfd_target pmac_xcoff_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
--- binutils/bfd/coff64-rs6000.c.comdat	2004-06-28 19:02:00.076338454 -0700
+++ binutils/bfd/coff64-rs6000.c	2004-06-28 21:29:04.078029477 -0700
@@ -2739,6 +2739,7 @@ const bfd_target rs6000coff64_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -2985,6 +2986,7 @@ const bfd_target aix5coff64_vec =
     bfd_generic_merge_sections,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
+    _bfd_generic_section_already_linked,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
--- binutils/bfd/coffcode.h.comdat	2004-06-28 19:02:00.352302766 -0700
+++ binutils/bfd/coffcode.h	2004-06-28 23:56:17.682255473 -0700
@@ -965,12 +965,13 @@ handle_COMDAT (abfd, sec_flags, hdr, nam
 		   Intel puts the two adjacent, but Alpha (at
 		   least) spreads them out.  */
 
-		amt = sizeof (struct bfd_comdat_info);
-		section->comdat = bfd_alloc (abfd, amt);
-		if (section->comdat == NULL)
+		amt = sizeof (struct coff_comdat_info);
+		coff_section_data (abfd, section)->comdat
+		  = bfd_alloc (abfd, amt);
+		if (coff_section_data (abfd, section)->comdat == NULL)
 		  abort ();
 
-		section->comdat->symbol =
+		coff_section_data (abfd, section)->comdat->symbol =
 		  (esym - esymstart) / bfd_coff_symesz (abfd);
 
 		amt = strlen (symname) + 1;
@@ -979,7 +980,8 @@ handle_COMDAT (abfd, sec_flags, hdr, nam
 		  abort ();
 
 		strcpy (newname, symname);
-		section->comdat->name = newname;
+		coff_section_data (abfd, section)->comdat->name
+		  = newname;
 	      }
 
 	      goto breakloop;
@@ -5586,6 +5588,10 @@ static const bfd_coff_backend_data ticof
 #define coff_bfd_discard_group		    bfd_generic_discard_group
 #endif
 
+#ifndef coff_section_already_linked
+#define coff_section_already_linked	    _bfd_coff_section_already_linked
+#endif
+
 #define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE, SWAP_TABLE)	\
 const bfd_target VAR =							\
 {									\
--- binutils/bfd/coffgen.c.comdat	2004-06-28 19:02:00.451289964 -0700
+++ binutils/bfd/coffgen.c	2004-06-29 00:44:53.067909497 -0700
@@ -2496,3 +2496,13 @@ bfd_coff_set_symbol_class (abfd, symbol,
 
   return TRUE;
 }
+
+struct coff_comdat_info *
+bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec)
+{
+  if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+    return coff_section_data (abfd, sec)->comdat;
+  else
+    return NULL;
+}
+
--- binutils/bfd/cofflink.c.comdat	2004-06-28 19:02:00.607269793 -0700
+++ binutils/bfd/cofflink.c	2004-06-29 00:25:46.558289146 -0700
@@ -435,18 +435,18 @@ coff_link_add_symbols (bfd *abfd,
 	  if (obj_pe (abfd)
 	      && (classification == COFF_SYMBOL_GLOBAL
 		  || classification == COFF_SYMBOL_PE_SECTION)
-	      && section->comdat != NULL
+	      && coff_section_data (abfd, section)->comdat != NULL
 	      && strncmp (name, "??_", 3) == 0
-	      && strcmp (name, section->comdat->name) == 0)
+	      && strcmp (name, coff_section_data (abfd, section)->comdat->name) == 0)
 	    {
 	      if (*sym_hash == NULL)
 		*sym_hash = coff_link_hash_lookup (coff_hash_table (info),
 						   name, FALSE, copy, FALSE);
 	      if (*sym_hash != NULL
 		  && (*sym_hash)->root.type == bfd_link_hash_defined
-		  && (*sym_hash)->root.u.def.section->comdat != NULL
-		  && strcmp ((*sym_hash)->root.u.def.section->comdat->name,
-			     section->comdat->name) == 0)
+		  && coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat != NULL
+		  && strcmp (coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat->name,
+			     coff_section_data (abfd, section)->comdat->name) == 0)
 		addit = FALSE;
 	    }
 
@@ -3012,3 +3012,113 @@ _bfd_coff_generic_relocate_section (bfd 
     }
   return TRUE;
 }
+
+/* Sections marked with the SEC_LINK_ONCE flag should only be linked
+   once into the output.  This routine checks each section, and
+   arrange to discard it if a section of the same name has already
+   been linked.  This code assumes that all relevant sections have the 
+   SEC_LINK_ONCE flag set; that is, it does not depend solely upon the
+   section name.  bfd_section_already_linked is called via
+   bfd_map_over_sections.  */
+
+void
+_bfd_coff_section_already_linked (bfd *abfd, asection *sec)
+{
+  flagword flags;
+  const char *name;
+  struct bfd_section_already_linked *l;
+  struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+  flags = sec->flags;
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return;
+
+  /* FIXME: When doing a relocatable link, we may have trouble
+     copying relocations in other sections that refer to local symbols
+     in the section being discarded.  Those relocations will have to
+     be converted somehow; as of this writing I'm not sure that any of
+     the backends handle that correctly.
+
+     It is tempting to instead not discard link once sections when
+     doing a relocatable link (technically, they should be discarded
+     whenever we are building constructors).  However, that fails,
+     because the linker winds up combining all the link once sections
+     into a single large link once section, which defeats the purpose
+     of having link once sections in the first place.
+
+     Also, not merging link once sections in a relocatable link
+     causes trouble for MIPS ELF, which relies on link once semantics
+     to handle the .reginfo section correctly.  */
+
+  name = bfd_get_section_name (abfd, sec);
+
+  already_linked_list =
+    ((struct bfd_section_already_linked_hash_entry *)
+     bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+		      TRUE, FALSE));
+
+  for (l = already_linked_list->entry; l != NULL; l = l->next)
+    {
+      if (coff_section_data (abfd, sec)->comdat == NULL
+	  || coff_section_data (abfd, l->sec)->comdat == NULL
+	  || strcmp (coff_section_data (abfd, sec)->comdat->name,
+		     coff_section_data (abfd, l->sec)->comdat->name) == 0)
+	{
+	  /* The section has already been linked.  See if we should
+             issue a warning.  */
+	  switch (flags & SEC_LINK_DUPLICATES)
+	    {
+	    default:
+	      abort ();
+
+	    case SEC_LINK_DUPLICATES_DISCARD:
+	      break;
+
+	    case SEC_LINK_DUPLICATES_ONE_ONLY:
+	      if (coff_section_data (abfd, sec)->comdat == NULL)
+		(*_bfd_error_handler)
+		  (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
+		   bfd_archive_filename (abfd), name);
+	      else
+		(*_bfd_error_handler)
+		  (_("%s: %s: warning: ignoring duplicate `%s' section symbol `%s'\n"),
+		   bfd_archive_filename (abfd), name,
+		   coff_section_data (abfd, sec)->comdat->name);
+	      break;
+
+	    case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+	      /* FIXME: We should really dig out the contents of both
+                 sections and memcmp them.  The COFF/PE spec says that
+                 the Microsoft linker does not implement this
+                 correctly, so I'm not going to bother doing it
+                 either.  */
+	      /* Fall through.  */
+	    case SEC_LINK_DUPLICATES_SAME_SIZE:
+	      if (sec->size != l->sec->size)
+		(*_bfd_error_handler)
+		  (_("%s: %s: warning: duplicate section `%s' has different size\n"),
+		   bfd_archive_filename (abfd), name);
+	      break;
+	    }
+
+	  /* Set the output_section field so that lang_add_section
+	     does not create a lang_input_section structure for this
+	     section.  Since there might be a symbol in the section
+	     being discarded, we must retain a pointer to the section
+	     which we are really going to use.  */
+	  sec->output_section = bfd_abs_section_ptr;
+	  sec->kept_section = l->sec;
+
+	  return;
+	}
+    }
+
+  /* This is the first section with this name.  Record it.  Allocate
+     the memory from the same obstack as the hash table is kept in.  */
+
+  l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+
+  l->sec = sec;
+  l->next = already_linked_list->entry;
+  already_linked_list->entry = l;
+}
--- binutils/bfd/ecoff.c.comdat	2004-06-28 19:02:01.299180313 -0700
+++ binutils/bfd/ecoff.c	2004-06-28 23:20:52.872038271 -0700
@@ -92,8 +92,8 @@ static asection bfd_debug_section =
      NULL,       NULL,        0,           0,       0,
   /* line_filepos, userdata, contents, lineno, lineno_count,       */
      0,            NULL,     NULL,     NULL,   0,
-  /* entsize, comdat, kept_section, moving_line_filepos,           */
-     0,       NULL,   NULL,         0,
+  /* entsize, kept_section, moving_line_filepos,	           */
+     0,       NULL,         0,
   /* target_index, used_by_bfd, constructor_chain, owner,          */
      0,            NULL,        NULL,              NULL,
   /* symbol,                                                       */
--- binutils/bfd/elf-bfd.h.comdat	2004-06-28 19:02:01.401167124 -0700
+++ binutils/bfd/elf-bfd.h	2004-06-29 00:23:03.578359823 -0700
@@ -1380,6 +1380,8 @@ extern bfd_boolean bfd_elf_is_group_sect
   (bfd *, const struct bfd_section *);
 extern bfd_boolean bfd_elf_discard_group
   (bfd *, struct bfd_section *);
+extern void _bfd_elf_section_already_linked
+  (bfd *, struct bfd_section *);
 extern void bfd_elf_set_group_contents
   (bfd *, asection *, void *);
 extern void _bfd_elf_link_just_syms
--- binutils/bfd/elflink.c.comdat	2004-06-28 19:02:08.554242073 -0700
+++ binutils/bfd/elflink.c	2004-06-29 00:28:17.717737947 -0700
@@ -8974,3 +8974,9 @@ bfd_elf_discard_info (bfd *output_bfd, s
 
   return ret;
 }
+
+void
+_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
+{
+  return _bfd_generic_section_already_linked (abfd, sec);
+}
--- binutils/bfd/elfxx-target.h.comdat	2004-06-21 14:05:28.000000000 -0700
+++ binutils/bfd/elfxx-target.h	2004-06-29 00:23:41.967398128 -0700
@@ -144,6 +144,11 @@
 #define bfd_elfNN_bfd_discard_group bfd_elf_discard_group
 #endif
 
+#ifndef bfd_elfNN_section_already_linked
+#define bfd_elfNN_section_already_linked \
+  _bfd_elf_section_already_linked
+#endif
+
 #ifndef bfd_elfNN_bfd_make_debug_symbol
 #define bfd_elfNN_bfd_make_debug_symbol \
   ((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
--- binutils/bfd/i386msdos.c.comdat	2004-06-28 19:02:09.441127379 -0700
+++ binutils/bfd/i386msdos.c	2004-06-28 21:29:04.087028312 -0700
@@ -177,6 +177,8 @@ msdos_set_section_contents (abfd, sectio
 #define msdos_bfd_merge_sections bfd_generic_merge_sections
 #define msdos_bfd_is_group_section bfd_generic_is_group_section
 #define msdos_bfd_discard_group bfd_generic_discard_group
+#define msdos_section_already_linked \
+  _bfd_generic_section_already_linked
 #define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define msdos_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/i386os9k.c.comdat	2004-06-28 19:02:09.444126992 -0700
+++ binutils/bfd/i386os9k.c	2004-06-28 21:29:04.087028312 -0700
@@ -335,6 +335,8 @@ os9k_sizeof_headers (ignore_abfd, ignore
 #define os9k_bfd_merge_sections bfd_generic_merge_sections
 #define os9k_bfd_is_group_section bfd_generic_is_group_section
 #define os9k_bfd_discard_group bfd_generic_discard_group
+#define os9k_section_already_linked \
+  _bfd_generic_section_already_linked
 #define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define os9k_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/ieee.c.comdat	2004-06-28 19:02:09.620104234 -0700
+++ binutils/bfd/ieee.c	2004-06-28 21:29:04.089028053 -0700
@@ -4039,6 +4039,8 @@ ieee_bfd_debug_info_accumulate (abfd, se
 #define ieee_bfd_merge_sections bfd_generic_merge_sections
 #define ieee_bfd_is_group_section bfd_generic_is_group_section
 #define ieee_bfd_discard_group bfd_generic_discard_group
+#define ieee_section_already_linked \
+  _bfd_generic_section_already_linked
 #define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ieee_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/ihex.c.comdat	2004-06-28 19:02:09.712092338 -0700
+++ binutils/bfd/ihex.c	2004-06-28 21:29:04.091027794 -0700
@@ -990,6 +990,8 @@ ihex_sizeof_headers (abfd, exec)
 #define ihex_bfd_merge_sections bfd_generic_merge_sections
 #define ihex_bfd_is_group_section bfd_generic_is_group_section
 #define ihex_bfd_discard_group bfd_generic_discard_group
+#define ihex_section_already_linked \
+  _bfd_generic_section_already_linked
 #define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ihex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/libbfd-in.h.comdat	2004-06-28 19:02:09.915066089 -0700
+++ binutils/bfd/libbfd-in.h	2004-06-28 23:59:37.473336135 -0700
@@ -375,6 +375,8 @@ extern bfd_boolean _bfd_generic_set_sect
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) bfd_false)
 #define _bfd_nolink_bfd_link_split_section \
   ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
+#define _bfd_nolink_section_already_linked \
+  ((void (*) (bfd *, struct bfd_section *)) bfd_void)
 
 /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not
    have dynamic symbols or relocs.  Use BFD_JUMP_TABLE_DYNAMIC
@@ -474,6 +476,9 @@ extern bfd_boolean _bfd_generic_final_li
 extern bfd_boolean _bfd_generic_link_split_section
   (bfd *, struct bfd_section *);
 
+extern void _bfd_generic_section_already_linked
+  (bfd *, struct bfd_section *);
+
 /* Generic reloc_link_order processing routine.  */
 extern bfd_boolean _bfd_generic_reloc_link_order
   (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
@@ -653,3 +658,23 @@ extern bfd_boolean _bfd_sh_align_load_sp
    bfd_boolean (*) (bfd *, asection *, void *, bfd_byte *, bfd_vma),
    void *, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *);
 #endif
+
+/* This is the shape of the elements inside the already_linked hash
+   table. It maps a name onto a list of already_linked elements with
+   the same name.  */
+
+struct bfd_section_already_linked_hash_entry
+{
+  struct bfd_hash_entry root;
+  struct bfd_section_already_linked *entry;
+};
+
+struct bfd_section_already_linked
+{
+  struct bfd_section_already_linked *next;
+  asection *sec;
+};
+
+/* The hash table.  */
+
+extern struct bfd_hash_table _bfd_section_already_linked_table;
--- binutils/bfd/libcoff-in.h.comdat	2004-06-28 19:02:10.235024711 -0700
+++ binutils/bfd/libcoff-in.h	2004-06-29 00:45:21.062285126 -0700
@@ -194,6 +194,8 @@ struct coff_section_tdata
   bfd_vma offset;
   unsigned int i;
   const char *function;
+  /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+  struct coff_comdat_info *comdat;
   int line_base;
   /* A pointer used for .stab linking optimizations.  */
   PTR stab_info;
@@ -357,6 +359,8 @@ extern bfd_vma bfd_coff_reloc16_get_valu
    PARAMS ((arelent *, struct bfd_link_info *, asection *));
 extern void bfd_perform_slip
   PARAMS ((bfd *, unsigned int, asection *, bfd_vma));
+extern void _bfd_coff_section_already_linked
+  (bfd *, asection *);
 
 /* Functions and types in cofflink.c.  */
 
--- binutils/bfd/linker.c.comdat	2004-06-28 19:02:10.388004927 -0700
+++ binutils/bfd/linker.c	2004-06-29 00:24:46.728026442 -0700
@@ -2825,3 +2825,147 @@ _bfd_generic_link_split_section (bfd *ab
 {
   return FALSE;
 }
+
+/*
+FUNCTION
+	bfd_section_already_linked
+
+SYNOPSIS
+        void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+DESCRIPTION
+	Check if @var{sec} has been already linked during a reloceatable
+	or final link.
+
+.#define bfd_section_already_linked(abfd, sec) \
+.       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.
+
+*/
+
+/* Sections marked with the SEC_LINK_ONCE flag should only be linked
+   once into the output.  This routine checks each section, and
+   arrange to discard it if a section of the same name has already
+   been linked.  This code assumes that all relevant sections have the 
+   SEC_LINK_ONCE flag set; that is, it does not depend solely upon the
+   section name.  bfd_section_already_linked is called via
+   bfd_map_over_sections.  */
+
+struct bfd_hash_table _bfd_section_already_linked_table;
+
+void
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+{
+  flagword flags;
+  const char *name;
+  struct bfd_section_already_linked *l;
+  struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+  flags = sec->flags;
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return;
+
+  /* FIXME: When doing a relocatable link, we may have trouble
+     copying relocations in other sections that refer to local symbols
+     in the section being discarded.  Those relocations will have to
+     be converted somehow; as of this writing I'm not sure that any of
+     the backends handle that correctly.
+
+     It is tempting to instead not discard link once sections when
+     doing a relocatable link (technically, they should be discarded
+     whenever we are building constructors).  However, that fails,
+     because the linker winds up combining all the link once sections
+     into a single large link once section, which defeats the purpose
+     of having link once sections in the first place.
+
+     Also, not merging link once sections in a relocatable link
+     causes trouble for MIPS ELF, which relies on link once semantics
+     to handle the .reginfo section correctly.  */
+
+  name = bfd_get_section_name (abfd, sec);
+
+  already_linked_list =
+    ((struct bfd_section_already_linked_hash_entry *)
+     bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+		      TRUE, FALSE));
+
+  l = already_linked_list->entry;
+  if (l)
+    {
+      /* The section has already been linked.  See if we should issue
+	 a warning.  */
+      switch (flags & SEC_LINK_DUPLICATES)
+	{
+	default:
+	  abort ();
+	
+	case SEC_LINK_DUPLICATES_DISCARD:
+	  break;
+	
+	case SEC_LINK_DUPLICATES_ONE_ONLY:
+	  (*_bfd_error_handler)
+	    (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
+	     bfd_archive_filename (abfd), name);
+	  break;
+
+	case SEC_LINK_DUPLICATES_SAME_SIZE:
+	  if (sec->size != l->sec->size)
+	    (*_bfd_error_handler)
+	      (_("%s: %s: warning: duplicate section `%s' has different size\n"),
+	       bfd_archive_filename (abfd), name);
+	  break;
+	}
+      
+      /* Set the output_section field so that lang_add_section does not
+	 create a lang_input_section structure for this section.  Since
+	 there might be a symbol in the section being discarded, we
+	 must retain a pointer to the section which we are really going
+	 to use.  */
+      sec->output_section = bfd_abs_section_ptr;
+      sec->kept_section = l->sec;
+      
+      if (flags & SEC_GROUP)
+	bfd_discard_group (abfd, sec);
+
+      return;
+    }
+
+  /* This is the first section with this name.  Record it.  Allocate
+     the memory from the same obstack as the hash table is kept in.  */
+
+  l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+
+  l->sec = sec;
+  l->next = already_linked_list->entry;
+  already_linked_list->entry = l;
+}
+
+/* Support routines for the hash table used by section_already_linked,
+   initialize the table, fill in an entry and remove the table.  */
+
+static struct bfd_hash_entry *
+already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
+			struct bfd_hash_table *table,
+			const char *string ATTRIBUTE_UNUSED)
+{
+  struct bfd_section_already_linked_hash_entry *ret =
+    bfd_hash_allocate (table,
+		       sizeof (struct bfd_section_already_linked_hash_entry));
+
+  ret->entry = NULL;
+
+  return &ret->root;
+}
+
+bfd_boolean
+bfd_section_already_linked_table_init (void)
+{
+  return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
+				already_linked_newfunc, 42);
+}
+
+void
+bfd_section_already_linked_table_free (void)
+{
+  bfd_hash_table_free (&_bfd_section_already_linked_table);
+}
--- binutils/bfd/mach-o.c.comdat	2004-06-28 19:02:10.488991867 -0700
+++ binutils/bfd/mach-o.c	2004-06-28 21:29:04.093027535 -0700
@@ -70,6 +70,8 @@
 #define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections
 #define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section
 #define bfd_mach_o_bfd_discard_group bfd_generic_discard_group
+#define bfd_mach_o_section_already_linked \
+  _bfd_generic_section_already_linked
 #define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
 
 static bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data
--- binutils/bfd/mmo.c.comdat	2004-06-28 19:02:10.811950102 -0700
+++ binutils/bfd/mmo.c	2004-06-28 21:29:04.096027147 -0700
@@ -3286,6 +3286,8 @@ mmo_canonicalize_reloc (abfd, section, r
 #define mmo_bfd_merge_sections bfd_generic_merge_sections
 #define mmo_bfd_is_group_section bfd_generic_is_group_section
 #define mmo_bfd_discard_group bfd_generic_discard_group
+#define mmo_section_already_linked \
+  _bfd_generic_section_already_linked
 
 /* objcopy will be upset if we return -1 from bfd_get_reloc_upper_bound by
    using BFD_JUMP_TABLE_RELOCS (_bfd_norelocs) rather than 0.  FIXME: Most
--- binutils/bfd/nlm-target.h.comdat	2004-05-10 07:18:16.000000000 -0700
+++ binutils/bfd/nlm-target.h	2004-06-28 21:29:04.097027017 -0700
@@ -46,6 +46,8 @@ Foundation, Inc., 59 Temple Place - Suit
 #define nlm_bfd_merge_sections bfd_generic_merge_sections
 #define nlm_bfd_is_group_section bfd_generic_is_group_section
 #define nlm_bfd_discard_group bfd_generic_discard_group
+#define nlm_section_already_linked \
+  _bfd_generic_section_already_linked
 #define nlm_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define nlm_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define nlm_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/oasys.c.comdat	2004-06-28 19:02:11.054918681 -0700
+++ binutils/bfd/oasys.c	2004-06-28 21:29:04.098026888 -0700
@@ -1508,6 +1508,8 @@ oasys_sizeof_headers (abfd, exec)
 #define oasys_bfd_merge_sections bfd_generic_merge_sections
 #define oasys_bfd_is_group_section bfd_generic_is_group_section
 #define oasys_bfd_discard_group bfd_generic_discard_group
+#define oasys_section_already_linked \
+  _bfd_generic_section_already_linked
 #define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/pef.c.comdat	2004-06-28 19:02:11.521858295 -0700
+++ binutils/bfd/pef.c	2004-06-28 21:29:04.099026758 -0700
@@ -54,6 +54,7 @@
 #define bfd_pef_bfd_merge_sections                  bfd_generic_merge_sections
 #define bfd_pef_bfd_is_group_section		    bfd_generic_is_group_section
 #define bfd_pef_bfd_discard_group                   bfd_generic_discard_group
+#define bfd_pef_section_already_linked	    _bfd_generic_section_already_linked
 #define bfd_pef_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
 #define bfd_pef_bfd_link_hash_table_free            _bfd_generic_link_hash_table_free
 #define bfd_pef_bfd_link_add_symbols                _bfd_generic_link_add_symbols
--- binutils/bfd/ppcboot.c.comdat	2004-06-28 19:02:11.525857778 -0700
+++ binutils/bfd/ppcboot.c	2004-06-28 21:29:04.100026629 -0700
@@ -471,6 +471,8 @@ ppcboot_bfd_print_private_bfd_data (abfd
 #define ppcboot_bfd_merge_sections bfd_generic_merge_sections
 #define ppcboot_bfd_is_group_section bfd_generic_is_group_section
 #define ppcboot_bfd_discard_group bfd_generic_discard_group
+#define ppcboot_section_already_linked \
+  _bfd_generic_section_already_linked
 #define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ppcboot_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/section.c.comdat	2004-06-28 19:02:11.856814978 -0700
+++ binutils/bfd/section.c	2004-06-28 23:21:09.369896697 -0700
@@ -149,23 +149,6 @@ SUBSECTION
 
 CODE_FRAGMENT
 .
-.{* This structure is used for a comdat section, as in PE.  A comdat
-.   section is associated with a particular symbol.  When the linker
-.   sees a comdat section, it keeps only one of the sections with a
-.   given name and associated with a given symbol.  *}
-.
-.struct bfd_comdat_info
-.{
-.  {* The name of the symbol associated with a comdat section.  *}
-.  const char *name;
-.
-.  {* The local symbol table index of the symbol associated with a
-.     comdat section.  This is only meaningful to the object file format
-.     specific code; it is not an index into the list returned by
-.     bfd_canonicalize_symtab.  *}
-.  long symbol;
-.};
-.
 .typedef struct bfd_section
 .{
 .  {* The name of the section; the name isn't a copy, the pointer is
@@ -488,9 +471,6 @@ CODE_FRAGMENT
 .  {* Entity size for merging purposes.  *}
 .  unsigned int entsize;
 .
-.  {* Optional information about a COMDAT entry; NULL if not COMDAT.  *}
-.  struct bfd_comdat_info *comdat;
-.
 .  {* Points to the kept section if this section is a link-once section,
 .     and is discarded.  *}
 .  struct bfd_section *kept_section;
@@ -633,8 +613,8 @@ static const asymbol global_syms[] =
     /* line_filepos, userdata, contents, lineno, lineno_count,       */	\
        0,            NULL,     NULL,     NULL,   0,			\
 									\
-    /* entsize, comdat, kept_section, moving_line_filepos,           */	\
-       0,       NULL,   NULL,	      0,				\
+    /* entsize, kept_section, moving_line_filepos,	           */	\
+       0,       NULL,	      0,					\
 									\
     /* target_index, used_by_bfd, constructor_chain, owner,          */	\
        0,            NULL,        NULL,              NULL,		\
--- binutils/bfd/som.c.comdat	2004-06-28 19:02:12.099783556 -0700
+++ binutils/bfd/som.c	2004-06-28 21:29:04.105025982 -0700
@@ -6404,6 +6404,8 @@ som_bfd_link_split_section (abfd, sec)
 #define som_bfd_merge_sections		bfd_generic_merge_sections
 #define som_bfd_is_group_section	bfd_generic_is_group_section
 #define som_bfd_discard_group		bfd_generic_discard_group
+#define som_section_already_linked \
+  _bfd_generic_section_already_linked
 
 const bfd_target som_vec = {
   "som",			/* name */
--- binutils/bfd/srec.c.comdat	2004-06-28 19:02:12.184772565 -0700
+++ binutils/bfd/srec.c	2004-06-28 21:29:04.106025852 -0700
@@ -1286,6 +1286,8 @@ srec_print_symbol (abfd, afile, symbol, 
 #define srec_bfd_merge_sections bfd_generic_merge_sections
 #define srec_bfd_is_group_section bfd_generic_is_group_section
 #define srec_bfd_discard_group bfd_generic_discard_group
+#define srec_section_already_linked \
+  _bfd_generic_section_already_linked
 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/targets.c.comdat	2004-05-25 22:45:54.000000000 -0700
+++ binutils/bfd/targets.c	2004-06-28 21:54:25.227081136 -0700
@@ -412,7 +412,8 @@ BFD_JUMP_TABLE macros.
 .  NAME##_bfd_gc_sections, \
 .  NAME##_bfd_merge_sections, \
 .  NAME##_bfd_is_group_section, \
-.  NAME##_bfd_discard_group
+.  NAME##_bfd_discard_group, \
+.  NAME##_section_already_linked \
 .
 .  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
 .  bfd_byte *  (*_bfd_get_relocated_section_contents)
@@ -455,6 +456,10 @@ BFD_JUMP_TABLE macros.
 .  {* Discard members of a group.  *}
 .  bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
 .
+.  {* Check if SEC has been already linked during a reloceatable or
+.     final link.  *}
+.  void (*_section_already_linked) (bfd *, struct bfd_section *);
+.
 .  {* Routines to handle dynamic symbols and relocs.  *}
 .#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
 .  NAME##_get_dynamic_symtab_upper_bound, \
--- binutils/bfd/tekhex.c.comdat	2004-06-28 19:02:12.429740886 -0700
+++ binutils/bfd/tekhex.c	2004-06-28 21:29:04.109025464 -0700
@@ -1003,6 +1003,8 @@ tekhex_print_symbol (abfd, filep, symbol
 #define tekhex_bfd_merge_sections bfd_generic_merge_sections
 #define tekhex_bfd_is_group_section bfd_generic_is_group_section
 #define tekhex_bfd_discard_group bfd_generic_discard_group
+#define tekhex_section_already_linked \
+  _bfd_generic_section_already_linked
 #define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define tekhex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/versados.c.comdat	2004-06-28 19:02:12.474735067 -0700
+++ binutils/bfd/versados.c	2004-06-28 21:29:04.109025464 -0700
@@ -874,6 +874,8 @@ versados_canonicalize_reloc (abfd, secti
 #define versados_bfd_merge_sections bfd_generic_merge_sections
 #define versados_bfd_is_group_section bfd_generic_is_group_section
 #define versados_bfd_discard_group bfd_generic_discard_group
+#define versados_section_already_linked \
+  _bfd_generic_section_already_linked
 #define versados_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define versados_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define versados_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/vms.c.comdat	2004-06-28 19:02:12.671709594 -0700
+++ binutils/bfd/vms.c	2004-06-28 21:29:04.111025205 -0700
@@ -168,6 +168,8 @@ static bfd_boolean vms_bfd_set_private_f
 #define vms_bfd_link_just_syms _bfd_generic_link_just_syms
 #define vms_bfd_is_group_section bfd_generic_is_group_section
 #define vms_bfd_discard_group bfd_generic_discard_group
+#define vms_section_already_linked \
+  _bfd_generic_section_already_linked
 #define vms_bfd_copy_private_header_data \
   _bfd_generic_bfd_copy_private_header_data
 
--- binutils/bfd/xcoff-target.h.comdat	2002-11-30 00:39:40.000000000 -0800
+++ binutils/bfd/xcoff-target.h	2004-06-28 21:29:04.111025205 -0700
@@ -99,6 +99,8 @@ extern int lynx_core_file_failing_signal
 #define _bfd_xcoff_bfd_gc_sections coff_bfd_gc_sections
 #define _bfd_xcoff_bfd_merge_sections coff_bfd_merge_sections
 #define _bfd_xcoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_xcoff_section_already_linked \
+  _bfd_generic_section_already_linked
 #define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
 
 /* XCOFF archives do not have anything which corresponds to an
--- binutils/bfd/xsym.c.comdat	2004-06-28 19:02:13.059659423 -0700
+++ binutils/bfd/xsym.c	2004-06-28 21:29:04.113024946 -0700
@@ -44,6 +44,8 @@
 #define bfd_sym_bfd_merge_sections bfd_generic_merge_sections
 #define bfd_sym_bfd_is_group_section bfd_generic_is_group_section
 #define bfd_sym_bfd_discard_group bfd_generic_discard_group
+#define bfd_sym_section_already_linked \
+  _bfd_generic_section_already_linked
 #define bfd_sym_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define bfd_sym_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 #define bfd_sym_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/ld/ldlang.c.comdat	2004-06-28 19:02:15.394357495 -0700
+++ binutils/ld/ldlang.c	2004-06-29 00:52:33.383317486 -0700
@@ -883,44 +883,10 @@ exp_init_os (etree_type *exp)
     }
 }
 
-/* Sections marked with the SEC_LINK_ONCE flag should only be linked
-   once into the output.  This routine checks each section, and
-   arrange to discard it if a section of the same name has already
-   been linked.  If the section has COMDAT information, then it uses
-   that to decide whether the section should be included.  This code
-   assumes that all relevant sections have the SEC_LINK_ONCE flag set;
-   that is, it does not depend solely upon the section name.
-   section_already_linked is called via bfd_map_over_sections.  */
-
-/* This is the shape of the elements inside the already_linked hash
-   table. It maps a name onto a list of already_linked elements with
-   the same name.  It's possible to get more than one element in a
-   list if the COMDAT sections have different names.  */
-
-struct already_linked_hash_entry
-{
-  struct bfd_hash_entry root;
-  struct already_linked *entry;
-};
-
-struct already_linked
-{
-  struct already_linked *next;
-  asection *sec;
-};
-
-/* The hash table.  */
-
-static struct bfd_hash_table already_linked_table;
-
 static void
 section_already_linked (bfd *abfd, asection *sec, void *data)
 {
   lang_input_statement_type *entry = data;
-  flagword flags;
-  const char *name;
-  struct already_linked *l;
-  struct already_linked_hash_entry *already_linked_list;
 
   /* If we are only reading symbols from this object, then we want to
      discard all sections.  */
@@ -930,128 +896,7 @@ section_already_linked (bfd *abfd, asect
       return;
     }
 
-  flags = sec->flags;
-  if ((flags & SEC_LINK_ONCE) == 0)
-    return;
-
-  /* FIXME: When doing a relocatable link, we may have trouble
-     copying relocations in other sections that refer to local symbols
-     in the section being discarded.  Those relocations will have to
-     be converted somehow; as of this writing I'm not sure that any of
-     the backends handle that correctly.
-
-     It is tempting to instead not discard link once sections when
-     doing a relocatable link (technically, they should be discarded
-     whenever we are building constructors).  However, that fails,
-     because the linker winds up combining all the link once sections
-     into a single large link once section, which defeats the purpose
-     of having link once sections in the first place.
-
-     Also, not merging link once sections in a relocatable link
-     causes trouble for MIPS ELF, which relies on link once semantics
-     to handle the .reginfo section correctly.  */
-
-  name = bfd_get_section_name (abfd, sec);
-
-  already_linked_list =
-    ((struct already_linked_hash_entry *)
-     bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE));
-
-  for (l = already_linked_list->entry; l != NULL; l = l->next)
-    {
-      if (sec->comdat == NULL
-	  || l->sec->comdat == NULL
-	  || strcmp (sec->comdat->name, l->sec->comdat->name) == 0)
-	{
-	  /* The section has already been linked.  See if we should
-             issue a warning.  */
-	  switch (flags & SEC_LINK_DUPLICATES)
-	    {
-	    default:
-	      abort ();
-
-	    case SEC_LINK_DUPLICATES_DISCARD:
-	      break;
-
-	    case SEC_LINK_DUPLICATES_ONE_ONLY:
-	      if (sec->comdat == NULL)
-		einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
-		       abfd, name);
-	      else
-		einfo (_("%P: %B: warning: ignoring duplicate `%s'"
-			 " section symbol `%s'\n"),
-		       abfd, name, sec->comdat->name);
-	      break;
-
-	    case SEC_LINK_DUPLICATES_SAME_CONTENTS:
-	      /* FIXME: We should really dig out the contents of both
-                 sections and memcmp them.  The COFF/PE spec says that
-                 the Microsoft linker does not implement this
-                 correctly, so I'm not going to bother doing it
-                 either.  */
-	      /* Fall through.  */
-	    case SEC_LINK_DUPLICATES_SAME_SIZE:
-	      if (sec->size != l->sec->size)
-		einfo (_("%P: %B: warning: duplicate section `%s'"
-			 " has different size\n"),
-		       abfd, name);
-	      break;
-	    }
-
-	  /* Set the output_section field so that lang_add_section
-	     does not create a lang_input_section structure for this
-	     section.  Since there might be a symbol in the section
-	     being discarded, we must retain a pointer to the section
-	     which we are really going to use.  */
-	  sec->output_section = bfd_abs_section_ptr;
-	  sec->kept_section = l->sec;
-
-	  if (flags & SEC_GROUP)
-	    bfd_discard_group (abfd, sec);
-
-	  return;
-	}
-    }
-
-  /* This is the first section with this name.  Record it.  Allocate
-     the memory from the same obstack as the hash table is kept in.  */
-
-  l = bfd_hash_allocate (&already_linked_table, sizeof *l);
-
-  l->sec = sec;
-  l->next = already_linked_list->entry;
-  already_linked_list->entry = l;
-}
-
-/* Support routines for the hash table used by section_already_linked,
-   initialize the table, fill in an entry and remove the table.  */
-
-static struct bfd_hash_entry *
-already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
-			struct bfd_hash_table *table,
-			const char *string ATTRIBUTE_UNUSED)
-{
-  struct already_linked_hash_entry *ret =
-    bfd_hash_allocate (table, sizeof (struct already_linked_hash_entry));
-
-  ret->entry = NULL;
-
-  return &ret->root;
-}
-
-static void
-already_linked_table_init (void)
-{
-  if (! bfd_hash_table_init_n (&already_linked_table,
-			       already_linked_newfunc,
-			       42))
-    einfo (_("%P%F: Failed to create hash table\n"));
-}
-
-static void
-already_linked_table_free (void)
-{
-  bfd_hash_table_free (&already_linked_table);
+  bfd_section_already_linked (abfd, sec);
 }
 
 /* The wild routines.
@@ -4340,7 +4185,8 @@ lang_process (void)
   /* Add to the hash table all undefineds on the command line.  */
   lang_place_undefineds ();
 
-  already_linked_table_init ();
+  if (!bfd_section_already_linked_table_init ())
+    einfo (_("%P%F: Failed to create hash table\n"));
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
@@ -4352,7 +4198,7 @@ lang_process (void)
 
   ldemul_after_open ();
 
-  already_linked_table_free ();
+  bfd_section_already_linked_table_free ();
 
   /* Make sure that we're not mixing architectures.  We call this
      after all the input files have been opened, but before we do any


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]