PR ld/12365
authorAlan Modra <amodra@gmail.com>
Wed, 20 Apr 2011 00:22:08 +0000 (00:22 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 20 Apr 2011 00:22:08 +0000 (00:22 +0000)
bfd/
* elfcode.h (elf_slurp_symbol_table): Put common plugin IR symbols
in their own common section.
* elflink.c (elf_link_add_object_symbols): Likewise.
* linker.c (generic_link_check_archive_element): Don't lose flags
if common section is pre-existing.
(_bfd_generic_link_add_one_symbol): Likewise.
ld/
* ldfile.c (ldfile_try_open_bfd): Move code creating and switching
to plugin IR BFD..
* ldmain.c (add_archive_element): ..and similar code here..
* plugin.c (plugin_maybe_claim): ..to here.  New function.
(plugin_call_claim_file): Make static.
(asymbol_from_plugin_symbol): Set ELF st_shndx for common syms.
(plugin_multiple_common): New function.
(plugin_call_all_symbols_read): Hook in plugin_multiple_common.
* plugin.h (plugin_call_claim_file): Don't declare.
(plugin_maybe_claim): Declare.

bfd/ChangeLog
bfd/elfcode.h
bfd/elflink.c
bfd/linker.c
ld/ChangeLog
ld/ldfile.c
ld/ldmain.c
ld/plugin.c
ld/plugin.h

index 0d532e8796a7fed310ea2fa0ac1ddfee424007cd..582e98f85b97bece469e6fd4abffec425bbdc583 100644 (file)
@@ -1,3 +1,13 @@
+2011-04-20  Alan Modra  <amodra@gmail.com>
+
+       PR ld/12365
+       * elfcode.h (elf_slurp_symbol_table): Put common plugin IR symbols
+       in their own common section.
+       * elflink.c (elf_link_add_object_symbols): Likewise.
+       * linker.c (generic_link_check_archive_element): Don't lose flags
+       if common section is pre-existing.
+       (_bfd_generic_link_add_one_symbol): Likewise.
+
 2011-04-20  Alan Modra  <amodra@gmail.com>
 
        PR ld/12365
index 28b6b904e5fb1c88900d1acb97e97311ea2eab2a..d8833dfdcf3ca634327e645dd75467460ebc745d 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
@@ -1282,6 +1282,20 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
          else if (isym->st_shndx == SHN_COMMON)
            {
              sym->symbol.section = bfd_com_section_ptr;
+             if ((abfd->flags & BFD_PLUGIN) != 0)
+               {
+                 asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+                 if (xc == NULL)
+                   {
+                     flagword flags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+                                       | SEC_EXCLUDE);
+                     xc = bfd_make_section_with_flags (abfd, "COMMON", flags);
+                     if (xc == NULL)
+                       goto error_return;
+                   }
+                 sym->symbol.section = xc;
+               }
              /* Elf puts the alignment into the `value' field, and
                 the size into the `size' field.  BFD wants to see the
                 size in the value field, and doesn't care (at the
index f0ad579876bf7e66addf1a1903609fa234725469..110bb663aa13cd01ef4de24ea21b13b359173a86 100644 (file)
@@ -3937,18 +3937,31 @@ error_free_dyn:
        goto error_free_vers;
 
       if (isym->st_shndx == SHN_COMMON
-         && ELF_ST_TYPE (isym->st_info) == STT_TLS
-         && !info->relocatable)
+         && (abfd->flags & BFD_PLUGIN) != 0)
+       {
+         asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+         if (xc == NULL)
+           {
+             flagword sflags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+                                | SEC_EXCLUDE);
+             xc = bfd_make_section_with_flags (abfd, "COMMON", sflags);
+             if (xc == NULL)
+               goto error_free_vers;
+           }
+         sec = xc;
+       }
+      else if (isym->st_shndx == SHN_COMMON
+              && ELF_ST_TYPE (isym->st_info) == STT_TLS
+              && !info->relocatable)
        {
          asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
 
          if (tcomm == NULL)
            {
-             tcomm = bfd_make_section_with_flags (abfd, ".tcommon",
-                                                  (SEC_ALLOC
-                                                   | SEC_IS_COMMON
-                                                   | SEC_LINKER_CREATED
-                                                   | SEC_THREAD_LOCAL));
+             flagword sflags = (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_IS_COMMON
+                                | SEC_LINKER_CREATED);
+             tcomm = bfd_make_section_with_flags (abfd, ".tcommon", sflags);
              if (tcomm == NULL)
                goto error_free_vers;
            }
index 8c577f27220ae9a0fcaf9d797ee335b8cb007a1a..9f2bac3c44f4771278931b3cbc8ad3f9e7234111 100644 (file)
@@ -1296,7 +1296,7 @@ generic_link_check_archive_element (bfd *abfd,
          else
            h->u.c.p->section = bfd_make_section_old_way (symbfd,
                                                          p->section->name);
-         h->u.c.p->section->flags = SEC_ALLOC;
+         h->u.c.p->section->flags |= SEC_ALLOC;
        }
       else
        {
@@ -1756,13 +1756,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
          if (section == bfd_com_section_ptr)
            {
              h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
-             h->u.c.p->section->flags = SEC_ALLOC;
+             h->u.c.p->section->flags |= SEC_ALLOC;
            }
          else if (section->owner != abfd)
            {
              h->u.c.p->section = bfd_make_section_old_way (abfd,
                                                            section->name);
-             h->u.c.p->section->flags = SEC_ALLOC;
+             h->u.c.p->section->flags |= SEC_ALLOC;
            }
          else
            h->u.c.p->section = section;
@@ -1803,13 +1803,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
                {
                  h->u.c.p->section
                    = bfd_make_section_old_way (abfd, "COMMON");
-                 h->u.c.p->section->flags = SEC_ALLOC;
+                 h->u.c.p->section->flags |= SEC_ALLOC;
                }
              else if (section->owner != abfd)
                {
                  h->u.c.p->section
                    = bfd_make_section_old_way (abfd, section->name);
-                 h->u.c.p->section->flags = SEC_ALLOC;
+                 h->u.c.p->section->flags |= SEC_ALLOC;
                }
              else
                h->u.c.p->section = section;
index ab16c693bfe732b96c3f65e5c48562c2dbbeac1c..31acf598cb61fde7c932ff11c0c985abced00dba 100644 (file)
@@ -1,3 +1,17 @@
+2011-04-20  Alan Modra  <amodra@gmail.com>
+
+       PR ld/12365
+       * ldfile.c (ldfile_try_open_bfd): Move code creating and switching
+       to plugin IR BFD..
+       * ldmain.c (add_archive_element): ..and similar code here..
+       * plugin.c (plugin_maybe_claim): ..to here.  New function.
+       (plugin_call_claim_file): Make static.
+       (asymbol_from_plugin_symbol): Set ELF st_shndx for common syms.
+       (plugin_multiple_common): New function.
+       (plugin_call_all_symbols_read): Hook in plugin_multiple_common.
+       * plugin.h (plugin_call_claim_file): Don't declare.
+       (plugin_maybe_claim): Declare.
+
 2011-04-20  Alan Modra  <amodra@gmail.com>
 
        PR ld/12365
index 96a3856e4a3aad4f7184688e2f75ed17bb22cfac..c4b89120eeed9860e40a07e22007e218d1da652d 100644 (file)
@@ -1,6 +1,7 @@
 /* Linker file opening and searching.
    Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -320,35 +321,12 @@ success:
       if (fd >= 0)
        {
          struct ld_plugin_input_file file;
-         int claimed = 0;
 
          file.name = attempt;
          file.offset = 0;
          file.filesize = lseek (fd, 0, SEEK_END);
          file.fd = fd;
-         /* We create a dummy BFD, initially empty, to house
-            whatever symbols the plugin may want to add.  */
-         file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd);
-         if (plugin_call_claim_file (&file, &claimed))
-           einfo (_("%P%F: %s: plugin reported error claiming file\n"),
-                  plugin_error_plugin ());
-         /* fd belongs to us, not the plugin; but we don't need it.  */
-         close (fd);
-         if (claimed)
-           {
-             /* Discard the real file's BFD and substitute the dummy one.  */
-             bfd_close (entry->the_bfd);
-             entry->the_bfd = file.handle;
-             entry->claimed = TRUE;
-             bfd_make_readable (entry->the_bfd);
-           }
-         else
-           {
-             /* If plugin didn't claim the file, we don't need the dummy
-                bfd.  Can't avoid speculatively creating it, alas.  */
-             bfd_close_all_done (file.handle);
-             entry->claimed = FALSE;
-           }
+         plugin_maybe_claim (&file, entry);
        }
     }
 #endif /* ENABLE_PLUGINS */
index b7e725be80a2d217659e28995b39a27444429948..0de78903bbb2df358347cca3ed69c3523b70e372 100644 (file)
@@ -813,7 +813,7 @@ add_archive_element (struct bfd_link_info *info,
       if (fd >= 0)
        {
          struct ld_plugin_input_file file;
-         int claimed = 0;
+
          /* Offset and filesize must refer to the individual archive
             member, not the whole file, and must exclude the header.
             Fortunately for us, that is how the data is stored in the
@@ -822,29 +822,12 @@ add_archive_element (struct bfd_link_info *info,
          file.offset = abfd->origin;
          file.filesize = arelt_size (abfd);
          file.fd = fd;
-         /* We create a dummy BFD, initially empty, to house
-            whatever symbols the plugin may want to add.  */
-         file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
-         if (plugin_call_claim_file (&file, &claimed))
-           einfo (_("%P%F: %s: plugin reported error claiming file\n"),
-                  plugin_error_plugin ());
-         /* fd belongs to us, not the plugin; but we don't need it.  */
-         close (fd);
-         if (claimed)
+         plugin_maybe_claim (&file, input);
+         if (input->claimed)
            {
-             /* Substitute the dummy BFD.  */
-             input->the_bfd = file.handle;
-             input->claimed = TRUE;
              input->claim_archive = TRUE;
-             bfd_make_readable (input->the_bfd);
              *subsbfd = input->the_bfd;
            }
-         else
-           {
-             /* Abandon the dummy BFD.  */
-             bfd_close_all_done (file.handle);
-             input->claimed = FALSE;
-           }
        }
     }
 #endif /* ENABLE_PLUGINS */
index b363bc104f3193b50b71b403364b3e6dd76eea8a..f45064efb270cf35d622454ec58b128ef6e3f551 100644 (file)
@@ -140,6 +140,11 @@ static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
                                               bfd *nbfd,
                                               asection *nsec,
                                               bfd_vma nval);
+static bfd_boolean plugin_multiple_common (struct bfd_link_info *info,
+                                          struct bfd_link_hash_entry *h,
+                                          bfd *nbfd,
+                                          enum bfd_link_hash_type ntype,
+                                          bfd_vma nsize);
 
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
@@ -312,7 +317,10 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
       asym->value = ldsym->size;
       /* For ELF targets, set alignment of common symbol to 1.  */
       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-       ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+       {
+         ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
+         ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+       }
       break;
 
     default:
@@ -812,7 +820,7 @@ plugin_load_plugins (void)
 }
 
 /* Call 'claim file' hook for all plugins.  */
-int
+static int
 plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
 {
   plugin_t *curplug = plugins_list;
@@ -835,6 +843,42 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
   return plugin_error_p () ? -1 : 0;
 }
 
+void
+plugin_maybe_claim (struct ld_plugin_input_file *file,
+                   lang_input_statement_type *entry)
+{
+  int claimed = 0;
+
+  /* We create a dummy BFD, initially empty, to house whatever symbols
+     the plugin may want to add.  */
+  file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
+                                         entry->the_bfd);
+  if (plugin_call_claim_file (file, &claimed))
+    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+          plugin_error_plugin ());
+  /* fd belongs to us, not the plugin; but we don't need it.  */
+  close (file->fd);
+  if (claimed)
+    {
+      /* Discard the real file's BFD and substitute the dummy one.  */
+
+      /* BFD archive handling caches elements so we can't call
+        bfd_close for archives.  */
+      if (entry->the_bfd->my_archive == NULL)
+       bfd_close (entry->the_bfd);
+      entry->the_bfd = file->handle;
+      entry->claimed = TRUE;
+      bfd_make_readable (entry->the_bfd);
+    }
+  else
+    {
+      /* If plugin didn't claim the file, we don't need the dummy bfd.
+        Can't avoid speculatively creating it, alas.  */
+      bfd_close_all_done (file->handle);
+      entry->claimed = FALSE;
+    }
+}
+
 /* Call 'all symbols read' hook for all plugins.  */
 int
 plugin_call_all_symbols_read (void)
@@ -845,6 +889,7 @@ plugin_call_all_symbols_read (void)
   no_more_claiming = TRUE;
 
   plugin_callbacks.multiple_definition = &plugin_multiple_definition;
+  plugin_callbacks.multiple_common = &plugin_multiple_common;
 
   while (curplug)
     {
@@ -955,3 +1000,22 @@ plugin_multiple_definition (struct bfd_link_info *info,
 
   return (*orig_callbacks->multiple_definition) (info, h, nbfd, nsec, nval);
 }
+
+static bfd_boolean
+plugin_multiple_common (struct bfd_link_info *info,
+                       struct bfd_link_hash_entry *h,
+                       bfd *nbfd, enum bfd_link_hash_type ntype, bfd_vma nsize)
+{
+  if (h->type == bfd_link_hash_common
+      && is_ir_dummy_bfd (h->u.c.p->section->owner)
+      && ntype == bfd_link_hash_common
+      && !is_ir_dummy_bfd (nbfd))
+    {
+      /* Arrange to have it replaced.  */
+      ASSERT (nsize != 0);
+      h->u.c.size = 0;
+      return TRUE;
+    }
+
+  return (*orig_callbacks->multiple_common) (info, h, nbfd, ntype, nsize);
+}
index 7b39e729ea9c115c9afcfb2c2b72898baf3bf629..ee29b7ce1c9908c840b6c975d1868f1cd71c30d0 100644 (file)
@@ -50,8 +50,8 @@ extern int plugin_load_plugins (void);
 extern const char *plugin_error_plugin (void);
 
 /* Call 'claim file' hook for all plugins.  */
-extern int plugin_call_claim_file (const struct ld_plugin_input_file *file,
-                                  int *claimed);
+extern void plugin_maybe_claim (struct ld_plugin_input_file *,
+                               lang_input_statement_type *);
 
 /* Call 'all symbols read' hook for all plugins.  */
 extern int plugin_call_all_symbols_read (void);