PATCH: Remove bfd_comdat_info and move section_already_linked

H. J. Lu hjl@lucon.org
Tue Jul 20 21:08:00 GMT 2004


On Tue, Jul 20, 2004 at 06:24:17PM +0100, Nick Clifton wrote:
> Hi H.J.
> 
> > > I like it, except that it seems to me that you could leave
> > > section_already_linked where it is, and just provide a bfd xvec
> > > predicate.  That would save some code duplication, which helps
> > > in maintaining the linker.
> > > 
> > 
> > The problem is that piece of code can be very much format specific. I
> > have a follow-on patch to fix
> > 
> > http://sources.redhat.com/bugzilla/show_bug.cgi?id=246
> > 
> > My patch needs to access ELF backend. To do it in the linker, I will
> > need to add another field to bfd xvec and we have to do more checking
> > on input to see if it is ELF. I think the code duplication is very
> > minimum here.
> 
> Well you still have the ...section_already_linked() code duplicated
> three times.  That could be reduced.  Plus there is a problem in that
> some of the COFF based ports do not currently include cofflink.lo when
> building libbfd.a, so that there is an unresolved reference to
> _bfd_coff_section_already_linked().

I updated my patch to fold _bfd_coff_section_already_linked into
_bfd_generic_section_already_linked.

> 
> How about this variation on your patch which adds in the necessary
> fixes to bfd/configure.in and also creates a generic
> section_already_linked() function which takes file format specific
> helper functions as arguments ?
> 

The problem is _bfd_elf_section_already_linked will be changed into
somthing which helper functions won't work to support

http://gcc.gnu.org/ml/gcc-patches/2004-07/msg01047.html


H.J.
-------------- next part --------------
bfd/

2004-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* aout-adobe.c (aout_32_section_already_linked): Defined.
	* aout-target.h (MY_section_already_linked): Likewise.
	* aout-tic30.c (MY_section_already_linked): Likewise.
	* binary.c (binary_section_already_linked): Likewise.
	* bout.c (b_out_section_already_linked): Likewise.
	* coff-alpha.c (_bfd_ecoff_section_already_linked): Likewise.
	* coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
	* coffcode.h (coff_section_already_linked): Likewise.
	* i386msdos.c (msdos_section_already_linked): Likewise.
	* i386os9k.c (os9k_section_already_linked): Likewise.
	* ieee.c (ieee_section_already_linked): Likewise.
	* ihex.c (ihex_section_already_linked): Likewise.
	* mach-o.c (bfd_mach_o_section_already_linked): Likewise.
	* mmo.c (mmo_section_already_linked): Likewise.
	* nlm-target.h (nlm_section_already_linked): Likewise.
	* oasys.c (oasys_section_already_linked): Likewise.
	* pef.c (bfd_pef_section_already_linked): Likewise.
	* ppcboot.c (ppcboot_section_already_linked): Likewise.
	* som.c (som_bfd_discard_group): Likewise.
	* srec.c (srec_section_already_linked): Likewise.
	* tekhex.c (tekhex_section_already_linked): Likewise.
	* versados.c (versados_section_already_linked): Likewise.
	* vms.c (vms_section_already_linked): Likewise.
	* coff-target.h (_bfd_xcoff_section_already_linked): Likewise.
	* xsym.c (bfd_sym_section_already_linked): Likewise.

	* bfd-in.h (bfd_section_already_linked_table_init): New.
	(bfd_section_already_linked_table_free): Likewise.

	* coff-rs6000.c (rs6000coff_vec): Add
	_bfd_generic_section_already_linked.
	(pmac_xcoff_vec): Likewise.
	* coff64-rs6000.c (rs6000coff64_vec): Likewise.
	(aix5coff64_vec): Likewise.

	* elf-bfd.h (_bfd_elf_section_already_linked): New prototype.
	* elflink.c (_bfd_elf_section_already_linked): New function.

	* elfxx-target.h (bfd_elfNN_section_already_linked): Defined.

	* libbfd-in.h (_bfd_nolink_section_already_linked): Defined.
	(_bfd_generic_section_already_linked): New.
	(bfd_section_already_linked_hash_entry): Likewise.
	(bfd_section_already_linked): Likewise.
	(bfd_section_already_linked_table_lookup): Likewise.
	(bfd_section_already_linked_table_insert): Likewise.

	* linker.c (bfd_section_already_linked): New.
	(_bfd_section_already_linked_table): Likewise.
	(bfd_section_already_linked_table_lookup): Likewise.
	(bfd_section_already_linked_table_insert): Likewise.
	(already_linked_newfunc): Likewise.
	(bfd_section_already_linked_table_init): Likewise.
	(bfd_section_already_linked_table_free): Likewise.
	(_bfd_generic_section_already_linked): Likewise.

	* section.c (bfd_section): Remove comdat.
	(bfd_comdat_info): Moved to ...
	* bfd-in.h (coff_comdat_info): Here.
	(bfd_coff_get_comdat_section): New.
	* coffgen.c (bfd_coff_get_comdat_section): Likewise.
	* libcoff-in.h (coff_section_tdata): Add comdat.
	* coffcode.h (handle_COMDAT): Updated.
	* cofflink.c (coff_link_add_symbols): Likewise.
	* ecoff.c (bfd_debug_section): Likewise.

	* targets.c (bfd_target): Add _section_already_linked.
	(BFD_JUMP_TABLE_LINK): Updated.

	* bfd-in2.h: Regenerated.
	* libbfd.h: Likewise.
	* libcoff.h: Likewise.

binutils/

2004-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* objcopy.c (filter_symbols): Use bfd_coff_get_comdat_section
	to access comdat.
	* objdump.c (dump_section_header): Likewise.
ld/

2004-06-30  H.J. Lu  <hongjiu.lu@intel.com>

	* ldlang.c (already_linked_hash_entry): Removed.
	(already_linked): Likewise.
	(already_linked_table): Likewise.
	(section_already_linked): Call bfd_section_already_linked.
	(lang_process): Replace already_linked_table_init with
	bfd_section_already_linked_table_init and check return. Replace
	already_linked_table_free with bfd_section_already_linked_table_free.

--- binutils/bfd/aout-adobe.c.comdat	2004-06-28 19:01:58.000000000 -0700
+++ binutils/bfd/aout-adobe.c	2004-07-20 11:21:13.000000000 -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.000000000 -0700
+++ binutils/bfd/aout-target.h	2004-07-20 11:21:13.000000000 -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-29 11:22:40.000000000 -0700
+++ binutils/bfd/aout-tic30.c	2004-07-20 11:21:13.000000000 -0700
@@ -976,6 +976,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-07-19 09:41:19.000000000 -0700
+++ binutils/bfd/bfd-in.h	2004-07-20 11:21:13.000000000 -0700
@@ -559,6 +559,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.  */
 
@@ -847,3 +850,23 @@ 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.000000000 -0700
+++ binutils/bfd/binary.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/bout.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/coff-alpha.c	2004-07-20 11:21:14.000000000 -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-29 11:22:41.000000000 -0700
+++ binutils/bfd/coff-mips.c	2004-07-20 11:21:14.000000000 -0700
@@ -1395,6 +1395,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.000000000 -0700
+++ binutils/bfd/coff-rs6000.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/coff64-rs6000.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/coffcode.h	2004-07-20 13:06:22.604923290 -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,11 @@ 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_generic_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.000000000 -0700
+++ binutils/bfd/coffgen.c	2004-07-20 11:21:14.000000000 -0700
@@ -2496,3 +2496,12 @@ 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-07-03 10:00:44.000000000 -0700
+++ binutils/bfd/cofflink.c	2004-07-20 13:02:13.347159055 -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;
 	    }
 
--- binutils/bfd/ecoff.c.comdat	2004-06-28 19:02:01.000000000 -0700
+++ binutils/bfd/ecoff.c	2004-07-20 11:21:14.000000000 -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-07-19 09:33:04.000000000 -0700
+++ binutils/bfd/elf-bfd.h	2004-07-20 11:21:14.000000000 -0700
@@ -1387,6 +1387,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-07-19 09:49:44.000000000 -0700
+++ binutils/bfd/elflink.c	2004-07-20 11:21:14.000000000 -0700
@@ -9034,3 +9034,89 @@ bfd_elf_discard_info (bfd *output_bfd, s
 
   return ret;
 }
+
+void
+_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * 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 = bfd_section_already_linked_table_lookup (name);
+
+  for (l = already_linked_list->entry; l != NULL; l = l->next)
+    {
+      /* We may have 3 different sections on the list: group section,
+	 comdat section and linkonce section. SEC may be a linkonce or
+	 group section. We match a group section with a group section,
+	 a linkonce section with a linkonce section, and ignore comdat
+	 section.  */
+      if ((sec->flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+	  && bfd_coff_get_comdat_section (abfd, l->sec) == NULL)
+	{
+	  /* 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_elf_discard_group (abfd, sec);
+
+	  return;
+	}
+    }
+
+  /* This is the first section with this name.  Record it.  */
+  bfd_section_already_linked_table_insert (already_linked_list, sec);
+}
--- binutils/bfd/elfxx-target.h.comdat	2004-07-19 09:33:07.000000000 -0700
+++ binutils/bfd/elfxx-target.h	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/i386msdos.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/i386os9k.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/ieee.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/ihex.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/libbfd-in.h	2004-07-20 11:21:14.000000000 -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,24 @@ 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;
+};
+
+extern struct bfd_section_already_linked_hash_entry *
+  bfd_section_already_linked_table_lookup (const char *);
+extern void bfd_section_already_linked_table_insert
+  (struct bfd_section_already_linked_hash_entry *, asection *);
--- binutils/bfd/libcoff-in.h.comdat	2004-06-28 19:02:10.000000000 -0700
+++ binutils/bfd/libcoff-in.h	2004-07-20 13:04:07.685372034 -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;
--- binutils/bfd/linker.c.comdat	2004-06-29 11:22:45.000000000 -0700
+++ binutils/bfd/linker.c	2004-07-20 13:12:22.205417227 -0700
@@ -2827,3 +2827,197 @@ _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.  */
+
+/* The hash table.  */
+
+static struct bfd_hash_table _bfd_section_already_linked_table;
+
+/* Support routines for the hash table used by section_already_linked,
+   initialize the table, lookup, fill in an entry and remove the
+   table.  */
+
+struct bfd_section_already_linked_hash_entry *
+bfd_section_already_linked_table_lookup (const char *name)
+{
+  return ((struct bfd_section_already_linked_hash_entry *)
+	  bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+			   TRUE, FALSE));
+}
+
+void
+bfd_section_already_linked_table_insert
+  (struct bfd_section_already_linked_hash_entry *already_linked_list,
+   asection *sec)
+{
+  struct bfd_section_already_linked *l;
+
+  /* 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;
+}
+
+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 *ret);
+
+  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);
+}
+
+/* This is used on non-ELF inputs.  */
+
+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.  */
+
+  name = bfd_get_section_name (abfd, sec);
+
+  already_linked_list = bfd_section_already_linked_table_lookup (name);
+
+  for (l = already_linked_list->entry; l != NULL; l = l->next)
+    {
+      bfd_boolean skip = FALSE;
+      struct coff_comdat_info *s_comdat
+	= bfd_coff_get_comdat_section (abfd, sec);
+      struct coff_comdat_info *l_comdat
+	= bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+      /* We may have 3 different sections on the list: group section,
+	 comdat section and linkonce section. SEC may be a linkonce or
+	 comdat section. We always ignore group section. For non-COFF
+	 inputs, we also ignore comdat section.
+
+	 FIXME: Is that safe to match a linkonce section with a comdat
+	 section for COFF inputs?  */
+      if ((l->sec->flags & SEC_GROUP) != 0)
+	skip = TRUE;
+      else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+	{
+	  if (s_comdat != NULL
+	      && l_comdat != NULL
+	      && strcmp (s_comdat->name, l_comdat->name) != 0)
+	    skip = TRUE;
+	}
+      else if (l_comdat != NULL)
+	skip = TRUE;
+
+      if (!skip)
+	{
+	  /* 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 (s_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, s_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.  */
+  bfd_section_already_linked_table_insert (already_linked_list, sec);
+}
--- binutils/bfd/mach-o.c.comdat	2004-06-28 19:02:10.000000000 -0700
+++ binutils/bfd/mach-o.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/mmo.c	2004-07-20 11:21:14.000000000 -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-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/oasys.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/pef.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/ppcboot.c	2004-07-20 11:21:14.000000000 -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-29 11:22:46.000000000 -0700
+++ binutils/bfd/section.c	2004-07-20 11:21:14.000000000 -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
@@ -489,9 +472,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;
@@ -634,8 +614,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.000000000 -0700
+++ binutils/bfd/som.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/srec.c	2004-07-20 11:21:14.000000000 -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-07-19 09:33:08.000000000 -0700
+++ binutils/bfd/targets.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/tekhex.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/versados.c	2004-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/vms.c	2004-07-20 11:21:14.000000000 -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-07-20 11:21:14.000000000 -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.000000000 -0700
+++ binutils/bfd/xsym.c	2004-07-20 11:21:14.000000000 -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/binutils/objcopy.c.comdat	2004-06-28 19:01:56.000000000 -0700
+++ binutils/binutils/objcopy.c	2004-07-20 11:21:14.000000000 -0700
@@ -891,7 +891,7 @@ filter_symbols (bfd *abfd, bfd *obfd, as
 	keep = (strip_symbols != STRIP_DEBUG
 		&& strip_symbols != STRIP_UNNEEDED
 		&& ! convert_debugging);
-      else if (bfd_get_section (sym)->comdat)
+      else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
 	/* COMDAT sections store special information in local
 	   symbols, so we cannot risk stripping any of them.  */
 	keep = 1;
--- binutils/binutils/objdump.c.comdat	2004-06-21 14:05:20.000000000 -0700
+++ binutils/binutils/objdump.c	2004-07-20 11:21:14.000000000 -0700
@@ -351,9 +351,10 @@ dump_section_header (bfd *abfd ATTRIBUTE
 	}
       printf ("%s%s", comma, ls);
 
-      if (section->comdat != NULL)
-	printf (" (COMDAT %s %ld)", section->comdat->name,
-		section->comdat->symbol);
+      if (bfd_coff_get_comdat_section (abfd, section) != NULL)
+	printf (" (COMDAT %s %ld)",
+		bfd_coff_get_comdat_section (abfd, section)->name,
+		bfd_coff_get_comdat_section (abfd, section)->symbol);
 
       comma = ", ";
     }
--- binutils/ld/ldlang.c.comdat	2004-07-19 09:57:29.000000000 -0700
+++ binutils/ld/ldlang.c	2004-07-20 11:21:14.000000000 -0700
@@ -884,44 +884,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.  */
@@ -931,128 +897,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.
@@ -4345,7 +4190,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;
@@ -4357,7 +4203,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


More information about the Binutils mailing list