PR ld/12762
authorAlan Modra <amodra@gmail.com>
Wed, 17 Aug 2011 00:39:41 +0000 (00:39 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 17 Aug 2011 00:39:41 +0000 (00:39 +0000)
bfd/
* 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/
* 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.

19 files changed:
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/coff-alpha.c
bfd/coff-mips.c
bfd/coffcode.h
bfd/coffgen.c
bfd/cofflink.c
bfd/elf-bfd.h
bfd/elflink.c
bfd/libbfd-in.h
bfd/libbfd.h
bfd/libcoff-in.h
bfd/libcoff.h
bfd/linker.c
bfd/targets.c
ld/ChangeLog
ld/ldlang.c
ld/plugin.c

index d3ec83004349f2cadd9d46dba497cad43bd57af0..1cd864b692c5b7d055167d8771620bc8a2a1b3c9 100644 (file)
@@ -1,3 +1,32 @@
+2011-08-17  Alan Modra  <amodra@gmail.com>
+
+       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.
+
 2011-08-14  Alan Modra  <amodra@gmail.com>
 
        * elf32-ppc.c (ppc_elf_select_plt_layout): Force bss-plt when
index f375d2f488033de1f54d707a2b7f3f478d151a6d..718d72e51f37094512f516fd46cf32903c829d91 100644 (file)
@@ -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 63ffd95f534816553eaad1c1701f814624726529..7cf3b7e60bc2d32bcb716c8c71fd0734c98f8913 100644 (file)
@@ -559,11 +559,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;
@@ -571,8 +566,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
@@ -5773,7 +5778,6 @@ enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
 
 /* Forward declaration.  */
 typedef struct bfd_link_info _bfd_link_info;
-struct already_linked;
 
 /* Forward declaration.  */
 typedef struct flag_info flag_info;
@@ -6107,7 +6111,7 @@ typedef struct bfd_target
 
   /* 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.  */
@@ -6178,11 +6182,11 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
        BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
 
 bfd_boolean bfd_section_already_linked (bfd *abfd,
-    struct already_linked *data,
+    asection *sec,
     struct bfd_link_info *info);
 
-#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))
 
 bfd_boolean bfd_generic_define_common_symbol
    (bfd *output_bfd, struct bfd_link_info *info,
index 2233a335cbf739fa2186dfd6087041e57690752f..4466e4d71a5dc2c7ab2da4283ef9f02f61e5cff8 100644 (file)
@@ -2403,7 +2403,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
 #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 9f8b90dcef8285f1bcf740e99f27fb6cc0bb7725..4048ca89dd183154761e3e8e5d30062bf9032f5e 100644 (file)
@@ -1419,7 +1419,7 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
 #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 2313dc50a2d61b2e047c4b72b1d17a1095711752..6f9685b4ee9f2033a2091fe85b4f36e6b9c9088a 100644 (file)
@@ -5670,7 +5670,7 @@ static bfd_coff_backend_data ticoff1_swap_table =
 
 #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 b0c2c62f1871e2651dec4e631b98b153e0b12bce..bbb0acc1c62bc916447ee582c3667687fc34bc52 100644 (file)
@@ -2399,3 +2399,70 @@ bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec)
   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 27257baa9c48490aee28857e0bb927b56f8e69d0..bca136445de141eef3bb77cac9b734139810dad7 100644 (file)
@@ -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 2c80f67be77ff1fcfe40902843cecb987cad9899..d6e2ab29ce4d8282a1d719c81eea3e46ce201acd 100644 (file)
@@ -1801,9 +1801,8 @@ extern bfd_boolean _bfd_elf_match_sections_by_type
   (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 53765b626df330cb707f08ce8a33a8c025038863..528f705e8a8cce54e37d8f752611eaa0ba0dda57 100644 (file)
@@ -12502,208 +12502,84 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   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,
+                                asection *sec,
                                 struct bfd_link_info *info)
 {
   flagword flags;
-  const char *name, *p;
+  const char *name, *key;
   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.
+  if (sec->output_section == bfd_abs_section_ptr)
+    return FALSE;
 
-        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;
 
-        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.  */
+  /* 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;
 
-      name = section_signature (sec);
+  /* 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.")
-         && ((p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.'))
-             != NULL))
-       p++;
+         && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+       key++;
       else
-       p = name;
+       /* Must be a user linkonce section that doesn't follow gcc's
+          naming convention.  In this case we won't be matching
+          single member groups.  */
+       key = name;
     }
 
-  already_linked_list = bfd_section_already_linked_table_lookup (p);
+  already_linked_list = bfd_section_already_linked_table_lookup (key);
 
   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 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.  */
-         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 (!_bfd_handle_already_linked (sec, l, info))
+           return FALSE;
 
-         if (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 +12587,67 @@ _bfd_elf_section_already_linked (bfd *abfd,
        }
     }
 
-  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 db39f3cfc65e03bd4f7378e6908cba52fc1720d6..b6c90d1fb11491d8aeb54bfb944123e383e59e3d 100644 (file)
@@ -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_section_contents
 #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_split_section
   (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_entry
   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 71188dcc1e938e31cace3ae73f02e912f8ee3f0d..200a6fad3190eb9b8113e15c9c12598979cfe41f 100644 (file)
@@ -8,7 +8,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.
@@ -486,7 +486,7 @@ extern bfd_boolean _bfd_generic_set_section_contents
 #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 *, \
@@ -608,7 +608,7 @@ extern bfd_boolean _bfd_generic_link_split_section
   (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
@@ -800,26 +800,16 @@ struct bfd_section_already_linked_hash_entry
   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 1b6515147605e35860e991b543b0208f853a43f4..00d9ab261b259990bd08ccd821a168b5949de2dd 100644 (file)
@@ -546,6 +546,8 @@ extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
   (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 37b05d197018d6f4a3c33032182c8911ebed66a9..bd58c82e479fce87d97c38ead3b7a9ff913b0f0a 100644 (file)
@@ -550,6 +550,8 @@ extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
   (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 b3ccefd6e1100c33082b4b5489077f0e7690d123..e44386232d34562c03bbb6a07324c64897749968 100644 (file)
@@ -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 (const char *name)
 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;
@@ -2988,159 +2988,137 @@ bfd_section_already_linked_table_free (void)
   bfd_hash_table_free (&_bfd_section_already_linked_table);
 }
 
-/* This is used on non-ELF inputs.  */
+/* Report warnings as appropriate for duplicate section SEC.
+   Return FALSE if we decide to keep SEC after all.  */
 
 bfd_boolean
-_bfd_generic_section_already_linked (bfd *abfd,
-                                    struct already_linked *linked,
-                                    struct bfd_link_info *info)
+_bfd_handle_already_linked (asection *sec,
+                           struct bfd_section_already_linked *l,
+                           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
+  switch (sec->flags & SEC_LINK_DUPLICATES)
     {
-      sec = linked->u.sec;
-      flags = sec->flags;
-      if ((flags & SEC_LINK_ONCE) == 0)
-       return FALSE;
+    default:
+      abort ();
 
-      s_comdat = bfd_coff_get_comdat_section (abfd, sec);
+    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;
 
-      /* 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.
+    case SEC_LINK_DUPLICATES_ONE_ONLY:
+      info->callbacks->einfo
+       (_("%B: ignoring duplicate section `%A'\n"),
+        sec->owner, sec);
+      break;
 
-        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.  */
+    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;
 
-      name = bfd_get_section_name (abfd, sec);
+    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;
     }
 
-  already_linked_list = bfd_section_already_linked_table_lookup (name);
+  /* 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;
+}
 
-  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;
+/* This is used on non-ELF inputs.  */
 
-      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);
-       }
+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;
 
-      /* 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.
+  if ((sec->flags & SEC_LINK_ONCE) == 0)
+    return FALSE;
 
-        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;
+  /* The generic linker doesn't handle section groups.  */
+  if ((sec->flags & SEC_GROUP) != 0)
+    return FALSE;
 
-      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;
+  /* 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.
 
-           case SEC_LINK_DUPLICATES_ONE_ONLY:
-             (*_bfd_error_handler)
-               (_("%B: warning: ignoring duplicate section `%A'\n"),
-                abfd, sec);
-             break;
+     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.  */
 
-           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;
-           }
+  name = bfd_get_section_name (abfd, sec);
 
-         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;
-           }
+  already_linked_list = bfd_section_already_linked_table_lookup (name);
 
-         return TRUE;
-       }
+  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,
-                                                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 3dfa145b458bbbba8f186f3fe8dff645eefef8be..46c2c9442e365be03f89f3843ef5c390379e339d 100644 (file)
@@ -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 f842a82fa4417149d26c9ab1ff7c8eea9be051e5..ce8a0345329aa34e72f14ee9d585cef8ff32b1d4 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-17  Alan Modra  <amodra@gmail.com>
+
+       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.
+
 2011-08-09  Matthew Gretton-Dann  <matthew.gretton-dann@arm.com>
 
        * emultempl/armelf.em (fix_arm1176): New variable.
index 0ffafb66554041d46791017d2ddf63e0ff1863b6..5b548d0b4a9590f21dd73235cd4e82d0a08342de 100644 (file)
@@ -2240,12 +2240,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
     }
 
   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 9baeb468a9543314bed4b1c262ef6560a6e683e5..0be7fa3a6b57e4512f5efef3583de483c69badd7 100644 (file)
@@ -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 *name, bfd *srctemplate)
        {
          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, asymbol *asym,
       /* 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, const struct ld_plugin_symbol *syms)
       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);