Fix PR12762 using linkonce sections in plugin bfd

Alan Modra amodra@gmail.com
Thu Aug 11 13:08:00 GMT 2011


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);
 }
 
 /* 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



More information about the Binutils mailing list