public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Fix PR12762 using linkonce sections in plugin bfd
@ 2011-08-11 13:08 Alan Modra
  2011-08-11 13:18 ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2011-08-11 13:08 UTC (permalink / raw)
  To: binutils

This patch undoes HJ's changes to bfd_section_already_linked in
http://sourceware.org/ml/binutils/2011-07/msg00070.html, and some of
my later changes.  HJ's patch effectively added another type of entry
to the already_linked list for plugin comdat symbols.  This works fine
most of the time, but there are parts of the bfd and linker code that
really want separate sections for comdat symbols.  For example,
ldmain.c:multiple_definition just after the FIXME comment.  So
this patch simply provides dummy linkonce sections for plugin comdat
symbols.

Ironically, the FIXME advocates doing exactly what we were attempting
in plugin.c:add_symbols, so in some respects this patch is a backwards
step.  It also uses more memory.  The reason I didn't apply further
tweaks like the patch in PR13066 is that bfd_section_already_linked
was getting quite messy.  If we are going to go the way this FIXME
suggests then we really aught to do so for all symbols, not just
plugin symbols.  I'd like to see that happen but don't have time at
the moment to fix all the fallout.

bfd/
	PR ld/12762
	* cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
	* elf-bfd.h: Likewise.
	* libbfd-in.h: Likewise.
	* targets.c: Likewise.
	* elflink.c (_bfd_elf_section_already_linked): Likewise.  Match
	plugin linkonce section with groups.  Don't check size or contents
	when comparing againt dummy plugin linkonce section.
	* linker.c (bfd_section_already_linked): Revert 2011-07-09 changes.
	(bfd_section_already_linked_table_lookup): Likewise.
	(bfd_section_already_linked_table_insert): Likewise.
	(_bfd_generic_section_already_linked): Likewise.  Don't check size
	when comparing againt dummy plugin linkonce section.
	* libbfd.h: Regenerate.
	* bfd-in2.h: Regenerate.
ld/
	PR ld/12762
	* ldlang.c (section_already_linked): Revert 2011-07-09 changes.
	* plugin.c: Likewise.
	(asymbol_from_plugin_symbol): Create linkonce section for syms
	with comdat_key.

Index: bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.78
diff -u -p -r1.78 cofflink.c
--- bfd/cofflink.c	9 Jul 2011 06:20:50 -0000	1.78
+++ bfd/cofflink.c	11 Aug 2011 06:23:38 -0000
@@ -392,11 +392,7 @@ coff_link_add_symbols (bfd *abfd,
 	      section = coff_section_from_bfd_index (abfd, sym.n_scnum);
 	      if (! obj_pe (abfd))
 		value -= section->vma;
-	      /* Treat a symbol from a discarded section as undefined.  */
-	      if (bfd_is_abs_section (section)
-		  || !bfd_is_abs_section (section->output_section))
-		break;
-	      /* Fall thru */
+	      break;
 
 	    case COFF_SYMBOL_UNDEFINED:
 	      flags = 0;
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.328
diff -u -p -r1.328 elf-bfd.h
--- bfd/elf-bfd.h	5 Aug 2011 03:17:11 -0000	1.328
+++ bfd/elf-bfd.h	11 Aug 2011 06:23:39 -0000
@@ -1801,9 +1801,8 @@ extern bfd_boolean _bfd_elf_match_sectio
   (bfd *, const asection *, bfd *, const asection *);
 extern bfd_boolean bfd_elf_is_group_section
   (bfd *, const struct bfd_section *);
-struct already_linked;
 extern bfd_boolean _bfd_elf_section_already_linked
-  (bfd *, struct already_linked *, struct bfd_link_info *);
+  (bfd *, asection *, struct bfd_link_info *);
 extern void bfd_elf_set_group_contents
   (bfd *, asection *, void *);
 extern asection *_bfd_elf_check_kept_section
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.417
diff -u -p -r1.417 elflink.c
--- bfd/elflink.c	5 Aug 2011 03:17:11 -0000	1.417
+++ bfd/elflink.c	11 Aug 2011 06:23:45 -0000
@@ -12517,95 +12517,64 @@ section_signature (asection *sec)
 
 bfd_boolean
 _bfd_elf_section_already_linked (bfd *abfd,
-				 struct already_linked *linked,
+				 asection *sec,
 				 struct bfd_link_info *info)
 {
   flagword flags;
   const char *name, *p;
   struct bfd_section_already_linked *l;
   struct bfd_section_already_linked_hash_entry *already_linked_list;
-  asection *sec, *l_sec;
-  bfd_boolean matched;
 
-  p = name = linked->comdat_key;
-  if (name)
-    {
-      sec = NULL;
-      flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
-    }
+  if (sec->output_section == bfd_abs_section_ptr)
+    return FALSE;
+
+  flags = sec->flags;
+
+  /* Return if it isn't a linkonce section.  A comdat group section
+     also has SEC_LINK_ONCE set.  */
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return FALSE;
+
+  /* Don't put group member sections on our list of already linked
+     sections.  They are handled as a group via their group section.  */
+  if (elf_sec_group (sec) != NULL)
+    return FALSE;
+
+  /* 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 = section_signature (sec);
+
+  if (CONST_STRNEQ (name, ".gnu.linkonce.")
+      && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+    p++;
   else
-    {
-      sec = linked->u.sec;
-      if (sec->output_section == bfd_abs_section_ptr)
-	return FALSE;
-
-      flags = sec->flags;
-
-      /* Return if it isn't a linkonce section.  A comdat group section
-	 also has SEC_LINK_ONCE set.  */
-      if ((flags & SEC_LINK_ONCE) == 0)
-	return FALSE;
-
-      /* Don't put group member sections on our list of already linked
-	 sections.  They are handled as a group via their group section.
-	 */
-      if (elf_sec_group (sec) != NULL)
-	return FALSE;
-
-      /* 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 = section_signature (sec);
-
-      if (CONST_STRNEQ (name, ".gnu.linkonce.")
-	  && ((p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.'))
-	      != NULL))
-	p++;
-      else
-	p = name;
-    }
+    p = name;
 
   already_linked_list = bfd_section_already_linked_table_lookup (p);
 
   for (l = already_linked_list->entry; l != NULL; l = l->next)
     {
-      flagword l_flags;
-      bfd *l_owner;
-      const char *l_name = l->linked.comdat_key;
-      if (l_name)
-	{
-	  l_sec = NULL;
-	  l_owner = l->linked.u.abfd;
-	  l_flags = (SEC_GROUP
-		     | SEC_LINK_ONCE
-		     | SEC_LINK_DUPLICATES_DISCARD);
-	}
-      else
-	{
-	  l_sec = l->linked.u.sec;
-	  l_owner = l_sec->owner;
-	  l_flags = l_sec->flags;
-	  l_name = section_signature (l_sec);
-	}
-
       /* We may have 2 different types of sections on the list: group
-	 sections and linkonce sections.  Match like sections.  */
-      if ((flags & SEC_GROUP) == (l_flags & SEC_GROUP)
-	  && strcmp (name, l_name) == 0)
+	 sections and linkonce sections.  Match like sections, but
+	 plugin sections match both types.  */
+      if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+	   || (l->sec->owner->flags & BFD_PLUGIN) != 0)
+	  && strcmp (name, section_signature (l->sec)) == 0)
 	{
 	  /* The section has already been linked.  See if we should
 	     issue a warning.  */
@@ -12622,9 +12591,9 @@ _bfd_elf_section_already_linked (bfd *ab
 		 mix of LTO and normal objects and we must keep the
 		 first match, be it IR or real.  */
 	      if (info->loading_lto_outputs
-		  && (l_owner->flags & BFD_PLUGIN) != 0)
+		  && (l->sec->owner->flags & BFD_PLUGIN) != 0)
 		{
-		  l->linked = *linked;
+		  l->sec = sec;
 		  return FALSE;
 		}
 	      break;
@@ -12636,20 +12605,18 @@ _bfd_elf_section_already_linked (bfd *ab
 	      break;
 
 	    case SEC_LINK_DUPLICATES_SAME_SIZE:
-	      if (!sec || !l_sec)
-		abort ();
-
-	      if (sec->size != l_sec->size)
+	      if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
+		;
+	      else if (sec->size != l->sec->size)
 		(*_bfd_error_handler)
 		  (_("%B: duplicate section `%A' has different size"),
 		   abfd, sec);
 	      break;
 
 	    case SEC_LINK_DUPLICATES_SAME_CONTENTS:
-	      if (!sec || !l_sec)
-		abort ();
-
-	      if (sec->size != l_sec->size)
+	      if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
+		;
+	      else if (sec->size != l->sec->size)
 		(*_bfd_error_handler)
 		  (_("%B: duplicate section `%A' has different size"),
 		   abfd, sec);
@@ -12661,11 +12628,11 @@ _bfd_elf_section_already_linked (bfd *ab
 		    (*_bfd_error_handler)
 		      (_("%B: warning: could not read contents of section `%A'"),
 		       abfd, sec);
-		  else if (!bfd_malloc_and_get_section (l_sec->owner, l_sec,
+		  else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
 							&l_sec_contents))
 		    (*_bfd_error_handler)
 		      (_("%B: warning: could not read contents of section `%A'"),
-		       l_sec->owner, l_sec);
+		       l->sec->owner, l->sec);
 		  else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
 		    (*_bfd_error_handler)
 		      (_("%B: warning: duplicate section `%A' has different contents"),
@@ -12679,31 +12646,28 @@ _bfd_elf_section_already_linked (bfd *ab
 	      break;
 	    }
 
-	  if (sec)
+	  /* 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)
 	    {
-	      /* 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;
+	      asection *first = elf_next_in_group (sec);
+	      asection *s = first;
 
-	      if (flags & SEC_GROUP)
+	      while (s != NULL)
 		{
-		  asection *first = elf_next_in_group (sec);
-		  asection *s = first;
-
-		  while (s != NULL)
-		    {
-		      s->output_section = bfd_abs_section_ptr;
-		      /* Record which group discards it.  */
-		      s->kept_section = l_sec;
-		      s = elf_next_in_group (s);
-		      /* These lists are circular.  */
-		      if (s == first)
-			break;
-		    }
+		  s->output_section = bfd_abs_section_ptr;
+		  /* Record which group discards it.  */
+		  s->kept_section = l->sec;
+		  s = elf_next_in_group (s);
+		  /* These lists are circular.  */
+		  if (s == first)
+		    break;
 		}
 	    }
 
@@ -12711,108 +12675,67 @@ _bfd_elf_section_already_linked (bfd *ab
 	}
     }
 
-  matched = FALSE;
-  if (sec)
+  /* A single member comdat group section may be discarded by a
+     linkonce section and vice versa.  */
+  if ((flags & SEC_GROUP) != 0)
     {
-      /* A single member comdat group section may be discarded by a
-	 linkonce section and vice versa.  */
+      asection *first = elf_next_in_group (sec);
 
-      if ((flags & SEC_GROUP) != 0)
+      if (first != NULL && elf_next_in_group (first) == first)
+	/* Check this single member group against linkonce sections.  */
+	for (l = already_linked_list->entry; l != NULL; l = l->next)
+	  if ((l->sec->flags & SEC_GROUP) == 0
+	      && bfd_elf_match_symbols_in_sections (l->sec, first, info))
+	    {
+	      first->output_section = bfd_abs_section_ptr;
+	      first->kept_section = l->sec;
+	      sec->output_section = bfd_abs_section_ptr;
+	      break;
+	    }
+    }
+  else
+    /* Check this linkonce section against single member groups.  */
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if (l->sec->flags & SEC_GROUP)
 	{
-	  asection *first = elf_next_in_group (sec);
+	  asection *first = elf_next_in_group (l->sec);
 
-	  if (first != NULL && elf_next_in_group (first) == first)
-	    /* Check this single member group against linkonce sections.  */
-	    for (l = already_linked_list->entry; l != NULL; l = l->next)
-	      {
-		if (l->linked.comdat_key == NULL)
-		  {
-		    l_sec = l->linked.u.sec;
-
-		    if ((l_sec->flags & SEC_GROUP) == 0
-			&& bfd_coff_get_comdat_section (l_sec->owner,
-							l_sec) == NULL
-			&& bfd_elf_match_symbols_in_sections (l_sec,
-							      first,
-							      info))
-		      {
-			first->output_section = bfd_abs_section_ptr;
-			first->kept_section = l_sec;
-			sec->output_section = bfd_abs_section_ptr;
-			matched = TRUE;
-			break;
-		      }
-		  }
-	      }
+	  if (first != NULL
+	      && elf_next_in_group (first) == first
+	      && bfd_elf_match_symbols_in_sections (first, sec, info))
+	    {
+	      sec->output_section = bfd_abs_section_ptr;
+	      sec->kept_section = first;
+	      break;
+	    }
 	}
-      else
-	/* Check this linkonce section against single member groups.  */
-	for (l = already_linked_list->entry; l != NULL; l = l->next)
-	  {
-	    if (l->linked.comdat_key == NULL)
-	      {
-		l_sec = l->linked.u.sec;
-
-		if (l_sec->flags & SEC_GROUP)
-		  {
-		    asection *first = elf_next_in_group (l_sec);
-
-		    if (first != NULL
-			&& elf_next_in_group (first) == first
-			&& bfd_elf_match_symbols_in_sections (first,
-							      sec,
-							      info))
-		      {
-			sec->output_section = bfd_abs_section_ptr;
-			sec->kept_section = first;
-			matched = TRUE;
-			break;
-		      }
-		  }
-	      }
-	  }
-
-      /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
-	 referencing its discarded `.gnu.linkonce.t.F' counterpart -
-	 g++-3.4 specific as g++-4.x is using COMDAT groups (without the
-	 `.gnu.linkonce' prefix) instead.  `.gnu.linkonce.r.*' were the
-	 `.rodata' part of its matching `.gnu.linkonce.t.*'.  If
-	 `.gnu.linkonce.r.F' is not discarded but its `.gnu.linkonce.t.F'
-	 is discarded means we chose one-only `.gnu.linkonce.t.F' section
-	 from a different bfd not requiring any `.gnu.linkonce.r.F'.
-	 Thus `.gnu.linkonce.r.F' should be discarded.  The reverse order
-	 cannot happen as there is never a bfd with only the
-	 `.gnu.linkonce.r.F' section.  The order of sections in a bfd
-	 does not matter as here were are looking only for cross-bfd
-	 sections.  */
 
-      if ((flags & SEC_GROUP) == 0
-	  && CONST_STRNEQ (name, ".gnu.linkonce.r."))
-	for (l = already_linked_list->entry; l != NULL; l = l->next)
-	  {
-	    if (l->linked.comdat_key == NULL)
-	      {
-		l_sec = l->linked.u.sec;
-
-		if ((l_sec->flags & SEC_GROUP) == 0
-		    && CONST_STRNEQ (l_sec->name, ".gnu.linkonce.t."))
-		  {
-		    if (abfd != l_sec->owner)
-		      {
-			sec->output_section = bfd_abs_section_ptr;
-			matched = TRUE;
-		      }
-		    break;
-		  }
-	      }
-	  }
-    }
+  /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
+     referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
+     specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
+     prefix) instead.  `.gnu.linkonce.r.*' were the `.rodata' part of its
+     matching `.gnu.linkonce.t.*'.  If `.gnu.linkonce.r.F' is not discarded
+     but its `.gnu.linkonce.t.F' is discarded means we chose one-only
+     `.gnu.linkonce.t.F' section from a different bfd not requiring any
+     `.gnu.linkonce.r.F'.  Thus `.gnu.linkonce.r.F' should be discarded.
+     The reverse order cannot happen as there is never a bfd with only the
+     `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
+     matter as here were are looking only for cross-bfd sections.  */
+
+  if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if ((l->sec->flags & SEC_GROUP) == 0
+	  && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
+	{
+	  if (abfd != l->sec->owner)
+	    sec->output_section = bfd_abs_section_ptr;
+	  break;
+	}
 
   /* This is the first section with this name.  Record it.  */
-  if (! bfd_section_already_linked_table_insert (already_linked_list,
-						 linked))
+  if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
     info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
-  return matched;
+  return sec->output_section == bfd_abs_section_ptr;
 }
 
 bfd_boolean
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.91
diff -u -p -r1.91 libbfd-in.h
--- bfd/libbfd-in.h	5 Aug 2011 03:17:11 -0000	1.91
+++ bfd/libbfd-in.h	11 Aug 2011 06:23:50 -0000
@@ -3,7 +3,7 @@
 
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010
+   2010, 2011
    Free Software Foundation, Inc.
 
    Written by Cygnus Support.
@@ -481,7 +481,7 @@ extern bfd_boolean _bfd_generic_set_sect
 #define _bfd_nolink_bfd_link_split_section \
   ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
 #define _bfd_nolink_section_already_linked \
-  ((bfd_boolean (*) (bfd *, struct already_linked*, \
+  ((bfd_boolean (*) (bfd *, asection *, \
 		     struct bfd_link_info *)) bfd_false)
 #define _bfd_nolink_bfd_define_common_symbol \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
@@ -603,7 +603,7 @@ extern bfd_boolean _bfd_generic_link_spl
   (bfd *, struct bfd_section *);
 
 extern bfd_boolean _bfd_generic_section_already_linked
-  (bfd *, struct already_linked *, struct bfd_link_info *);
+  (bfd *, asection *, struct bfd_link_info *);
 
 /* Generic reloc_link_order processing routine.  */
 extern bfd_boolean _bfd_generic_reloc_link_order
@@ -795,26 +795,16 @@ struct bfd_section_already_linked_hash_e
   struct bfd_section_already_linked *entry;
 };
 
-struct already_linked
-{
-  const char *comdat_key;
-  union
-    {
-      asection *sec;
-      bfd *abfd;
-    } u;
-};
-
 struct bfd_section_already_linked
 {
   struct bfd_section_already_linked *next;
-  struct already_linked linked;
+  asection *sec;
 };
 
 extern struct bfd_section_already_linked_hash_entry *
   bfd_section_already_linked_table_lookup (const char *);
 extern bfd_boolean bfd_section_already_linked_table_insert
-  (struct bfd_section_already_linked_hash_entry *, struct already_linked *);
+  (struct bfd_section_already_linked_hash_entry *, asection *);
 extern void bfd_section_already_linked_table_traverse
   (bfd_boolean (*) (struct bfd_section_already_linked_hash_entry *,
 		    void *), void *);
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.88
diff -u -p -r1.88 linker.c
--- bfd/linker.c	5 Aug 2011 03:17:11 -0000	1.88
+++ bfd/linker.c	11 Aug 2011 06:23:51 -0000
@@ -2889,15 +2889,15 @@ FUNCTION
 
 SYNOPSIS
         bfd_boolean bfd_section_already_linked (bfd *abfd,
-						struct already_linked *data,
+						asection *sec,
 						struct bfd_link_info *info);
 
 DESCRIPTION
 	Check if @var{data} has been already linked during a reloceatable
 	or final link.  Return TRUE if it has.
 
-.#define bfd_section_already_linked(abfd, data, info) \
-.       BFD_SEND (abfd, _section_already_linked, (abfd, data, info))
+.#define bfd_section_already_linked(abfd, sec, info) \
+.       BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
 .
 
 */
@@ -2940,7 +2940,7 @@ bfd_section_already_linked_table_lookup 
 bfd_boolean
 bfd_section_already_linked_table_insert
   (struct bfd_section_already_linked_hash_entry *already_linked_list,
-   struct already_linked *data)
+   asection *sec)
 {
   struct bfd_section_already_linked *l;
 
@@ -2950,7 +2950,7 @@ bfd_section_already_linked_table_insert
       bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
   if (l == NULL)
     return FALSE;
-  l->linked = *data;
+  l->sec = sec;
   l->next = already_linked_list->entry;
   already_linked_list->entry = l;
   return TRUE;
@@ -2992,7 +2992,7 @@ bfd_section_already_linked_table_free (v
 
 bfd_boolean
 _bfd_generic_section_already_linked (bfd *abfd,
-				     struct already_linked *linked,
+				     asection *sec,
 				     struct bfd_link_info *info)
 {
   flagword flags;
@@ -3000,64 +3000,35 @@ _bfd_generic_section_already_linked (bfd
   struct bfd_section_already_linked *l;
   struct bfd_section_already_linked_hash_entry *already_linked_list;
   struct coff_comdat_info *s_comdat;
-  asection *sec;
 
-  name = linked->comdat_key;
-  if (name)
-    {
-      sec = NULL;
-      flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
-      s_comdat = NULL;
-    }
-  else
-    {
-      sec = linked->u.sec;
-      flags = sec->flags;
-      if ((flags & SEC_LINK_ONCE) == 0)
-	return FALSE;
-
-      s_comdat = bfd_coff_get_comdat_section (abfd, sec);
-
-      /* 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.  */
+  flags = sec->flags;
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return FALSE;
 
-      name = bfd_get_section_name (abfd, sec);
-    }
+  /* 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);
+  s_comdat = bfd_coff_get_comdat_section (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;
-      bfd *l_owner;
-      flagword l_flags;
       struct coff_comdat_info *l_comdat;
-      asection *l_sec;
 
-      if (l->linked.comdat_key)
-	{
-	  l_sec = NULL;
-	  l_owner = l->linked.u.abfd;
-	  l_comdat = NULL;
-	  l_flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
-	}
-      else
-	{
-	  l_sec = l->linked.u.sec;
-	  l_owner = l_sec->owner;
-	  l_flags = l_sec->flags;
-	  l_comdat = bfd_coff_get_comdat_section (l_sec->owner, l_sec);
-	}
+      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
@@ -3066,7 +3037,7 @@ _bfd_generic_section_already_linked (bfd
 
 	 FIXME: Is that safe to match a linkonce section with a comdat
 	 section for COFF inputs?  */
-      if ((l_flags & SEC_GROUP) != 0)
+      if ((l->sec->flags & SEC_GROUP) != 0)
 	skip = TRUE;
       else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
 	{
@@ -3095,9 +3066,9 @@ _bfd_generic_section_already_linked (bfd
 		 mix of LTO and normal objects and we must keep the
 		 first match, be it IR or real.  */
 	      if (info->loading_lto_outputs
-		  && (l_owner->flags & BFD_PLUGIN) != 0)
+		  && (l->sec->owner->flags & BFD_PLUGIN) != 0)
 		{
-		  l->linked = *linked;
+		  l->sec = sec;
 		  return FALSE;
 		}
 	      break;
@@ -3116,31 +3087,29 @@ _bfd_generic_section_already_linked (bfd
                  either.  */
 	      /* Fall through.  */
 	    case SEC_LINK_DUPLICATES_SAME_SIZE:
-	      if (sec->size != l_sec->size)
+	      if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
+		;
+	      else if (sec->size != l->sec->size)
 		(*_bfd_error_handler)
 		  (_("%B: warning: duplicate section `%A' has different size\n"),
 		   abfd, sec);
 	      break;
 	    }
 
-	  if (sec)
-	    {
-	      /* 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;
-	    }
+	  /* 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 TRUE;
 	}
     }
 
   /* This is the first section with this name.  Record it.  */
-  if (! bfd_section_already_linked_table_insert (already_linked_list,
-						 linked))
+  if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
     info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
   return FALSE;
 }
Index: bfd/targets.c
===================================================================
RCS file: /cvs/src/src/bfd/targets.c,v
retrieving revision 1.207
diff -u -p -r1.207 targets.c
--- bfd/targets.c	5 Aug 2011 03:17:11 -0000	1.207
+++ bfd/targets.c	11 Aug 2011 06:23:52 -0000
@@ -176,7 +176,6 @@ DESCRIPTION
 .
 .{* Forward declaration.  *}
 .typedef struct bfd_link_info _bfd_link_info;
-.struct already_linked;
 .
 .{* Forward declaration.  *}
 .typedef struct flag_info flag_info;
@@ -512,7 +511,7 @@ BFD_JUMP_TABLE macros.
 .
 .  {* Check if SEC has been already linked during a reloceatable or
 .     final link.  *}
-.  bfd_boolean (*_section_already_linked) (bfd *, struct already_linked *,
+.  bfd_boolean (*_section_already_linked) (bfd *, asection *,
 .					   struct bfd_link_info *);
 .
 .  {* Define a common symbol.  *}
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.375
diff -u -p -r1.375 ldlang.c
--- ld/ldlang.c	16 Jul 2011 07:58:40 -0000	1.375
+++ ld/ldlang.c	11 Aug 2011 06:24:21 -0000
@@ -2240,12 +2240,7 @@ section_already_linked (bfd *abfd, asect
     }
 
   if (!(abfd->flags & DYNAMIC))
-    {
-      struct already_linked linked;
-      linked.comdat_key = NULL;
-      linked.u.sec = sec;
-      bfd_section_already_linked (abfd, &linked, &link_info);
-    }
+    bfd_section_already_linked (abfd, sec, &link_info);
 }
 \f
 /* The wild routines.
Index: ld/plugin.c
===================================================================
RCS file: /cvs/src/src/ld/plugin.c,v
retrieving revision 1.38
diff -u -p -r1.38 plugin.c
--- ld/plugin.c	9 Aug 2011 09:27:34 -0000	1.38
+++ ld/plugin.c	11 Aug 2011 06:24:21 -0000
@@ -32,7 +32,6 @@
 #include "plugin.h"
 #include "plugin-api.h"
 #include "elf-bfd.h"
-#include "libbfd.h"
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 #include <windows.h>
 #endif
@@ -240,7 +239,7 @@ plugin_get_ir_dummy_bfd (const char *nam
 	{
 	  flagword flags;
 
-	  /* Create sections to own the symbols.  */
+	  /* Create section to own the symbols.  */
 	  flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
 		   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
 	  if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
@@ -285,7 +284,25 @@ asymbol_from_plugin_symbol (bfd *abfd, a
       /* FALLTHRU */
     case LDPK_DEF:
       flags |= BSF_GLOBAL;
-      section = bfd_get_section_by_name (abfd, ".text");
+      if (ldsym->comdat_key)
+	{
+	  section = bfd_get_section_by_name (abfd, ldsym->comdat_key);
+	  if (section == NULL)
+	    {
+	      flagword sflags;
+
+	      sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
+			| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
+			| SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
+	      section = bfd_make_section_anyway_with_flags (abfd,
+							    xstrdup (ldsym->comdat_key),
+							    sflags);
+	      if (section == NULL)
+		return LDPS_ERR;
+	    }
+	}
+      else
+	section = bfd_get_section_by_name (abfd, ".text");
       break;
 
     case LDPK_WEAKUNDEF:
@@ -389,13 +406,6 @@ add_symbols (void *handle, int nsyms, co
       enum ld_plugin_status rv;
       asymbol *bfdsym;
 
-      if (syms[n].comdat_key)
-	{
-	  struct already_linked linked;
-	  linked.comdat_key = xstrdup (syms[n].comdat_key);
-	  linked.u.abfd = abfd;
-	  bfd_section_already_linked (abfd, &linked, &link_info);
-	}
       bfdsym = bfd_make_empty_symbol (abfd);
       symptrs[n] = bfdsym;
       rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 13:08 Fix PR12762 using linkonce sections in plugin bfd Alan Modra
@ 2011-08-11 13:18 ` H.J. Lu
  2011-08-11 14:04   ` Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-11 13:18 UTC (permalink / raw)
  To: binutils

On Thu, Aug 11, 2011 at 6:08 AM, Alan Modra <amodra@gmail.com> wrote:
> This patch undoes HJ's changes to bfd_section_already_linked in
> http://sourceware.org/ml/binutils/2011-07/msg00070.html, and some of
> my later changes.  HJ's patch effectively added another type of entry
> to the already_linked list for plugin comdat symbols.  This works fine
> most of the time, but there are parts of the bfd and linker code that
> really want separate sections for comdat symbols.  For example,
> ldmain.c:multiple_definition just after the FIXME comment.  So
> this patch simply provides dummy linkonce sections for plugin comdat
> symbols.
>
> Ironically, the FIXME advocates doing exactly what we were attempting
> in plugin.c:add_symbols, so in some respects this patch is a backwards
> step.  It also uses more memory.  The reason I didn't apply further
> tweaks like the patch in PR13066 is that bfd_section_already_linked
> was getting quite messy.  If we are going to go the way this FIXME
> suggests then we really aught to do so for all symbols, not just
> plugin symbols.  I'd like to see that happen but don't have time at
> the moment to fix all the fallout.
>

> Index: ld/plugin.c
> ===================================================================
> RCS file: /cvs/src/src/ld/plugin.c,v
> retrieving revision 1.38
> diff -u -p -r1.38 plugin.c
> --- ld/plugin.c 9 Aug 2011 09:27:34 -0000       1.38
> +++ ld/plugin.c 11 Aug 2011 06:24:21 -0000
> @@ -32,7 +32,6 @@
>  #include "plugin.h"
>  #include "plugin-api.h"
>  #include "elf-bfd.h"
> -#include "libbfd.h"
>  #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
>  #include <windows.h>
>  #endif
> @@ -240,7 +239,7 @@ plugin_get_ir_dummy_bfd (const char *nam
>        {
>          flagword flags;
>
> -         /* Create sections to own the symbols.  */
> +         /* Create section to own the symbols.  */
>          flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
>                   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
>          if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
> @@ -285,7 +284,25 @@ asymbol_from_plugin_symbol (bfd *abfd, a
>       /* FALLTHRU */
>     case LDPK_DEF:
>       flags |= BSF_GLOBAL;
> -      section = bfd_get_section_by_name (abfd, ".text");
> +      if (ldsym->comdat_key)
> +       {
> +         section = bfd_get_section_by_name (abfd, ldsym->comdat_key);
> +         if (section == NULL)
> +           {
> +             flagword sflags;
> +
> +             sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
> +                       | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
> +                       | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
> +             section = bfd_make_section_anyway_with_flags (abfd,
> +                                                           xstrdup (ldsym->comdat_key),
> +                                                           sflags);
> +             if (section == NULL)
> +               return LDPS_ERR;
> +           }
> +       }
> +      else
> +       section = bfd_get_section_by_name (abfd, ".text");
>       break;
>

This is the first approach I tried and failed with GCC 4.7 LTO
tests on Linux/x86-64 since adding new sections to dummy
LTO bfd at this stage didn't work very well.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 13:18 ` H.J. Lu
@ 2011-08-11 14:04   ` Alan Modra
  2011-08-11 14:40     ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2011-08-11 14:04 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Thu, Aug 11, 2011 at 06:18:03AM -0700, H.J. Lu wrote:
> This is the first approach I tried and failed with GCC 4.7 LTO
> tests on Linux/x86-64 since adding new sections to dummy
> LTO bfd at this stage didn't work very well.

Current mainline gcc bootstrap and regression tests look good on
powerpc.  What is peculiar about x86-64?  Can you test my patch and
let me know what fails?  I'll wait to hear back before applying.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 14:04   ` Alan Modra
@ 2011-08-11 14:40     ` H.J. Lu
  2011-08-11 14:57       ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-11 14:40 UTC (permalink / raw)
  To: Binutils

On Thu, Aug 11, 2011 at 7:04 AM, Alan Modra <amodra@gmail.com> wrote:
> On Thu, Aug 11, 2011 at 06:18:03AM -0700, H.J. Lu wrote:
>> This is the first approach I tried and failed with GCC 4.7 LTO
>> tests on Linux/x86-64 since adding new sections to dummy
>> LTO bfd at this stage didn't work very well.
>
> Current mainline gcc bootstrap and regression tests look good on
> powerpc.  What is peculiar about x86-64?  Can you test my patch and
> let me know what fails?  I'll wait to hear back before applying.
>

I will start test.


-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 14:40     ` H.J. Lu
@ 2011-08-11 14:57       ` H.J. Lu
  2011-08-11 15:08         ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-11 14:57 UTC (permalink / raw)
  To: Binutils

On Thu, Aug 11, 2011 at 7:40 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Aug 11, 2011 at 7:04 AM, Alan Modra <amodra@gmail.com> wrote:
>> On Thu, Aug 11, 2011 at 06:18:03AM -0700, H.J. Lu wrote:
>>> This is the first approach I tried and failed with GCC 4.7 LTO
>>> tests on Linux/x86-64 since adding new sections to dummy
>>> LTO bfd at this stage didn't work very well.
>>
>> Current mainline gcc bootstrap and regression tests look good on
>> powerpc.  What is peculiar about x86-64?  Can you test my patch and
>> let me know what fails?  I'll wait to hear back before applying.
>>
>
> I will start test.

It failed testcase in

http://sourceware.org/bugzilla/show_bug.cgi?id=12942

with GCC 4.7 on Linux/x86-64.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 14:57       ` H.J. Lu
@ 2011-08-11 15:08         ` H.J. Lu
  2011-08-12  3:46           ` Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-11 15:08 UTC (permalink / raw)
  To: Binutils

On Thu, Aug 11, 2011 at 7:56 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Aug 11, 2011 at 7:40 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Thu, Aug 11, 2011 at 7:04 AM, Alan Modra <amodra@gmail.com> wrote:
>>> On Thu, Aug 11, 2011 at 06:18:03AM -0700, H.J. Lu wrote:
>>>> This is the first approach I tried and failed with GCC 4.7 LTO
>>>> tests on Linux/x86-64 since adding new sections to dummy
>>>> LTO bfd at this stage didn't work very well.
>>>
>>> Current mainline gcc bootstrap and regression tests look good on
>>> powerpc.  What is peculiar about x86-64?  Can you test my patch and
>>> let me know what fails?  I'll wait to hear back before applying.
>>>
>>
>> I will start test.
>
> It failed testcase in
>
> http://sourceware.org/bugzilla/show_bug.cgi?id=12942
>
> with GCC 4.7 on Linux/x86-64.

I put your change on hjl/lto/pr12762 branch at

http://git.kernel.org/?p=devel/binutils/hjl/x86.git;a=summary

When compiling with GCC 4.7, I got

Executing on host: sh -c {/usr/gcc-4.7.0-x32/bin/g++
-B/export/build/gnu/binutils-lto/build-x86_64-linux/ld/tmpdir/ld/
-L/usr/local/x86_64-unknown-linux-gnu/lib64 -L/usr/local/lib64
-L/lib64 -L/usr/lib64 -L/usr/local/x86_64-unknown-linux-gnu/lib
-L/usr/local/lib -L/lib -L/usr/lib   -o tmpdir/pr12942a.exe
-L/export/gnu/import/git/binutils-lto/ld/testsuite/ld-plugin -O2 -flto
-fuse-linker-plugin tmpdir/pr12942a.o tmpdir/pr12942b.o tmpdir/dummy.o
2>&1}  /dev/null ld.tmp (timeout = 300)
spawn [open ...]^M
tmpdir/pr12942b.o: In function `test()':
/export/gnu/import/git/binutils-lto/ld/testsuite/ld-plugin/pr12942a.h:7:
undefined reference to `link_error()'
collect2: error: ld returned 1 exit status
tmpdir/pr12942b.o: In function `test()':
/export/gnu/import/git/binutils-lto/ld/testsuite/ld-plugin/pr12942a.h:7:
undefined reference to `link_error()'
collect2: error: ld returned 1 exit status
FAIL: PR ld/12942 (1)


-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-11 15:08         ` H.J. Lu
@ 2011-08-12  3:46           ` Alan Modra
  2011-08-13  9:59             ` Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2011-08-12  3:46 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Thu, Aug 11, 2011 at 08:07:43AM -0700, H.J. Lu wrote:
> FAIL: PR ld/12942 (1)

Sigh.  Yes, we do need to set up the already_linked list on the first
pass for lto objects.  It wasn't working simply because the linkonce
attribute doesn't make it through bfd_make_readable().  I have a patch
that works on the testcase, but I'll do a gcc bootstrap and regression
test before inflicting it on you.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-12  3:46           ` Alan Modra
@ 2011-08-13  9:59             ` Alan Modra
  2011-08-13 14:31               ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2011-08-13  9:59 UTC (permalink / raw)
  To: H.J. Lu, Binutils; +Cc: Nick Clifton

Revised patch.  This one gives the plugin comdat_key symbols sections
named .gnu.linkonce.t.<comdat_key>, so that SEC_LINK_ONCE gets set for
the sections when recreating them during bfd_make_readable().

I've also given the COFF backend its own bfd_section_already_linked
and tidied the existing bfd_section_already_linked functions.  I'd
appreciate someone familiar with our COFF support reviewing
_bfd_coff_section_already_linked in case I've made some glaring
mistakes..  The old code basically matched on section name, but if
both sections had a comdat symbol then the symbols had to match too.
That meant a comdat section could match a non-comdat section with the
same name, something the new code specifically disallows, and anyway
is a side-effect of hashing on the comdat key.  COFF also gets the
benefit of the ELF code for SEC_LINK_DUPLICATES_SAME_CONTENTS, so
section contents are actually checked now.

bfd/
	PR ld/12762
	* bfd-in.h (struct bfd_section_already_linked): Forward declare.
	(_bfd_handle_already_linked): Declare.
	* coff-alpha.c (_bfd_ecoff_section_already_linked): Define as
	_bfd_coff_section_already_linked.
	* coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
	* coffcode.h (coff_section_already_linked): Likewise.
	* cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
	* elf-bfd.h: Likewise.
	* libbfd-in.h: Likewise.
	* targets.c: Likewise.
	* linker.c (bfd_section_already_linked): Likewise.
	(bfd_section_already_linked_table_lookup): Likewise.
	(bfd_section_already_linked_table_insert): Likewise.
	(_bfd_generic_section_already_linked): Likewise.  Call
	_bfd_handle_already_linked.
	(_bfd_handle_already_linked): New function, split out from..
	* elflink.c (_bfd_elf_section_already_linked): ..here.  Revert
	2011-07-09 changes.  Avoid unnecessary strcmp when matching
	already_linked_list entries.  Match plugin linkonce section.
	(section_signature): Delete.
	* coffgen.c (_bfd_coff_section_already_linked): New function.
	* libcoff-in.h (_bfd_coff_section_already_linked): Declare.
	* libbfd.h: Regenerate.
	* libcoff.h: Regenerate.
	* bfd-in2.h: Regenerate.
ld/
	PR ld/12762
	* ldlang.c (section_already_linked): Revert 2011-07-09 changes.
	* plugin.c: Likewise.
	(asymbol_from_plugin_symbol): Create linkonce section for syms
	with comdat_key.

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.156
diff -u -p -r1.156 bfd-in.h
--- bfd/bfd-in.h	9 Aug 2011 13:10:43 -0000	1.156
+++ bfd/bfd-in.h	12 Aug 2011 23:56:06 -0000
@@ -552,11 +552,6 @@ 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);
-\f
-/* Externally visible ECOFF routines.  */
-
 #if defined(__STDC__) || defined(ALMOST_STDC)
 struct ecoff_debug_info;
 struct ecoff_debug_swap;
@@ -564,8 +559,18 @@ struct ecoff_extr;
 struct bfd_symbol;
 struct bfd_link_info;
 struct bfd_link_hash_entry;
+struct bfd_section_already_linked;
 struct bfd_elf_version_tree;
 #endif
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
+extern bfd_boolean _bfd_handle_already_linked
+  (struct bfd_section *, struct bfd_section_already_linked *,
+   struct bfd_link_info *);
+\f
+/* Externally visible ECOFF routines.  */
+
 extern bfd_vma bfd_ecoff_get_gp_value
   (bfd * abfd);
 extern bfd_boolean bfd_ecoff_set_gp_value
Index: bfd/coff-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-alpha.c,v
retrieving revision 1.47
diff -u -p -r1.47 coff-alpha.c
--- bfd/coff-alpha.c	11 Jul 2011 15:03:04 -0000	1.47
+++ bfd/coff-alpha.c	12 Aug 2011 23:56:09 -0000
@@ -2403,7 +2403,7 @@ static const struct ecoff_backend_data a
 #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
+  _bfd_coff_section_already_linked
 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
 
 const bfd_target ecoffalpha_little_vec =
Index: bfd/coff-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-mips.c,v
retrieving revision 1.40
diff -u -p -r1.40 coff-mips.c
--- bfd/coff-mips.c	11 Jul 2011 15:03:04 -0000	1.40
+++ bfd/coff-mips.c	12 Aug 2011 23:56:09 -0000
@@ -1419,7 +1419,7 @@ 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
+  _bfd_coff_section_already_linked
 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
 
 extern const bfd_target ecoff_big_vec;
Index: bfd/coffcode.h
===================================================================
RCS file: /cvs/src/src/bfd/coffcode.h,v
retrieving revision 1.180
diff -u -p -r1.180 coffcode.h
--- bfd/coffcode.h	11 Jul 2011 15:03:04 -0000	1.180
+++ bfd/coffcode.h	12 Aug 2011 23:56:11 -0000
@@ -5670,7 +5670,7 @@ static bfd_coff_backend_data ticoff1_swa
 
 #ifndef coff_section_already_linked
 #define coff_section_already_linked \
-  _bfd_generic_section_already_linked
+  _bfd_coff_section_already_linked
 #endif
 
 #ifndef coff_bfd_define_common_symbol
Index: bfd/cofflink.c
===================================================================
RCS file: /cvs/src/src/bfd/cofflink.c,v
retrieving revision 1.78
diff -u -p -r1.78 cofflink.c
--- bfd/cofflink.c	9 Jul 2011 06:20:50 -0000	1.78
+++ bfd/cofflink.c	12 Aug 2011 23:56:13 -0000
@@ -392,11 +392,7 @@ coff_link_add_symbols (bfd *abfd,
 	      section = coff_section_from_bfd_index (abfd, sym.n_scnum);
 	      if (! obj_pe (abfd))
 		value -= section->vma;
-	      /* Treat a symbol from a discarded section as undefined.  */
-	      if (bfd_is_abs_section (section)
-		  || !bfd_is_abs_section (section->output_section))
-		break;
-	      /* Fall thru */
+	      break;
 
 	    case COFF_SYMBOL_UNDEFINED:
 	      flags = 0;
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.328
diff -u -p -r1.328 elf-bfd.h
--- bfd/elf-bfd.h	5 Aug 2011 03:17:11 -0000	1.328
+++ bfd/elf-bfd.h	12 Aug 2011 23:56:14 -0000
@@ -1801,9 +1801,8 @@ extern bfd_boolean _bfd_elf_match_sectio
   (bfd *, const asection *, bfd *, const asection *);
 extern bfd_boolean bfd_elf_is_group_section
   (bfd *, const struct bfd_section *);
-struct already_linked;
 extern bfd_boolean _bfd_elf_section_already_linked
-  (bfd *, struct already_linked *, struct bfd_link_info *);
+  (bfd *, asection *, struct bfd_link_info *);
 extern void bfd_elf_set_group_contents
   (bfd *, asection *, void *);
 extern asection *_bfd_elf_check_kept_section
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.91
diff -u -p -r1.91 libbfd-in.h
--- bfd/libbfd-in.h	5 Aug 2011 03:17:11 -0000	1.91
+++ bfd/libbfd-in.h	12 Aug 2011 23:56:25 -0000
@@ -3,7 +3,7 @@
 
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010
+   2010, 2011
    Free Software Foundation, Inc.
 
    Written by Cygnus Support.
@@ -481,7 +481,7 @@ extern bfd_boolean _bfd_generic_set_sect
 #define _bfd_nolink_bfd_link_split_section \
   ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
 #define _bfd_nolink_section_already_linked \
-  ((bfd_boolean (*) (bfd *, struct already_linked*, \
+  ((bfd_boolean (*) (bfd *, asection *, \
 		     struct bfd_link_info *)) bfd_false)
 #define _bfd_nolink_bfd_define_common_symbol \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
@@ -603,7 +603,7 @@ extern bfd_boolean _bfd_generic_link_spl
   (bfd *, struct bfd_section *);
 
 extern bfd_boolean _bfd_generic_section_already_linked
-  (bfd *, struct already_linked *, struct bfd_link_info *);
+  (bfd *, asection *, struct bfd_link_info *);
 
 /* Generic reloc_link_order processing routine.  */
 extern bfd_boolean _bfd_generic_reloc_link_order
@@ -795,26 +795,16 @@ struct bfd_section_already_linked_hash_e
   struct bfd_section_already_linked *entry;
 };
 
-struct already_linked
-{
-  const char *comdat_key;
-  union
-    {
-      asection *sec;
-      bfd *abfd;
-    } u;
-};
-
 struct bfd_section_already_linked
 {
   struct bfd_section_already_linked *next;
-  struct already_linked linked;
+  asection *sec;
 };
 
 extern struct bfd_section_already_linked_hash_entry *
   bfd_section_already_linked_table_lookup (const char *);
 extern bfd_boolean bfd_section_already_linked_table_insert
-  (struct bfd_section_already_linked_hash_entry *, struct already_linked *);
+  (struct bfd_section_already_linked_hash_entry *, asection *);
 extern void bfd_section_already_linked_table_traverse
   (bfd_boolean (*) (struct bfd_section_already_linked_hash_entry *,
 		    void *), void *);
Index: bfd/libcoff-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libcoff-in.h,v
retrieving revision 1.43
diff -u -p -r1.43 libcoff-in.h
--- bfd/libcoff-in.h	13 Jun 2011 00:59:15 -0000	1.43
+++ bfd/libcoff-in.h	12 Aug 2011 23:56:25 -0000
@@ -546,6 +546,8 @@ extern struct bfd_link_hash_table *_bfd_
   (bfd *);
 extern const char *_bfd_coff_internal_syment_name
   (bfd *, const struct internal_syment *, char *);
+extern bfd_boolean _bfd_coff_section_already_linked
+  (bfd *, asection *, struct bfd_link_info *);
 extern bfd_boolean _bfd_coff_link_add_symbols
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean _bfd_coff_final_link
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.88
diff -c -p -r1.88 linker.c
*** bfd/linker.c	5 Aug 2011 03:17:11 -0000	1.88
--- bfd/linker.c	13 Aug 2011 06:21:45 -0000
*************** FUNCTION
*** 2889,2903 ****
  
  SYNOPSIS
          bfd_boolean bfd_section_already_linked (bfd *abfd,
! 						struct already_linked *data,
  						struct bfd_link_info *info);
  
  DESCRIPTION
  	Check if @var{data} has been already linked during a reloceatable
  	or final link.  Return TRUE if it has.
  
! .#define bfd_section_already_linked(abfd, data, info) \
! .       BFD_SEND (abfd, _section_already_linked, (abfd, data, info))
  .
  
  */
--- 2889,2903 ----
  
  SYNOPSIS
          bfd_boolean bfd_section_already_linked (bfd *abfd,
! 						asection *sec,
  						struct bfd_link_info *info);
  
  DESCRIPTION
  	Check if @var{data} has been already linked during a reloceatable
  	or final link.  Return TRUE if it has.
  
! .#define bfd_section_already_linked(abfd, sec, info) \
! .       BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
  .
  
  */
*************** bfd_section_already_linked_table_lookup 
*** 2940,2946 ****
  bfd_boolean
  bfd_section_already_linked_table_insert
    (struct bfd_section_already_linked_hash_entry *already_linked_list,
!    struct already_linked *data)
  {
    struct bfd_section_already_linked *l;
  
--- 2940,2946 ----
  bfd_boolean
  bfd_section_already_linked_table_insert
    (struct bfd_section_already_linked_hash_entry *already_linked_list,
!    asection *sec)
  {
    struct bfd_section_already_linked *l;
  
*************** bfd_section_already_linked_table_insert
*** 2950,2956 ****
        bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
    if (l == NULL)
      return FALSE;
!   l->linked = *data;
    l->next = already_linked_list->entry;
    already_linked_list->entry = l;
    return TRUE;
--- 2950,2956 ----
        bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
    if (l == NULL)
      return FALSE;
!   l->sec = sec;
    l->next = already_linked_list->entry;
    already_linked_list->entry = l;
    return TRUE;
*************** bfd_section_already_linked_table_free (v
*** 2988,3146 ****
    bfd_hash_table_free (&_bfd_section_already_linked_table);
  }
  
! /* This is used on non-ELF inputs.  */
  
  bfd_boolean
! _bfd_generic_section_already_linked (bfd *abfd,
! 				     struct already_linked *linked,
! 				     struct bfd_link_info *info)
  {
!   flagword flags;
!   const char *name;
!   struct bfd_section_already_linked *l;
!   struct bfd_section_already_linked_hash_entry *already_linked_list;
!   struct coff_comdat_info *s_comdat;
!   asection *sec;
! 
!   name = linked->comdat_key;
!   if (name)
      {
!       sec = NULL;
!       flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
!       s_comdat = NULL;
!     }
!   else
!     {
!       sec = linked->u.sec;
!       flags = sec->flags;
!       if ((flags & SEC_LINK_ONCE) == 0)
! 	return FALSE;
! 
!       s_comdat = bfd_coff_get_comdat_section (abfd, sec);
! 
!       /* 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;
!       bfd *l_owner;
!       flagword l_flags;
!       struct coff_comdat_info *l_comdat;
!       asection *l_sec;
! 
!       if (l->linked.comdat_key)
! 	{
! 	  l_sec = NULL;
! 	  l_owner = l->linked.u.abfd;
! 	  l_comdat = NULL;
! 	  l_flags = SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
! 	}
!       else
  	{
! 	  l_sec = l->linked.u.sec;
! 	  l_owner = l_sec->owner;
! 	  l_flags = l_sec->flags;
! 	  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_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:
! 	      /* If we found an LTO IR match for this comdat group on
! 		 the first pass, replace it with the LTO output on the
! 		 second pass.  We can't simply choose real object
! 		 files over IR because the first pass may contain a
! 		 mix of LTO and normal objects and we must keep the
! 		 first match, be it IR or real.  */
! 	      if (info->loading_lto_outputs
! 		  && (l_owner->flags & BFD_PLUGIN) != 0)
! 		{
! 		  l->linked = *linked;
! 		  return FALSE;
! 		}
! 	      break;
  
! 	    case SEC_LINK_DUPLICATES_ONE_ONLY:
! 	      (*_bfd_error_handler)
! 		(_("%B: warning: ignoring duplicate section `%A'\n"),
! 		 abfd, sec);
! 	      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)
! 		  (_("%B: warning: duplicate section `%A' has different size\n"),
! 		   abfd, sec);
! 	      break;
! 	    }
  
! 	  if (sec)
! 	    {
! 	      /* 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 TRUE;
! 	}
      }
  
    /* This is the first section with this name.  Record it.  */
!   if (! bfd_section_already_linked_table_insert (already_linked_list,
! 						 linked))
      info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
    return FALSE;
  }
--- 2988,3124 ----
    bfd_hash_table_free (&_bfd_section_already_linked_table);
  }
  
! /* Report warnings as appropriate for duplicate section SEC.
!    Return FALSE if we decide to keep SEC after all.  */
  
  bfd_boolean
! _bfd_handle_already_linked (asection *sec,
! 			    struct bfd_section_already_linked *l,
! 			    struct bfd_link_info *info)
  {
!   switch (sec->flags & SEC_LINK_DUPLICATES)
      {
!     default:
!       abort ();
  
!     case SEC_LINK_DUPLICATES_DISCARD:
!       /* If we found an LTO IR match for this comdat group on
! 	 the first pass, replace it with the LTO output on the
! 	 second pass.  We can't simply choose real object
! 	 files over IR because the first pass may contain a
! 	 mix of LTO and normal objects and we must keep the
! 	 first match, be it IR or real.  */
!       if (info->loading_lto_outputs
! 	  && (l->sec->owner->flags & BFD_PLUGIN) != 0)
  	{
! 	  l->sec = sec;
! 	  return FALSE;
  	}
+       break;
  
!     case SEC_LINK_DUPLICATES_ONE_ONLY:
!       info->callbacks->einfo
! 	(_("%B: ignoring duplicate section `%A'\n"),
! 	 sec->owner, sec);
!       break;
! 
!     case SEC_LINK_DUPLICATES_SAME_SIZE:
!       if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
! 	;
!       else if (sec->size != l->sec->size)
! 	info->callbacks->einfo
! 	  (_("%B: duplicate section `%A' has different size\n"),
! 	   sec->owner, sec);
!       break;
! 
!     case SEC_LINK_DUPLICATES_SAME_CONTENTS:
!       if ((l->sec->owner->flags & BFD_PLUGIN) != 0)
! 	;
!       else if (sec->size != l->sec->size)
! 	info->callbacks->einfo
! 	  (_("%B: duplicate section `%A' has different size\n"),
! 	   sec->owner, sec);
!       else if (sec->size != 0)
  	{
! 	  bfd_byte *sec_contents, *l_sec_contents = NULL;
! 
! 	  if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents))
! 	    info->callbacks->einfo
! 	      (_("%B: could not read contents of section `%A'\n"),
! 	       sec->owner, sec);
! 	  else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
! 						&l_sec_contents))
! 	    info->callbacks->einfo
! 	      (_("%B: could not read contents of section `%A'\n"),
! 	       l->sec->owner, l->sec);
! 	  else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
! 	    info->callbacks->einfo
! 	      (_("%B: duplicate section `%A' has different contents\n"),
! 	       sec->owner, sec);
! 
! 	  if (sec_contents)
! 	    free (sec_contents);
! 	  if (l_sec_contents)
! 	    free (l_sec_contents);
  	}
!       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 TRUE;
! }
  
! /* This is used on non-ELF inputs.  */
  
! bfd_boolean
! _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED,
! 				     asection *sec,
! 				     struct bfd_link_info *info)
! {
!   const char *name;
!   struct bfd_section_already_linked *l;
!   struct bfd_section_already_linked_hash_entry *already_linked_list;
  
!   if ((sec->flags & SEC_LINK_ONCE) == 0)
!     return FALSE;
  
!   /* The generic linker doesn't handle section groups.  */
!   if ((sec->flags & SEC_GROUP) != 0)
!     return FALSE;
  
!   /* 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);
! 
!   l = already_linked_list->entry;
!   if (l != NULL)
!     {
!       /* The section has already been linked.  See if we should
! 	 issue a warning.  */
!       return _bfd_handle_already_linked (sec, l, info);
      }
  
    /* This is the first section with this name.  Record it.  */
!   if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
      info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
    return FALSE;
  }
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.417
diff -c -p -r1.417 elflink.c
*** bfd/elflink.c	5 Aug 2011 03:17:11 -0000	1.417
--- bfd/elflink.c	13 Aug 2011 06:21:48 -0000
*************** bfd_elf_discard_info (bfd *output_bfd, s
*** 12502,12709 ****
    return ret;
  }
  
- /* For a SHT_GROUP section, return the group signature.  For other
-    sections, return the normal section name.  */
- 
- static const char *
- section_signature (asection *sec)
- {
-   if ((sec->flags & SEC_GROUP) != 0
-       && elf_next_in_group (sec) != NULL
-       && elf_group_name (elf_next_in_group (sec)) != NULL)
-     return elf_group_name (elf_next_in_group (sec));
-   return sec->name;
- }
- 
  bfd_boolean
  _bfd_elf_section_already_linked (bfd *abfd,
! 				 struct already_linked *linked,
  				 struct bfd_link_info *info)
  {
    flagword flags;
!   const char *name, *p;
    struct bfd_section_already_linked *l;
    struct bfd_section_already_linked_hash_entry *already_linked_list;
-   asection *sec, *l_sec;
-   bfd_boolean matched;
  
!   p = name = linked->comdat_key;
!   if (name)
!     {
!       sec = NULL;
!       flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
!     }
!   else
!     {
!       sec = linked->u.sec;
!       if (sec->output_section == bfd_abs_section_ptr)
! 	return FALSE;
! 
!       flags = sec->flags;
! 
!       /* Return if it isn't a linkonce section.  A comdat group section
! 	 also has SEC_LINK_ONCE set.  */
!       if ((flags & SEC_LINK_ONCE) == 0)
! 	return FALSE;
! 
!       /* Don't put group member sections on our list of already linked
! 	 sections.  They are handled as a group via their group section.
! 	 */
!       if (elf_sec_group (sec) != NULL)
! 	return FALSE;
! 
!       /* 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 = section_signature (sec);
  
        if (CONST_STRNEQ (name, ".gnu.linkonce.")
! 	  && ((p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.'))
! 	      != NULL))
! 	p++;
        else
! 	p = name;
      }
  
!   already_linked_list = bfd_section_already_linked_table_lookup (p);
  
    for (l = already_linked_list->entry; l != NULL; l = l->next)
      {
-       flagword l_flags;
-       bfd *l_owner;
-       const char *l_name = l->linked.comdat_key;
-       if (l_name)
- 	{
- 	  l_sec = NULL;
- 	  l_owner = l->linked.u.abfd;
- 	  l_flags = (SEC_GROUP
- 		     | SEC_LINK_ONCE
- 		     | SEC_LINK_DUPLICATES_DISCARD);
- 	}
-       else
- 	{
- 	  l_sec = l->linked.u.sec;
- 	  l_owner = l_sec->owner;
- 	  l_flags = l_sec->flags;
- 	  l_name = section_signature (l_sec);
- 	}
- 
        /* We may have 2 different types of sections on the list: group
! 	 sections and linkonce sections.  Match like sections.  */
!       if ((flags & SEC_GROUP) == (l_flags & SEC_GROUP)
! 	  && strcmp (name, l_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:
! 	      /* If we found an LTO IR match for this comdat group on
! 		 the first pass, replace it with the LTO output on the
! 		 second pass.  We can't simply choose real object
! 		 files over IR because the first pass may contain a
! 		 mix of LTO and normal objects and we must keep the
! 		 first match, be it IR or real.  */
! 	      if (info->loading_lto_outputs
! 		  && (l_owner->flags & BFD_PLUGIN) != 0)
! 		{
! 		  l->linked = *linked;
! 		  return FALSE;
! 		}
! 	      break;
! 
! 	    case SEC_LINK_DUPLICATES_ONE_ONLY:
! 	      (*_bfd_error_handler)
! 		(_("%B: ignoring duplicate section `%A'"),
! 		 abfd, sec);
! 	      break;
  
! 	    case SEC_LINK_DUPLICATES_SAME_SIZE:
! 	      if (!sec || !l_sec)
! 		abort ();
! 
! 	      if (sec->size != l_sec->size)
! 		(*_bfd_error_handler)
! 		  (_("%B: duplicate section `%A' has different size"),
! 		   abfd, sec);
! 	      break;
! 
! 	    case SEC_LINK_DUPLICATES_SAME_CONTENTS:
! 	      if (!sec || !l_sec)
! 		abort ();
! 
! 	      if (sec->size != l_sec->size)
! 		(*_bfd_error_handler)
! 		  (_("%B: duplicate section `%A' has different size"),
! 		   abfd, sec);
! 	      else if (sec->size != 0)
! 		{
! 		  bfd_byte *sec_contents, *l_sec_contents;
! 
! 		  if (!bfd_malloc_and_get_section (abfd, sec, &sec_contents))
! 		    (*_bfd_error_handler)
! 		      (_("%B: warning: could not read contents of section `%A'"),
! 		       abfd, sec);
! 		  else if (!bfd_malloc_and_get_section (l_sec->owner, l_sec,
! 							&l_sec_contents))
! 		    (*_bfd_error_handler)
! 		      (_("%B: warning: could not read contents of section `%A'"),
! 		       l_sec->owner, l_sec);
! 		  else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
! 		    (*_bfd_error_handler)
! 		      (_("%B: warning: duplicate section `%A' has different contents"),
! 		       abfd, sec);
! 
! 		  if (sec_contents)
! 		    free (sec_contents);
! 		  if (l_sec_contents)
! 		    free (l_sec_contents);
! 		}
! 	      break;
! 	    }
! 
! 	  if (sec)
  	    {
! 	      /* 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)
  		{
! 		  asection *first = elf_next_in_group (sec);
! 		  asection *s = first;
! 
! 		  while (s != NULL)
! 		    {
! 		      s->output_section = bfd_abs_section_ptr;
! 		      /* Record which group discards it.  */
! 		      s->kept_section = l_sec;
! 		      s = elf_next_in_group (s);
! 		      /* These lists are circular.  */
! 		      if (s == first)
! 			break;
! 		    }
  		}
  	    }
  
--- 12502,12585 ----
    return ret;
  }
  
  bfd_boolean
  _bfd_elf_section_already_linked (bfd *abfd,
! 				 asection *sec,
  				 struct bfd_link_info *info)
  {
    flagword flags;
!   const char *name, *key;
    struct bfd_section_already_linked *l;
    struct bfd_section_already_linked_hash_entry *already_linked_list;
  
!   if (sec->output_section == bfd_abs_section_ptr)
!     return FALSE;
  
!   flags = sec->flags;
  
+   /* Return if it isn't a linkonce section.  A comdat group section
+      also has SEC_LINK_ONCE set.  */
+   if ((flags & SEC_LINK_ONCE) == 0)
+     return FALSE;
+ 
+   /* Don't put group member sections on our list of already linked
+      sections.  They are handled as a group via their group section.  */
+   if (elf_sec_group (sec) != NULL)
+     return FALSE;
+ 
+   /* For a SHT_GROUP section, use the group signature as the key.  */
+   name = sec->name;
+   if ((flags & SEC_GROUP) != 0
+       && elf_next_in_group (sec) != NULL
+       && elf_group_name (elf_next_in_group (sec)) != NULL)
+     key = elf_group_name (elf_next_in_group (sec));
+   else
+     {
+       /* Otherwise we should have a .gnu.linkonce.<type>.<key> section.  */
        if (CONST_STRNEQ (name, ".gnu.linkonce.")
! 	  && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
! 	key++;
        else
! 	{
! 	  BFD_ASSERT (0);
! 	  key = name;
! 	}
      }
  
!   already_linked_list = bfd_section_already_linked_table_lookup (key);
  
    for (l = already_linked_list->entry; l != NULL; l = l->next)
      {
        /* We may have 2 different types of sections on the list: group
! 	 sections with a signature of <key> (<key> is some string),
! 	 and linkonce sections named .gnu.linkonce.<type>.<key>.
! 	 Match like sections.  LTO plugin sections are an exception.
! 	 They are always named .gnu.linkonce.t.<key> and match either
! 	 type of section.  */
!       if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
! 	   && ((flags & SEC_GROUP) != 0
! 	       || strcmp (name, l->sec->name) == 0))
! 	  || (l->sec->owner->flags & BFD_PLUGIN) != 0)
  	{
  	  /* The section has already been linked.  See if we should
  	     issue a warning.  */
! 	  if (!_bfd_handle_already_linked (sec, l, info))
! 	    return FALSE;
  
! 	  if (flags & SEC_GROUP)
  	    {
! 	      asection *first = elf_next_in_group (sec);
! 	      asection *s = first;
  
! 	      while (s != NULL)
  		{
! 		  s->output_section = bfd_abs_section_ptr;
! 		  /* Record which group discards it.  */
! 		  s->kept_section = l->sec;
! 		  s = elf_next_in_group (s);
! 		  /* These lists are circular.  */
! 		  if (s == first)
! 		    break;
  		}
  	    }
  
*************** _bfd_elf_section_already_linked (bfd *ab
*** 12711,12818 ****
  	}
      }
  
!   matched = FALSE;
!   if (sec)
      {
!       /* A single member comdat group section may be discarded by a
! 	 linkonce section and vice versa.  */
  
!       if ((flags & SEC_GROUP) != 0)
  	{
! 	  asection *first = elf_next_in_group (sec);
  
! 	  if (first != NULL && elf_next_in_group (first) == first)
! 	    /* Check this single member group against linkonce sections.  */
! 	    for (l = already_linked_list->entry; l != NULL; l = l->next)
! 	      {
! 		if (l->linked.comdat_key == NULL)
! 		  {
! 		    l_sec = l->linked.u.sec;
! 
! 		    if ((l_sec->flags & SEC_GROUP) == 0
! 			&& bfd_coff_get_comdat_section (l_sec->owner,
! 							l_sec) == NULL
! 			&& bfd_elf_match_symbols_in_sections (l_sec,
! 							      first,
! 							      info))
! 		      {
! 			first->output_section = bfd_abs_section_ptr;
! 			first->kept_section = l_sec;
! 			sec->output_section = bfd_abs_section_ptr;
! 			matched = TRUE;
! 			break;
! 		      }
! 		  }
! 	      }
  	}
-       else
- 	/* Check this linkonce section against single member groups.  */
- 	for (l = already_linked_list->entry; l != NULL; l = l->next)
- 	  {
- 	    if (l->linked.comdat_key == NULL)
- 	      {
- 		l_sec = l->linked.u.sec;
- 
- 		if (l_sec->flags & SEC_GROUP)
- 		  {
- 		    asection *first = elf_next_in_group (l_sec);
- 
- 		    if (first != NULL
- 			&& elf_next_in_group (first) == first
- 			&& bfd_elf_match_symbols_in_sections (first,
- 							      sec,
- 							      info))
- 		      {
- 			sec->output_section = bfd_abs_section_ptr;
- 			sec->kept_section = first;
- 			matched = TRUE;
- 			break;
- 		      }
- 		  }
- 	      }
- 	  }
- 
-       /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
- 	 referencing its discarded `.gnu.linkonce.t.F' counterpart -
- 	 g++-3.4 specific as g++-4.x is using COMDAT groups (without the
- 	 `.gnu.linkonce' prefix) instead.  `.gnu.linkonce.r.*' were the
- 	 `.rodata' part of its matching `.gnu.linkonce.t.*'.  If
- 	 `.gnu.linkonce.r.F' is not discarded but its `.gnu.linkonce.t.F'
- 	 is discarded means we chose one-only `.gnu.linkonce.t.F' section
- 	 from a different bfd not requiring any `.gnu.linkonce.r.F'.
- 	 Thus `.gnu.linkonce.r.F' should be discarded.  The reverse order
- 	 cannot happen as there is never a bfd with only the
- 	 `.gnu.linkonce.r.F' section.  The order of sections in a bfd
- 	 does not matter as here were are looking only for cross-bfd
- 	 sections.  */
  
!       if ((flags & SEC_GROUP) == 0
! 	  && CONST_STRNEQ (name, ".gnu.linkonce.r."))
! 	for (l = already_linked_list->entry; l != NULL; l = l->next)
! 	  {
! 	    if (l->linked.comdat_key == NULL)
! 	      {
! 		l_sec = l->linked.u.sec;
! 
! 		if ((l_sec->flags & SEC_GROUP) == 0
! 		    && CONST_STRNEQ (l_sec->name, ".gnu.linkonce.t."))
! 		  {
! 		    if (abfd != l_sec->owner)
! 		      {
! 			sec->output_section = bfd_abs_section_ptr;
! 			matched = TRUE;
! 		      }
! 		    break;
! 		  }
! 	      }
! 	  }
!     }
  
    /* This is the first section with this name.  Record it.  */
!   if (! bfd_section_already_linked_table_insert (already_linked_list,
! 						 linked))
      info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
!   return matched;
  }
  
  bfd_boolean
--- 12587,12653 ----
  	}
      }
  
!   /* A single member comdat group section may be discarded by a
!      linkonce section and vice versa.  */
!   if ((flags & SEC_GROUP) != 0)
      {
!       asection *first = elf_next_in_group (sec);
  
!       if (first != NULL && elf_next_in_group (first) == first)
! 	/* Check this single member group against linkonce sections.  */
! 	for (l = already_linked_list->entry; l != NULL; l = l->next)
! 	  if ((l->sec->flags & SEC_GROUP) == 0
! 	      && bfd_elf_match_symbols_in_sections (l->sec, first, info))
! 	    {
! 	      first->output_section = bfd_abs_section_ptr;
! 	      first->kept_section = l->sec;
! 	      sec->output_section = bfd_abs_section_ptr;
! 	      break;
! 	    }
!     }
!   else
!     /* Check this linkonce section against single member groups.  */
!     for (l = already_linked_list->entry; l != NULL; l = l->next)
!       if (l->sec->flags & SEC_GROUP)
  	{
! 	  asection *first = elf_next_in_group (l->sec);
  
! 	  if (first != NULL
! 	      && elf_next_in_group (first) == first
! 	      && bfd_elf_match_symbols_in_sections (first, sec, info))
! 	    {
! 	      sec->output_section = bfd_abs_section_ptr;
! 	      sec->kept_section = first;
! 	      break;
! 	    }
  	}
  
!   /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
!      referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
!      specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
!      prefix) instead.  `.gnu.linkonce.r.*' were the `.rodata' part of its
!      matching `.gnu.linkonce.t.*'.  If `.gnu.linkonce.r.F' is not discarded
!      but its `.gnu.linkonce.t.F' is discarded means we chose one-only
!      `.gnu.linkonce.t.F' section from a different bfd not requiring any
!      `.gnu.linkonce.r.F'.  Thus `.gnu.linkonce.r.F' should be discarded.
!      The reverse order cannot happen as there is never a bfd with only the
!      `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
!      matter as here were are looking only for cross-bfd sections.  */
! 
!   if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
!     for (l = already_linked_list->entry; l != NULL; l = l->next)
!       if ((l->sec->flags & SEC_GROUP) == 0
! 	  && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
! 	{
! 	  if (abfd != l->sec->owner)
! 	    sec->output_section = bfd_abs_section_ptr;
! 	  break;
! 	}
  
    /* This is the first section with this name.  Record it.  */
!   if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
      info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
!   return sec->output_section == bfd_abs_section_ptr;
  }
  
  bfd_boolean
Index: bfd/coffgen.c
===================================================================
RCS file: /cvs/src/src/bfd/coffgen.c,v
retrieving revision 1.79
diff -c -p -r1.79 coffgen.c
*** bfd/coffgen.c	7 May 2011 14:26:56 -0000	1.79
--- bfd/coffgen.c	13 Aug 2011 06:21:49 -0000
*************** bfd_coff_get_comdat_section (bfd *abfd, 
*** 2399,2401 ****
--- 2399,2468 ----
    else
      return NULL;
  }
+ 
+ bfd_boolean
+ _bfd_coff_section_already_linked (bfd *abfd,
+ 				  asection *sec,
+ 				  struct bfd_link_info *info)
+ {
+   flagword flags;
+   const char *name, *key;
+   struct bfd_section_already_linked *l;
+   struct bfd_section_already_linked_hash_entry *already_linked_list;
+   struct coff_comdat_info *s_comdat;
+ 
+   flags = sec->flags;
+   if ((flags & SEC_LINK_ONCE) == 0)
+     return FALSE;
+ 
+   /* The COFF backend linker doesn't support group sections.  */
+   if ((flags & SEC_GROUP) != 0)
+     return FALSE;
+ 
+   name = bfd_get_section_name (abfd, sec);
+   s_comdat = bfd_coff_get_comdat_section (abfd, sec);
+ 
+   if (s_comdat != NULL)
+     key = s_comdat->name;
+   else
+     {
+       if (CONST_STRNEQ (name, ".gnu.linkonce.")
+ 	  && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+ 	key++;
+       else
+ 	/* FIXME: gcc as of 2011-09 emits sections like .text$<key>,
+ 	   .xdata$<key> and .pdata$<key> only the first of which has a
+ 	   comdat key.  Should these all match the LTO IR key?  */
+ 	key = name;
+     }
+ 
+   already_linked_list = bfd_section_already_linked_table_lookup (key);
+ 
+   for (l = already_linked_list->entry; l != NULL; l = l->next)
+     {
+       struct coff_comdat_info *l_comdat;
+ 
+       l_comdat = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+ 
+       /* The section names must match, and both sections must be
+ 	 comdat and have the same comdat name, or both sections must
+ 	 be non-comdat.  LTO IR plugin sections are an exception.  They
+ 	 are always named .gnu.linkonce.t.<key> (<key> is some string)
+ 	 and match any comdat section with comdat name of <key>, and
+ 	 any linkonce section with the same suffix, ie.
+ 	 .gnu.linkonce.*.<key>.  */
+       if (((s_comdat != NULL) == (l_comdat != NULL)
+ 	   && strcmp (name, l->sec->name) == 0)
+ 	  || (l->sec->owner->flags & BFD_PLUGIN) != 0)
+ 	{
+ 	  /* The section has already been linked.  See if we should
+ 	     issue a warning.  */
+ 	  return _bfd_handle_already_linked (sec, l, info);
+ 	}
+     }
+ 
+   /* This is the first section with this name.  Record it.  */
+   if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
+     info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
+   return FALSE;
+ }
Index: bfd/targets.c
===================================================================
RCS file: /cvs/src/src/bfd/targets.c,v
retrieving revision 1.207
diff -u -p -r1.207 targets.c
--- bfd/targets.c	5 Aug 2011 03:17:11 -0000	1.207
+++ bfd/targets.c	12 Aug 2011 23:56:27 -0000
@@ -176,7 +176,6 @@ DESCRIPTION
 .
 .{* Forward declaration.  *}
 .typedef struct bfd_link_info _bfd_link_info;
-.struct already_linked;
 .
 .{* Forward declaration.  *}
 .typedef struct flag_info flag_info;
@@ -512,7 +511,7 @@ BFD_JUMP_TABLE macros.
 .
 .  {* Check if SEC has been already linked during a reloceatable or
 .     final link.  *}
-.  bfd_boolean (*_section_already_linked) (bfd *, struct already_linked *,
+.  bfd_boolean (*_section_already_linked) (bfd *, asection *,
 .					   struct bfd_link_info *);
 .
 .  {* Define a common symbol.  *}
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.375
diff -u -p -r1.375 ldlang.c
--- ld/ldlang.c	16 Jul 2011 07:58:40 -0000	1.375
+++ ld/ldlang.c	12 Aug 2011 23:56:57 -0000
@@ -2240,12 +2240,7 @@ section_already_linked (bfd *abfd, asect
     }
 
   if (!(abfd->flags & DYNAMIC))
-    {
-      struct already_linked linked;
-      linked.comdat_key = NULL;
-      linked.u.sec = sec;
-      bfd_section_already_linked (abfd, &linked, &link_info);
-    }
+    bfd_section_already_linked (abfd, sec, &link_info);
 }
 \f
 /* The wild routines.
Index: ld/plugin.c
===================================================================
RCS file: /cvs/src/src/ld/plugin.c,v
retrieving revision 1.38
diff -u -p -r1.38 plugin.c
--- ld/plugin.c	9 Aug 2011 09:27:34 -0000	1.38
+++ ld/plugin.c	12 Aug 2011 23:56:57 -0000
@@ -32,7 +32,6 @@
 #include "plugin.h"
 #include "plugin-api.h"
 #include "elf-bfd.h"
-#include "libbfd.h"
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 #include <windows.h>
 #endif
@@ -240,7 +239,7 @@ plugin_get_ir_dummy_bfd (const char *nam
 	{
 	  flagword flags;
 
-	  /* Create sections to own the symbols.  */
+	  /* Create section to own the symbols.  */
 	  flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
 		   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
 	  if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
@@ -285,7 +284,27 @@ asymbol_from_plugin_symbol (bfd *abfd, a
       /* FALLTHRU */
     case LDPK_DEF:
       flags |= BSF_GLOBAL;
-      section = bfd_get_section_by_name (abfd, ".text");
+      if (ldsym->comdat_key)
+	{
+	  char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key,
+			       (const char *) NULL);
+	  section = bfd_get_section_by_name (abfd, name);
+	  if (section != NULL)
+	    free (name);
+	  else
+	    {
+	      flagword sflags;
+
+	      sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
+			| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
+			| SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
+	      section = bfd_make_section_anyway_with_flags (abfd, name, sflags);
+	      if (section == NULL)
+		return LDPS_ERR;
+	    }
+	}
+      else
+	section = bfd_get_section_by_name (abfd, ".text");
       break;
 
     case LDPK_WEAKUNDEF:
@@ -389,13 +408,6 @@ add_symbols (void *handle, int nsyms, co
       enum ld_plugin_status rv;
       asymbol *bfdsym;
 
-      if (syms[n].comdat_key)
-	{
-	  struct already_linked linked;
-	  linked.comdat_key = xstrdup (syms[n].comdat_key);
-	  linked.u.abfd = abfd;
-	  bfd_section_already_linked (abfd, &linked, &link_info);
-	}
       bfdsym = bfd_make_empty_symbol (abfd);
       symptrs[n] = bfdsym;
       rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-13  9:59             ` Alan Modra
@ 2011-08-13 14:31               ` H.J. Lu
  2011-08-16 18:04                 ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-13 14:31 UTC (permalink / raw)
  To: Binutils, Nick Clifton

On Sat, Aug 13, 2011 at 2:59 AM, Alan Modra <amodra@gmail.com> wrote:
> Revised patch.  This one gives the plugin comdat_key symbols sections
> named .gnu.linkonce.t.<comdat_key>, so that SEC_LINK_ONCE gets set for
> the sections when recreating them during bfd_make_readable().
>
> I've also given the COFF backend its own bfd_section_already_linked
> and tidied the existing bfd_section_already_linked functions.  I'd
> appreciate someone familiar with our COFF support reviewing
> _bfd_coff_section_already_linked in case I've made some glaring
> mistakes..  The old code basically matched on section name, but if
> both sections had a comdat symbol then the symbols had to match too.
> That meant a comdat section could match a non-comdat section with the
> same name, something the new code specifically disallows, and anyway
> is a side-effect of hashing on the comdat key.  COFF also gets the
> benefit of the ELF code for SEC_LINK_DUPLICATES_SAME_CONTENTS, so
> section contents are actually checked now.
>
> bfd/
>        PR ld/12762
>        * bfd-in.h (struct bfd_section_already_linked): Forward declare.
>        (_bfd_handle_already_linked): Declare.
>        * coff-alpha.c (_bfd_ecoff_section_already_linked): Define as
>        _bfd_coff_section_already_linked.
>        * coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
>        * coffcode.h (coff_section_already_linked): Likewise.
>        * cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
>        * elf-bfd.h: Likewise.
>        * libbfd-in.h: Likewise.
>        * targets.c: Likewise.
>        * linker.c (bfd_section_already_linked): Likewise.
>        (bfd_section_already_linked_table_lookup): Likewise.
>        (bfd_section_already_linked_table_insert): Likewise.
>        (_bfd_generic_section_already_linked): Likewise.  Call
>        _bfd_handle_already_linked.
>        (_bfd_handle_already_linked): New function, split out from..
>        * elflink.c (_bfd_elf_section_already_linked): ..here.  Revert
>        2011-07-09 changes.  Avoid unnecessary strcmp when matching
>        already_linked_list entries.  Match plugin linkonce section.
>        (section_signature): Delete.
>        * coffgen.c (_bfd_coff_section_already_linked): New function.
>        * libcoff-in.h (_bfd_coff_section_already_linked): Declare.
>        * libbfd.h: Regenerate.
>        * libcoff.h: Regenerate.
>        * bfd-in2.h: Regenerate.
> ld/
>        PR ld/12762
>        * ldlang.c (section_already_linked): Revert 2011-07-09 changes.
>        * plugin.c: Likewise.
>        (asymbol_from_plugin_symbol): Create linkonce section for syms
>        with comdat_key.
>

It works.

Thanks.


-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-13 14:31               ` H.J. Lu
@ 2011-08-16 18:04                 ` H.J. Lu
  2011-08-16 18:20                   ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-16 18:04 UTC (permalink / raw)
  To: Binutils, Nick Clifton

On Sat, Aug 13, 2011 at 7:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Aug 13, 2011 at 2:59 AM, Alan Modra <amodra@gmail.com> wrote:
>> Revised patch.  This one gives the plugin comdat_key symbols sections
>> named .gnu.linkonce.t.<comdat_key>, so that SEC_LINK_ONCE gets set for
>> the sections when recreating them during bfd_make_readable().
>>
>> I've also given the COFF backend its own bfd_section_already_linked
>> and tidied the existing bfd_section_already_linked functions.  I'd
>> appreciate someone familiar with our COFF support reviewing
>> _bfd_coff_section_already_linked in case I've made some glaring
>> mistakes..  The old code basically matched on section name, but if
>> both sections had a comdat symbol then the symbols had to match too.
>> That meant a comdat section could match a non-comdat section with the
>> same name, something the new code specifically disallows, and anyway
>> is a side-effect of hashing on the comdat key.  COFF also gets the
>> benefit of the ELF code for SEC_LINK_DUPLICATES_SAME_CONTENTS, so
>> section contents are actually checked now.
>>
>> bfd/
>>        PR ld/12762
>>        * bfd-in.h (struct bfd_section_already_linked): Forward declare.
>>        (_bfd_handle_already_linked): Declare.
>>        * coff-alpha.c (_bfd_ecoff_section_already_linked): Define as
>>        _bfd_coff_section_already_linked.
>>        * coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
>>        * coffcode.h (coff_section_already_linked): Likewise.
>>        * cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
>>        * elf-bfd.h: Likewise.
>>        * libbfd-in.h: Likewise.
>>        * targets.c: Likewise.
>>        * linker.c (bfd_section_already_linked): Likewise.
>>        (bfd_section_already_linked_table_lookup): Likewise.
>>        (bfd_section_already_linked_table_insert): Likewise.
>>        (_bfd_generic_section_already_linked): Likewise.  Call
>>        _bfd_handle_already_linked.
>>        (_bfd_handle_already_linked): New function, split out from..
>>        * elflink.c (_bfd_elf_section_already_linked): ..here.  Revert
>>        2011-07-09 changes.  Avoid unnecessary strcmp when matching
>>        already_linked_list entries.  Match plugin linkonce section.
>>        (section_signature): Delete.
>>        * coffgen.c (_bfd_coff_section_already_linked): New function.
>>        * libcoff-in.h (_bfd_coff_section_already_linked): Declare.
>>        * libbfd.h: Regenerate.
>>        * libcoff.h: Regenerate.
>>        * bfd-in2.h: Regenerate.
>> ld/
>>        PR ld/12762
>>        * ldlang.c (section_already_linked): Revert 2011-07-09 changes.
>>        * plugin.c: Likewise.
>>        (asymbol_from_plugin_symbol): Create linkonce section for syms
>>        with comdat_key.
>>
>
> It works.
>

I got:

ld: BFD (Linux/GNU Binutils) 2.21.53.0.3.20110813 assertion fail
/net/gnu-6/export/linux/src/binutils/binutils/bfd/elflink.c:12634

on a Linux/x86-64 kernel driver build.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-16 18:04                 ` H.J. Lu
@ 2011-08-16 18:20                   ` H.J. Lu
  2011-08-17  0:34                     ` Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2011-08-16 18:20 UTC (permalink / raw)
  To: Binutils, Nick Clifton

On Tue, Aug 16, 2011 at 11:03 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Aug 13, 2011 at 7:31 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Sat, Aug 13, 2011 at 2:59 AM, Alan Modra <amodra@gmail.com> wrote:
>>> Revised patch.  This one gives the plugin comdat_key symbols sections
>>> named .gnu.linkonce.t.<comdat_key>, so that SEC_LINK_ONCE gets set for
>>> the sections when recreating them during bfd_make_readable().
>>>
>>> I've also given the COFF backend its own bfd_section_already_linked
>>> and tidied the existing bfd_section_already_linked functions.  I'd
>>> appreciate someone familiar with our COFF support reviewing
>>> _bfd_coff_section_already_linked in case I've made some glaring
>>> mistakes..  The old code basically matched on section name, but if
>>> both sections had a comdat symbol then the symbols had to match too.
>>> That meant a comdat section could match a non-comdat section with the
>>> same name, something the new code specifically disallows, and anyway
>>> is a side-effect of hashing on the comdat key.  COFF also gets the
>>> benefit of the ELF code for SEC_LINK_DUPLICATES_SAME_CONTENTS, so
>>> section contents are actually checked now.
>>>
>>> bfd/
>>>        PR ld/12762
>>>        * bfd-in.h (struct bfd_section_already_linked): Forward declare.
>>>        (_bfd_handle_already_linked): Declare.
>>>        * coff-alpha.c (_bfd_ecoff_section_already_linked): Define as
>>>        _bfd_coff_section_already_linked.
>>>        * coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
>>>        * coffcode.h (coff_section_already_linked): Likewise.
>>>        * cofflink.c (coff_link_add_symbols): Revert 2011-07-09 changes.
>>>        * elf-bfd.h: Likewise.
>>>        * libbfd-in.h: Likewise.
>>>        * targets.c: Likewise.
>>>        * linker.c (bfd_section_already_linked): Likewise.
>>>        (bfd_section_already_linked_table_lookup): Likewise.
>>>        (bfd_section_already_linked_table_insert): Likewise.
>>>        (_bfd_generic_section_already_linked): Likewise.  Call
>>>        _bfd_handle_already_linked.
>>>        (_bfd_handle_already_linked): New function, split out from..
>>>        * elflink.c (_bfd_elf_section_already_linked): ..here.  Revert
>>>        2011-07-09 changes.  Avoid unnecessary strcmp when matching
>>>        already_linked_list entries.  Match plugin linkonce section.
>>>        (section_signature): Delete.
>>>        * coffgen.c (_bfd_coff_section_already_linked): New function.
>>>        * libcoff-in.h (_bfd_coff_section_already_linked): Declare.
>>>        * libbfd.h: Regenerate.
>>>        * libcoff.h: Regenerate.
>>>        * bfd-in2.h: Regenerate.
>>> ld/
>>>        PR ld/12762
>>>        * ldlang.c (section_already_linked): Revert 2011-07-09 changes.
>>>        * plugin.c: Likewise.
>>>        (asymbol_from_plugin_symbol): Create linkonce section for syms
>>>        with comdat_key.
>>>
>>
>> It works.
>>
>
> I got:
>
> ld: BFD (Linux/GNU Binutils) 2.21.53.0.3.20110813 assertion fail
> /net/gnu-6/export/linux/src/binutils/binutils/bfd/elflink.c:12634
>
> on a Linux/x86-64 kernel driver build.
>

It is

http://www.sourceware.org/bugzilla/show_bug.cgi?id=13099

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fix PR12762 using linkonce sections in plugin bfd
  2011-08-16 18:20                   ` H.J. Lu
@ 2011-08-17  0:34                     ` Alan Modra
  0 siblings, 0 replies; 12+ messages in thread
From: Alan Modra @ 2011-08-17  0:34 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils, Nick Clifton

On Tue, Aug 16, 2011 at 11:19:45AM -0700, H.J. Lu wrote:
> > ld: BFD (Linux/GNU Binutils) 2.21.53.0.3.20110813 assertion fail
> > /net/gnu-6/export/linux/src/binutils/binutils/bfd/elflink.c:12634
> >
> > on a Linux/x86-64 kernel driver build.
> 
> http://www.sourceware.org/bugzilla/show_bug.cgi?id=13099

A bug report before I even committed the patch.  :)
I was waiting a little while to see if anyone had any comments about
the new coff already_linked function.  Since there haven't been any
objections, I'll commit without the assertion.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2011-08-17  0:34 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-11 13:08 Fix PR12762 using linkonce sections in plugin bfd Alan Modra
2011-08-11 13:18 ` H.J. Lu
2011-08-11 14:04   ` Alan Modra
2011-08-11 14:40     ` H.J. Lu
2011-08-11 14:57       ` H.J. Lu
2011-08-11 15:08         ` H.J. Lu
2011-08-12  3:46           ` Alan Modra
2011-08-13  9:59             ` Alan Modra
2011-08-13 14:31               ` H.J. Lu
2011-08-16 18:04                 ` H.J. Lu
2011-08-16 18:20                   ` H.J. Lu
2011-08-17  0:34                     ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).