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: PATCH: Remove bfd_comdat_info and move section_already_linked


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().

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 ?

Cheers
  Nick

Index: bfd/aout-adobe.c
===================================================================
RCS file: /cvs/src/src/bfd/aout-adobe.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 aout-adobe.c
*** bfd/aout-adobe.c	24 Jun 2004 04:46:14 -0000	1.19
--- bfd/aout-adobe.c	20 Jul 2004 16:35:36 -0000
*************** aout_adobe_sizeof_headers (ignore_abfd, 
*** 518,523 ****
--- 518,525 ----
  #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 \
Index: bfd/aout-target.h
===================================================================
RCS file: /cvs/src/src/bfd/aout-target.h,v
retrieving revision 1.25
diff -c -3 -p -r1.25 aout-target.h
*** bfd/aout-target.h	24 Jun 2004 04:46:14 -0000	1.25
--- bfd/aout-target.h	20 Jul 2004 16:35:36 -0000
*************** MY_bfd_final_link (abfd, info)
*** 519,524 ****
--- 519,528 ----
  #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
Index: bfd/aout-tic30.c
===================================================================
RCS file: /cvs/src/src/bfd/aout-tic30.c,v
retrieving revision 1.25
diff -c -3 -p -r1.25 aout-tic30.c
*** bfd/aout-tic30.c	29 Jun 2004 13:46:29 -0000	1.25
--- bfd/aout-tic30.c	20 Jul 2004 16:35:37 -0000
*************** tic30_aout_set_arch_mach (abfd, arch, ma
*** 976,981 ****
--- 976,985 ----
  #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
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.86
diff -c -3 -p -r1.86 bfd-in.h
*** bfd/bfd-in.h	19 Jul 2004 16:40:45 -0000	1.86
--- bfd/bfd-in.h	20 Jul 2004 16:35:38 -0000
*************** void bfd_putl16 (bfd_vma, void *);
*** 559,564 ****
--- 559,567 ----
  
  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.  */
  
*************** extern void bfd_elf32_ia64_after_parse
*** 847,849 ****
--- 850,872 ----
  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;
+ };
+ 
+ struct coff_comdat_info *bfd_coff_get_comdat_section
+    (bfd *abfd, struct bfd_section *sec);
+ 
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.289
diff -c -3 -p -r1.289 bfd-in2.h
*** bfd/bfd-in2.h	19 Jul 2004 16:40:45 -0000	1.289
--- bfd/bfd-in2.h	20 Jul 2004 16:35:42 -0000
*************** void bfd_putl16 (bfd_vma, void *);
*** 566,571 ****
--- 566,574 ----
  
  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.  */
  
*************** extern void bfd_elf32_ia64_after_parse
*** 854,859 ****
--- 857,882 ----
  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;
+ };
+ 
+ struct coff_comdat_info *bfd_coff_get_comdat_section
+    (bfd *abfd, struct bfd_section *sec);
+ 
  /* Extracted from init.c.  */
  void bfd_init (void);
  
*************** long bfd_get_size (bfd *abfd);
*** 1019,1041 ****
  
  /* Extracted from bfdwin.c.  */
  /* Extracted from section.c.  */
- /* 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
--- 1042,1047 ----
*************** typedef struct bfd_section
*** 1359,1367 ****
    /* 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;
--- 1365,1370 ----
*************** typedef struct bfd_target
*** 4430,4436 ****
    NAME##_bfd_gc_sections, \
    NAME##_bfd_merge_sections, \
    NAME##_bfd_is_group_section, \
!   NAME##_bfd_discard_group
  
    int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
    bfd_byte *  (*_bfd_get_relocated_section_contents)
--- 4433,4440 ----
    NAME##_bfd_gc_sections, \
    NAME##_bfd_merge_sections, \
    NAME##_bfd_is_group_section, \
!   NAME##_bfd_discard_group, \
!   NAME##_section_already_linked \
  
    int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
    bfd_byte *  (*_bfd_get_relocated_section_contents)
*************** typedef struct bfd_target
*** 4473,4478 ****
--- 4477,4486 ----
    /* 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, \
*************** bfd_boolean bfd_link_split_section (bfd 
*** 4530,4535 ****
--- 4538,4548 ----
  #define bfd_link_split_section(abfd, sec) \
         BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
  
+ void bfd_section_already_linked (bfd *abfd, asection *sec);
+ 
+ #define bfd_section_already_linked(abfd, sec) \
+        BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+ 
  /* Extracted from simple.c.  */
  bfd_byte *bfd_simple_get_relocated_section_contents
     (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
Index: bfd/binary.c
===================================================================
RCS file: /cvs/src/src/bfd/binary.c,v
retrieving revision 1.22
diff -c -3 -p -r1.22 binary.c
*** bfd/binary.c	24 Jun 2004 04:46:15 -0000	1.22
--- bfd/binary.c	20 Jul 2004 16:35:42 -0000
*************** binary_sizeof_headers (abfd, exec)
*** 341,346 ****
--- 341,348 ----
  #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
Index: bfd/bout.c
===================================================================
RCS file: /cvs/src/src/bfd/bout.c,v
retrieving revision 1.21
diff -c -3 -p -r1.21 bout.c
*** bfd/bout.c	24 Jun 2004 04:46:15 -0000	1.21
--- bfd/bout.c	20 Jul 2004 16:35:44 -0000
*************** b_out_bfd_get_relocated_section_contents
*** 1487,1492 ****
--- 1487,1494 ----
  #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
Index: bfd/coff-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-alpha.c,v
retrieving revision 1.23
diff -c -3 -p -r1.23 coff-alpha.c
*** bfd/coff-alpha.c	24 Jun 2004 04:46:15 -0000	1.23
--- bfd/coff-alpha.c	20 Jul 2004 16:35:46 -0000
*************** static const struct ecoff_backend_data a
*** 2356,2361 ****
--- 2356,2363 ----
  #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 =
  {
Index: bfd/coff-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-mips.c,v
retrieving revision 1.26
diff -c -3 -p -r1.26 coff-mips.c
*** bfd/coff-mips.c	29 Jun 2004 13:46:29 -0000	1.26
--- bfd/coff-mips.c	20 Jul 2004 16:35:47 -0000
*************** static const struct ecoff_backend_data m
*** 1395,1400 ****
--- 1395,1402 ----
  
  #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;
  
Index: bfd/coff-rs6000.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-rs6000.c,v
retrieving revision 1.61
diff -c -3 -p -r1.61 coff-rs6000.c
*** bfd/coff-rs6000.c	24 Jun 2004 04:46:15 -0000	1.61
--- bfd/coff-rs6000.c	20 Jul 2004 16:35:54 -0000
*************** const bfd_target rs6000coff_vec =
*** 4198,4203 ****
--- 4198,4204 ----
      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,
*************** const bfd_target pmac_xcoff_vec =
*** 4443,4448 ****
--- 4444,4450 ----
      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,
Index: bfd/coff64-rs6000.c
===================================================================
RCS file: /cvs/src/src/bfd/coff64-rs6000.c,v
retrieving revision 1.53
diff -c -3 -p -r1.53 coff64-rs6000.c
*** bfd/coff64-rs6000.c	24 Jun 2004 04:46:16 -0000	1.53
--- bfd/coff64-rs6000.c	20 Jul 2004 16:35:54 -0000
*************** const bfd_target rs6000coff64_vec =
*** 2739,2744 ****
--- 2739,2745 ----
      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,
*************** const bfd_target aix5coff64_vec =
*** 2985,2990 ****
--- 2986,2992 ----
      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,
Index: bfd/coffcode.h
===================================================================
RCS file: /cvs/src/src/bfd/coffcode.h,v
retrieving revision 1.108
diff -c -3 -p -r1.108 coffcode.h
*** bfd/coffcode.h	24 Jun 2004 04:46:16 -0000	1.108
--- bfd/coffcode.h	20 Jul 2004 16:35:58 -0000
*************** handle_COMDAT (abfd, sec_flags, hdr, nam
*** 965,976 ****
  		   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)
  		  abort ();
  
! 		section->comdat->symbol =
  		  (esym - esymstart) / bfd_coff_symesz (abfd);
  
  		amt = strlen (symname) + 1;
--- 965,977 ----
  		   Intel puts the two adjacent, but Alpha (at
  		   least) spreads them out.  */
  
! 		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 ();
  
! 		coff_section_data (abfd, section)->comdat->symbol =
  		  (esym - esymstart) / bfd_coff_symesz (abfd);
  
  		amt = strlen (symname) + 1;
*************** handle_COMDAT (abfd, sec_flags, hdr, nam
*** 979,985 ****
  		  abort ();
  
  		strcpy (newname, symname);
! 		section->comdat->name = newname;
  	      }
  
  	      goto breakloop;
--- 980,987 ----
  		  abort ();
  
  		strcpy (newname, symname);
! 		coff_section_data (abfd, section)->comdat->name
! 		  = newname;
  	      }
  
  	      goto breakloop;
*************** static const bfd_coff_backend_data ticof
*** 5586,5591 ****
--- 5588,5597 ----
  #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 =							\
  {									\
Index: bfd/coffgen.c
===================================================================
RCS file: /cvs/src/src/bfd/coffgen.c,v
retrieving revision 1.43
diff -c -3 -p -r1.43 coffgen.c
*** bfd/coffgen.c	24 Jun 2004 04:46:16 -0000	1.43
--- bfd/coffgen.c	20 Jul 2004 16:36:01 -0000
*************** bfd_coff_set_symbol_class (abfd, symbol,
*** 2496,2498 ****
--- 2496,2507 ----
  
    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;
+ }
Index: bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.46
diff -c -3 -p -r1.46 cofflink.c
*** bfd/cofflink.c	3 Jul 2004 16:07:47 -0000	1.46
--- bfd/cofflink.c	20 Jul 2004 16:36:04 -0000
*************** coff_link_add_symbols (bfd *abfd,
*** 435,452 ****
  	  if (obj_pe (abfd)
  	      && (classification == COFF_SYMBOL_GLOBAL
  		  || classification == COFF_SYMBOL_PE_SECTION)
! 	      && section->comdat != NULL
  	      && strncmp (name, "??_", 3) == 0
! 	      && strcmp (name, 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)
  		addit = FALSE;
  	    }
  
--- 435,452 ----
  	  if (obj_pe (abfd)
  	      && (classification == COFF_SYMBOL_GLOBAL
  		  || classification == COFF_SYMBOL_PE_SECTION)
! 	      && coff_section_data (abfd, section)->comdat != NULL
  	      && strncmp (name, "??_", 3) == 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
! 		  && 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;
  	    }
  
*************** _bfd_coff_generic_relocate_section (bfd 
*** 3037,3039 ****
--- 3037,3114 ----
      }
    return TRUE;
  }
+ 
+ static bfd_boolean
+ coff_already_linked_test_func (bfd *abfd, asection *sec,
+ 			       struct bfd_section_already_linked *l)
+ {
+   struct coff_comdat_info *s_comdat
+     = bfd_coff_get_comdat_section (abfd, sec);
+   struct coff_comdat_info *l_comdat
+     = bfd_coff_get_comdat_section (abfd, 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 ignore group section.
+      
+      FIXME: Can we match a linkonce section with a comdat section?  */
+   return ((l->sec->flags & SEC_GROUP) == 0
+ 	  && (s_comdat == NULL
+ 	      || l_comdat == NULL
+ 	      || strcmp (s_comdat->name, l_comdat->name) == 0));
+ }
+ 
+ static void
+ coff_already_linked_maybe_issue_error_func (bfd *abfd, asection *sec,
+ 					    struct bfd_section_already_linked *l)
+ {
+   const char *err_msg = NULL;
+ 
+   switch (sec->flags & SEC_LINK_DUPLICATES)
+     {
+     default:
+       abort ();
+ 
+     case SEC_LINK_DUPLICATES_DISCARD:
+       break;
+ 
+     case SEC_LINK_DUPLICATES_ONE_ONLY:
+       if (bfd_coff_get_comdat_section (abfd, sec) == NULL)
+ 	err_msg = _("%s: %s: warning: ignoring duplicate section `%s'\n");
+       else
+ 	err_msg = _("%s: %s: warning: ignoring duplicate `%s' section symbol `%s'\n");
+       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)
+ 	err_msg = _("%s: %s: warning: duplicate section `%s' has different size\n");
+       break;
+     }
+ 
+   if (err_msg)
+     _bfd_error_handler (err_msg, bfd_archive_filename (abfd),
+ 			bfd_get_section_name (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.  */
+ 
+ void
+ _bfd_coff_section_already_linked (bfd *abfd, asection *sec)
+ {
+   _bfd_generic_section_already_linked_template
+     (abfd, sec, coff_already_linked_test_func,
+      coff_already_linked_maybe_issue_error_func);
+ }
Index: bfd/configure.in
===================================================================
RCS file: /cvs/src/src/bfd/configure.in,v
retrieving revision 1.157
diff -c -3 -p -r1.157 configure.in
*** bfd/configure.in	7 Jul 2004 17:28:45 -0000	1.157
--- bfd/configure.in	20 Jul 2004 16:36:11 -0000
*************** do
*** 701,708 ****
      ecoffalpha_little_vec)	tb="$tb coff-alpha.lo ecoff.lo ecofflink.lo"; target_size=64 ;;
      go32coff_vec)		tb="$tb coff-go32.lo cofflink.lo" ;;
      go32stubbedcoff_vec)	tb="$tb coff-stgo32.lo cofflink.lo" ;;
!     h8300coff_vec)		tb="$tb coff-h8300.lo reloc16.lo" ;;
!     h8500coff_vec)		tb="$tb coff-h8500.lo reloc16.lo" ;;
      host_aout_vec)		tb="$tb host-aout.lo aout32.lo" ;;
      hp300bsd_vec)		tb="$tb hp300bsd.lo aout32.lo" ;;
      hp300hpux_vec)		tb="$tb hp300hpux.lo aout32.lo" ;;
--- 701,708 ----
      ecoffalpha_little_vec)	tb="$tb coff-alpha.lo ecoff.lo ecofflink.lo"; target_size=64 ;;
      go32coff_vec)		tb="$tb coff-go32.lo cofflink.lo" ;;
      go32stubbedcoff_vec)	tb="$tb coff-stgo32.lo cofflink.lo" ;;
!     h8300coff_vec)		tb="$tb coff-h8300.lo reloc16.lo cofflink.lo" ;;
!     h8500coff_vec)		tb="$tb coff-h8500.lo reloc16.lo cofflink.lo" ;;
      host_aout_vec)		tb="$tb host-aout.lo aout32.lo" ;;
      hp300bsd_vec)		tb="$tb hp300bsd.lo aout32.lo" ;;
      hp300hpux_vec)		tb="$tb hp300hpux.lo aout32.lo" ;;
*************** do
*** 733,739 ****
      m68klynx_coff_vec)		tb="$tb cf-m68klynx.lo coff-m68k.lo cofflink.lo lynx-core.lo" ;;
      m68knetbsd_vec)		tb="$tb m68knetbsd.lo aout32.lo" ;;
      m68ksysvcoff_vec)		tb="$tb coff-svm68k.lo cofflink.lo" ;;
!     m88kbcs_vec)		tb="$tb coff-m88k.lo" ;;
      m88kmach3_vec)		tb="$tb m88kmach3.lo aout32.lo" ;;
      m88kopenbsd_vec)		tb="$tb m88kopenbsd.lo aout32.lo" ;;
      mach_o_be_vec)              tb="$tb mach-o.lo" ;;
--- 733,739 ----
      m68klynx_coff_vec)		tb="$tb cf-m68klynx.lo coff-m68k.lo cofflink.lo lynx-core.lo" ;;
      m68knetbsd_vec)		tb="$tb m68knetbsd.lo aout32.lo" ;;
      m68ksysvcoff_vec)		tb="$tb coff-svm68k.lo cofflink.lo" ;;
!     m88kbcs_vec)		tb="$tb coff-m88k.lo cofflink.lo" ;;
      m88kmach3_vec)		tb="$tb m88kmach3.lo aout32.lo" ;;
      m88kopenbsd_vec)		tb="$tb m88kopenbsd.lo aout32.lo" ;;
      mach_o_be_vec)              tb="$tb mach-o.lo" ;;
*************** do
*** 768,774 ****
      shlpe_vec)			tb="$tb pe-sh.lo coff-sh.lo peigen.lo cofflink.lo" ;;
      shlpei_vec)			tb="$tb pei-sh.lo coff-sh.lo peigen.lo cofflink.lo" ;;
      som_vec)			tb="$tb som.lo" ;;
!     sparccoff_vec)		tb="$tb coff-sparc.lo" ;;
      sparcle_aout_vec)		tb="$tb aout-sparcle.lo aout32.lo" ;;
      sparclinux_vec)		tb="$tb sparclinux.lo aout32.lo" ;;
      sparclynx_aout_vec)		tb="$tb sparclynx.lo lynx-core.lo aout32.lo" ;;
--- 768,774 ----
      shlpe_vec)			tb="$tb pe-sh.lo coff-sh.lo peigen.lo cofflink.lo" ;;
      shlpei_vec)			tb="$tb pei-sh.lo coff-sh.lo peigen.lo cofflink.lo" ;;
      som_vec)			tb="$tb som.lo" ;;
!     sparccoff_vec)		tb="$tb coff-sparc.lo cofflink.lo" ;;
      sparcle_aout_vec)		tb="$tb aout-sparcle.lo aout32.lo" ;;
      sparclinux_vec)		tb="$tb sparclinux.lo aout32.lo" ;;
      sparclynx_aout_vec)		tb="$tb sparclynx.lo lynx-core.lo aout32.lo" ;;
*************** do
*** 777,795 ****
      sunos_big_vec)		tb="$tb sunos.lo aout32.lo" ;;
      sym_vec)                    tb="$tb xsym.lo" ;;
      tic30_aout_vec)		tb="$tb aout-tic30.lo" ;;
!     tic30_coff_vec)		tb="$tb coff-tic30.lo" ;;
!     tic4x_coff0_vec)            tb="$tb coff-tic4x.lo" ;;
!     tic4x_coff0_beh_vec)        tb="$tb coff-tic4x.lo" ;;
!     tic4x_coff1_vec)            tb="$tb coff-tic4x.lo" ;;
!     tic4x_coff1_beh_vec)        tb="$tb coff-tic4x.lo" ;;
!     tic4x_coff2_vec)            tb="$tb coff-tic4x.lo" ;;
!     tic4x_coff2_beh_vec)        tb="$tb coff-tic4x.lo" ;;
!     tic54x_coff0_beh_vec)	tb="$tb coff-tic54x.lo" ;;
!     tic54x_coff0_vec)		tb="$tb coff-tic54x.lo" ;;
!     tic54x_coff1_beh_vec)	tb="$tb coff-tic54x.lo" ;;
!     tic54x_coff1_vec)		tb="$tb coff-tic54x.lo" ;;
!     tic54x_coff2_beh_vec)	tb="$tb coff-tic54x.lo" ;;
!     tic54x_coff2_vec)		tb="$tb coff-tic54x.lo" ;;
      tic80coff_vec)		tb="$tb coff-tic80.lo cofflink.lo" ;;
      vaxnetbsd_vec)		tb="$tb vaxnetbsd.lo aout32.lo" ;;
      vax1knetbsd_vec)		tb="$tb vax1knetbsd.lo aout32.lo" ;;
--- 777,795 ----
      sunos_big_vec)		tb="$tb sunos.lo aout32.lo" ;;
      sym_vec)                    tb="$tb xsym.lo" ;;
      tic30_aout_vec)		tb="$tb aout-tic30.lo" ;;
!     tic30_coff_vec)		tb="$tb coff-tic30.lo cofflink.lo" ;;
!     tic4x_coff0_vec)            tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic4x_coff0_beh_vec)        tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic4x_coff1_vec)            tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic4x_coff1_beh_vec)        tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic4x_coff2_vec)            tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic4x_coff2_beh_vec)        tb="$tb coff-tic4x.lo cofflink.lo" ;;
!     tic54x_coff0_beh_vec)	tb="$tb coff-tic54x.lo cofflink.lo" ;;
!     tic54x_coff0_vec)		tb="$tb coff-tic54x.lo cofflink.lo" ;;
!     tic54x_coff1_beh_vec)	tb="$tb coff-tic54x.lo cofflink.lo" ;;
!     tic54x_coff1_vec)		tb="$tb coff-tic54x.lo cofflink.lo" ;;
!     tic54x_coff2_beh_vec)	tb="$tb coff-tic54x.lo cofflink.lo" ;;
!     tic54x_coff2_vec)		tb="$tb coff-tic54x.lo cofflink.lo" ;;
      tic80coff_vec)		tb="$tb coff-tic80.lo cofflink.lo" ;;
      vaxnetbsd_vec)		tb="$tb vaxnetbsd.lo aout32.lo" ;;
      vax1knetbsd_vec)		tb="$tb vax1knetbsd.lo aout32.lo" ;;
*************** do
*** 797,805 ****
      versados_vec)		tb="$tb versados.lo" ;;
      vms_alpha_vec)		tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo"; target_size=64 ;;
      vms_vax_vec)		tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo" ;;
!     w65_vec)			tb="$tb coff-w65.lo reloc16.lo" ;;
!     we32kcoff_vec)		tb="$tb coff-we32k.lo" ;;
!     z8kcoff_vec)		tb="$tb coff-z8k.lo reloc16.lo" ;;
  
      # These appear out of order in targets.c
      srec_vec)			tb="$tb srec.lo" ;;
--- 797,805 ----
      versados_vec)		tb="$tb versados.lo" ;;
      vms_alpha_vec)		tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo"; target_size=64 ;;
      vms_vax_vec)		tb="$tb vms.lo vms-hdr.lo vms-gsd.lo vms-tir.lo vms-misc.lo" ;;
!     w65_vec)			tb="$tb coff-w65.lo reloc16.lo cofflink.lo" ;;
!     we32kcoff_vec)		tb="$tb coff-we32k.lo cofflink.lo" ;;
!     z8kcoff_vec)		tb="$tb coff-z8k.lo reloc16.lo cofflink.lo" ;;
  
      # These appear out of order in targets.c
      srec_vec)			tb="$tb srec.lo" ;;
Index: bfd/ecoff.c
===================================================================
RCS file: /cvs/src/src/bfd/ecoff.c,v
retrieving revision 1.35
diff -c -3 -p -r1.35 ecoff.c
*** bfd/ecoff.c	24 Jun 2004 04:46:17 -0000	1.35
--- bfd/ecoff.c	20 Jul 2004 16:36:15 -0000
*************** static asection bfd_debug_section =
*** 92,99 ****
       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,
    /* target_index, used_by_bfd, constructor_chain, owner,          */
       0,            NULL,        NULL,              NULL,
    /* symbol,                                                       */
--- 92,99 ----
       NULL,       NULL,        0,           0,       0,
    /* line_filepos, userdata, contents, lineno, lineno_count,       */
       0,            NULL,     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,                                                       */
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.146
diff -c -3 -p -r1.146 elf-bfd.h
*** bfd/elf-bfd.h	6 Jul 2004 16:58:41 -0000	1.146
--- bfd/elf-bfd.h	20 Jul 2004 16:36:17 -0000
*************** extern bfd_boolean bfd_elf_is_group_sect
*** 1387,1392 ****
--- 1387,1394 ----
    (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
Index: bfd/elf-m10300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-m10300.c,v
retrieving revision 1.55
diff -c -3 -p -r1.55 elf-m10300.c
*** bfd/elf-m10300.c	27 Jun 2004 03:02:21 -0000	1.55
--- bfd/elf-m10300.c	20 Jul 2004 16:36:21 -0000
*************** mn10300_elf_relax_section (abfd, sec, li
*** 1733,1739 ****
  	      if ((section->flags & SEC_RELOC) != 0
  		  && section->reloc_count != 0)
  		{
- 
  		  /* Get a copy of the native relocations.  */
  		  internal_relocs = (_bfd_elf_link_read_relocs
  				     (input_bfd, section, (PTR) NULL,
--- 1733,1738 ----
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.84
diff -c -3 -p -r1.84 elflink.c
*** bfd/elflink.c	19 Jul 2004 16:40:48 -0000	1.84
--- bfd/elflink.c	20 Jul 2004 16:36:30 -0000
*************** bfd_elf_discard_info (bfd *output_bfd, s
*** 9034,9036 ****
--- 9034,9067 ----
  
    return ret;
  }
+ 
+ static bfd_boolean
+ elf_already_linked_test (bfd *abfd, asection *sec,
+ 			 struct bfd_section_already_linked *l)
+ {
+   /* 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.  */
+   return ((sec->flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+ 	  && bfd_coff_get_comdat_section (abfd, l->sec) == NULL);
+ }
+ 
+ static void
+ elf_already_linked_maybe_issue_error (bfd *abfd, asection *sec,
+ 				      struct bfd_section_already_linked *l)
+ {
+   _bfd_generic_already_linked_maybe_issue_error (abfd, sec, l);
+ 
+   if (sec->flags & SEC_GROUP)
+     bfd_elf_discard_group (abfd, sec);
+ }
+ 
+ void
+ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
+ {
+   _bfd_generic_section_already_linked_template
+     (abfd, sec, elf_already_linked_test,
+      elf_already_linked_maybe_issue_error);
+ }
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.67
diff -c -3 -p -r1.67 elfxx-target.h
*** bfd/elfxx-target.h	6 Jul 2004 16:58:42 -0000	1.67
--- bfd/elfxx-target.h	20 Jul 2004 16:36:30 -0000
***************
*** 144,149 ****
--- 144,154 ----
  #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)
Index: bfd/i386msdos.c
===================================================================
RCS file: /cvs/src/src/bfd/i386msdos.c,v
retrieving revision 1.16
diff -c -3 -p -r1.16 i386msdos.c
*** bfd/i386msdos.c	24 Jun 2004 04:46:23 -0000	1.16
--- bfd/i386msdos.c	20 Jul 2004 16:36:31 -0000
*************** msdos_set_section_contents (abfd, sectio
*** 177,182 ****
--- 177,184 ----
  #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
Index: bfd/i386os9k.c
===================================================================
RCS file: /cvs/src/src/bfd/i386os9k.c,v
retrieving revision 1.14
diff -c -3 -p -r1.14 i386os9k.c
*** bfd/i386os9k.c	24 Jun 2004 04:46:23 -0000	1.14
--- bfd/i386os9k.c	20 Jul 2004 16:36:31 -0000
*************** os9k_sizeof_headers (ignore_abfd, ignore
*** 335,340 ****
--- 335,342 ----
  #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
Index: bfd/ieee.c
===================================================================
RCS file: /cvs/src/src/bfd/ieee.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 ieee.c
*** bfd/ieee.c	24 Jun 2004 04:46:23 -0000	1.38
--- bfd/ieee.c	20 Jul 2004 16:36:34 -0000
*************** ieee_bfd_debug_info_accumulate (abfd, se
*** 4039,4044 ****
--- 4039,4046 ----
  #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
Index: bfd/ihex.c
===================================================================
RCS file: /cvs/src/src/bfd/ihex.c,v
retrieving revision 1.23
diff -c -3 -p -r1.23 ihex.c
*** bfd/ihex.c	24 Jun 2004 04:46:24 -0000	1.23
--- bfd/ihex.c	20 Jul 2004 16:36:35 -0000
*************** ihex_sizeof_headers (abfd, exec)
*** 990,995 ****
--- 990,997 ----
  #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
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.38
diff -c -3 -p -r1.38 libbfd-in.h
*** bfd/libbfd-in.h	28 Jun 2004 13:57:59 -0000	1.38
--- bfd/libbfd-in.h	20 Jul 2004 16:36:35 -0000
*************** extern bfd_boolean _bfd_generic_set_sect
*** 375,380 ****
--- 375,382 ----
    ((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
*************** extern bfd_boolean _bfd_generic_final_li
*** 474,479 ****
--- 476,484 ----
  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 *);
*************** extern bfd_boolean _bfd_sh_align_load_sp
*** 653,655 ****
--- 658,686 ----
     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 *);
+ extern void _bfd_generic_section_already_linked_template
+   (bfd *, asection *, bfd_boolean (*) (bfd *, asection *, struct bfd_section_already_linked *),
+    void (*) (bfd *, asection *, struct bfd_section_already_linked *));
+ extern void _bfd_generic_already_linked_maybe_issue_error
+   (bfd *, asection *sec, struct bfd_section_already_linked *);
Index: bfd/libcoff-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libcoff-in.h,v
retrieving revision 1.21
diff -c -3 -p -r1.21 libcoff-in.h
*** bfd/libcoff-in.h	28 Jun 2004 13:57:58 -0000	1.21
--- bfd/libcoff-in.h	20 Jul 2004 16:36:37 -0000
*************** struct coff_section_tdata
*** 194,199 ****
--- 194,201 ----
    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;
*************** extern bfd_vma bfd_coff_reloc16_get_valu
*** 357,362 ****
--- 359,366 ----
     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.  */
  
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.37
diff -c -3 -p -r1.37 linker.c
*** bfd/linker.c	29 Jun 2004 14:13:44 -0000	1.37
--- bfd/linker.c	20 Jul 2004 16:36:40 -0000
*************** _bfd_generic_link_split_section (bfd *ab
*** 2827,2829 ****
--- 2827,3022 ----
  {
    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);
+ }
+ 
+ void
+ _bfd_generic_section_already_linked_template
+   (bfd *abfd, asection *sec,
+    bfd_boolean (* test_func) (bfd *, asection *, struct bfd_section_already_linked *),
+    void (* maybe_issue_error_func) (bfd *, asection *, struct bfd_section_already_linked *))
+ {
+   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)
+     {
+       if (test_func (abfd, sec, l))
+ 	{
+ 	  /* The section has already been linked.
+ 	     See if we should issue a warning.  */
+ 	  maybe_issue_error_func (abfd, sec, l);
+ 
+ 	  /* 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);
+ }
+ 
+ static bfd_boolean
+ generic_already_linked_test (bfd *abfd,
+ 			     asection *sec ATTRIBUTE_UNUSED,
+ 			     struct bfd_section_already_linked *l)
+ {
+   /* We may have 3 different sections on the list: group section,
+      comdat section and linkonce section. SEC is a linkonce section.
+      We ignore group section and comdat section.  */
+   return ((l->sec->flags & SEC_GROUP) == 0
+ 	  && bfd_coff_get_comdat_section (abfd, l->sec) == NULL);
+ }
+ 
+ /* Not static because it is called from
+    elf_already_linked_maybe_issue_error.  */
+ void
+ _bfd_generic_already_linked_maybe_issue_error (bfd *abfd, asection *sec,
+ 					       struct bfd_section_already_linked *l)
+ {
+   const char *err_msg = NULL;
+ 
+   switch (sec->flags & SEC_LINK_DUPLICATES)
+     {
+     default:
+       abort ();
+ 
+     case SEC_LINK_DUPLICATES_DISCARD:
+       break;
+ 
+     case SEC_LINK_DUPLICATES_ONE_ONLY:
+       err_msg = _("%s: %s: warning: ignoring duplicate section `%s'\n");
+       break;
+ 
+     case SEC_LINK_DUPLICATES_SAME_SIZE:
+       if (sec->size != l->sec->size)
+ 	err_msg = _("%s: %s: warning: duplicate section `%s' has different size\n");
+       break;
+     }
+ 
+   if (err_msg)
+     _bfd_error_handler (err_msg, bfd_archive_filename (abfd),
+ 			bfd_get_section_name (abfd, sec));
+ }
+ 
+ void
+ _bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+ {
+   _bfd_generic_section_already_linked_template
+     (abfd, sec, generic_already_linked_test,
+      _bfd_generic_already_linked_maybe_issue_error);
+ }
Index: bfd/mach-o.c
===================================================================
RCS file: /cvs/src/src/bfd/mach-o.c,v
retrieving revision 1.10
diff -c -3 -p -r1.10 mach-o.c
*** bfd/mach-o.c	24 Jun 2004 04:46:24 -0000	1.10
--- bfd/mach-o.c	20 Jul 2004 16:36:42 -0000
***************
*** 70,75 ****
--- 70,77 ----
  #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
Index: bfd/mmo.c
===================================================================
RCS file: /cvs/src/src/bfd/mmo.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 mmo.c
*** bfd/mmo.c	24 Jun 2004 04:46:25 -0000	1.19
--- bfd/mmo.c	20 Jul 2004 16:36:45 -0000
*************** mmo_canonicalize_reloc (abfd, section, r
*** 3286,3291 ****
--- 3286,3293 ----
  #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
Index: bfd/nlm-target.h
===================================================================
RCS file: /cvs/src/src/bfd/nlm-target.h,v
retrieving revision 1.11
diff -c -3 -p -r1.11 nlm-target.h
*** bfd/nlm-target.h	30 Apr 2004 14:23:40 -0000	1.11
--- bfd/nlm-target.h	20 Jul 2004 16:36:46 -0000
*************** Foundation, Inc., 59 Temple Place - Suit
*** 46,51 ****
--- 46,53 ----
  #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
Index: bfd/oasys.c
===================================================================
RCS file: /cvs/src/src/bfd/oasys.c,v
retrieving revision 1.24
diff -c -3 -p -r1.24 oasys.c
*** bfd/oasys.c	24 Jun 2004 04:46:25 -0000	1.24
--- bfd/oasys.c	20 Jul 2004 16:36:47 -0000
*************** oasys_sizeof_headers (abfd, exec)
*** 1508,1513 ****
--- 1508,1515 ----
  #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
Index: bfd/pef.c
===================================================================
RCS file: /cvs/src/src/bfd/pef.c,v
retrieving revision 1.8
diff -c -3 -p -r1.8 pef.c
*** bfd/pef.c	24 Jun 2004 04:46:25 -0000	1.8
--- bfd/pef.c	20 Jul 2004 16:36:48 -0000
***************
*** 54,59 ****
--- 54,60 ----
  #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
Index: bfd/ppcboot.c
===================================================================
RCS file: /cvs/src/src/bfd/ppcboot.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 ppcboot.c
*** bfd/ppcboot.c	24 Jun 2004 04:46:25 -0000	1.19
--- bfd/ppcboot.c	20 Jul 2004 16:36:49 -0000
*************** ppcboot_bfd_print_private_bfd_data (abfd
*** 471,476 ****
--- 471,478 ----
  #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
Index: bfd/section.c
===================================================================
RCS file: /cvs/src/src/bfd/section.c,v
retrieving revision 1.74
diff -c -3 -p -r1.74 section.c
*** bfd/section.c	29 Jun 2004 14:13:44 -0000	1.74
--- bfd/section.c	20 Jul 2004 16:36:53 -0000
*************** SUBSECTION
*** 149,171 ****
  
  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
--- 149,154 ----
*************** CODE_FRAGMENT
*** 489,497 ****
  .  {* 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;
--- 472,477 ----
*************** static const asymbol global_syms[] =
*** 634,641 ****
      /* line_filepos, userdata, contents, lineno, lineno_count,       */	\
         0,            NULL,     NULL,     NULL,   0,			\
  									\
!     /* entsize, comdat, kept_section, moving_line_filepos,           */	\
!        0,       NULL,   NULL,	      0,				\
  									\
      /* target_index, used_by_bfd, constructor_chain, owner,          */	\
         0,            NULL,        NULL,              NULL,		\
--- 614,621 ----
      /* line_filepos, userdata, contents, lineno, lineno_count,       */	\
         0,            NULL,     NULL,     NULL,   0,			\
  									\
!     /* entsize, kept_section, moving_line_filepos,	           */	\
!        0,       NULL,	      0,					\
  									\
      /* target_index, used_by_bfd, constructor_chain, owner,          */	\
         0,            NULL,        NULL,              NULL,		\
Index: bfd/som.c
===================================================================
RCS file: /cvs/src/src/bfd/som.c,v
retrieving revision 1.45
diff -c -3 -p -r1.45 som.c
*** bfd/som.c	25 Jun 2004 18:30:54 -0000	1.45
--- bfd/som.c	20 Jul 2004 16:36:59 -0000
*************** som_bfd_link_split_section (abfd, sec)
*** 6404,6409 ****
--- 6404,6411 ----
  #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 */
Index: bfd/srec.c
===================================================================
RCS file: /cvs/src/src/bfd/srec.c,v
retrieving revision 1.29
diff -c -3 -p -r1.29 srec.c
*** bfd/srec.c	24 Jun 2004 04:46:26 -0000	1.29
--- bfd/srec.c	20 Jul 2004 16:37:00 -0000
*************** srec_print_symbol (abfd, afile, symbol, 
*** 1286,1291 ****
--- 1286,1293 ----
  #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
Index: bfd/targets.c
===================================================================
RCS file: /cvs/src/src/bfd/targets.c,v
retrieving revision 1.113
diff -c -3 -p -r1.113 targets.c
*** bfd/targets.c	7 Jul 2004 17:28:46 -0000	1.113
--- bfd/targets.c	20 Jul 2004 16:37:02 -0000
*************** BFD_JUMP_TABLE macros.
*** 412,418 ****
  .  NAME##_bfd_gc_sections, \
  .  NAME##_bfd_merge_sections, \
  .  NAME##_bfd_is_group_section, \
! .  NAME##_bfd_discard_group
  .
  .  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
  .  bfd_byte *  (*_bfd_get_relocated_section_contents)
--- 412,419 ----
  .  NAME##_bfd_gc_sections, \
  .  NAME##_bfd_merge_sections, \
  .  NAME##_bfd_is_group_section, \
! .  NAME##_bfd_discard_group, \
! .  NAME##_section_already_linked \
  .
  .  int         (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
  .  bfd_byte *  (*_bfd_get_relocated_section_contents)
*************** BFD_JUMP_TABLE macros.
*** 455,460 ****
--- 456,465 ----
  .  {* 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, \
Index: bfd/tekhex.c
===================================================================
RCS file: /cvs/src/src/bfd/tekhex.c,v
retrieving revision 1.20
diff -c -3 -p -r1.20 tekhex.c
*** bfd/tekhex.c	24 Jun 2004 04:46:26 -0000	1.20
--- bfd/tekhex.c	20 Jul 2004 16:37:03 -0000
*************** tekhex_print_symbol (abfd, filep, symbol
*** 1003,1008 ****
--- 1003,1010 ----
  #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
Index: bfd/versados.c
===================================================================
RCS file: /cvs/src/src/bfd/versados.c,v
retrieving revision 1.22
diff -c -3 -p -r1.22 versados.c
*** bfd/versados.c	24 Jun 2004 04:46:26 -0000	1.22
--- bfd/versados.c	20 Jul 2004 16:37:04 -0000
*************** versados_canonicalize_reloc (abfd, secti
*** 874,879 ****
--- 874,881 ----
  #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
Index: bfd/vms.c
===================================================================
RCS file: /cvs/src/src/bfd/vms.c,v
retrieving revision 1.30
diff -c -3 -p -r1.30 vms.c
*** bfd/vms.c	24 Jun 2004 04:46:26 -0000	1.30
--- bfd/vms.c	20 Jul 2004 16:37:05 -0000
*************** static bfd_boolean vms_bfd_set_private_f
*** 168,173 ****
--- 168,175 ----
  #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
  
Index: bfd/xcoff-target.h
===================================================================
RCS file: /cvs/src/src/bfd/xcoff-target.h,v
retrieving revision 1.9
diff -c -3 -p -r1.9 xcoff-target.h
*** bfd/xcoff-target.h	30 Nov 2002 08:39:40 -0000	1.9
--- bfd/xcoff-target.h	20 Jul 2004 16:37:05 -0000
*************** extern int lynx_core_file_failing_signal
*** 99,104 ****
--- 99,106 ----
  #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
Index: bfd/xsym.c
===================================================================
RCS file: /cvs/src/src/bfd/xsym.c,v
retrieving revision 1.7
diff -c -3 -p -r1.7 xsym.c
*** bfd/xsym.c	24 Jun 2004 04:46:27 -0000	1.7
--- bfd/xsym.c	20 Jul 2004 16:37:06 -0000
***************
*** 44,49 ****
--- 44,51 ----
  #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
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.157
diff -c -3 -p -r1.157 ldlang.c
*** ld/ldlang.c	19 Jul 2004 16:40:51 -0000	1.157
--- ld/ldlang.c	20 Jul 2004 16:37:13 -0000
*************** exp_init_os (etree_type *exp)
*** 884,927 ****
      }
  }
  
- /* 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.  */
--- 884,893 ----
*************** section_already_linked (bfd *abfd, asect
*** 931,1058 ****
        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);
  }
  
  /* The wild routines.
--- 897,903 ----
        return;
      }
  
!   bfd_section_already_linked (abfd, sec);
  }
  
  /* The wild routines.
*************** lang_process (void)
*** 4345,4351 ****
    /* Add to the hash table all undefineds on the command line.  */
    lang_place_undefineds ();
  
!   already_linked_table_init ();
  
    /* Create a bfd for each input file.  */
    current_target = default_target;
--- 4190,4197 ----
    /* Add to the hash table all undefineds on the command line.  */
    lang_place_undefineds ();
  
!   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;
*************** lang_process (void)
*** 4357,4363 ****
  
    ldemul_after_open ();
  
!   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
--- 4203,4209 ----
  
    ldemul_after_open ();
  
!   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]