PR ld/17973 LTO file syms
authorAlan Modra <amodra@gmail.com>
Sat, 14 Feb 2015 08:08:32 +0000 (18:38 +1030)
committerAlan Modra <amodra@gmail.com>
Sat, 14 Feb 2015 13:11:54 +0000 (23:41 +1030)
LTO output objects have an STT_FILE symbol using the name of the file,
a temporary file.  This results in executables that can't be exactly
reproduced, so the file name needs to be dropped.  We don't want to
lose all file symbols when linking a mix of lto and non-lto objects as
a file symbol can be used to figure which source file generated a
given local symbol.  So lto output objects need to be marked.

I chose to mark lto output objects with a new bfd flag.  This flag is
also used to fix a bug in the link-once handling;  An object being
loaded after "loading_lto_outputs" is set might be one extracted from
an archive to satisfy new references from lto objects, not an lto
object itself.

The new flag is copied from archive to elements, and the same done
for no_export.  This fixes a bug in that --exclude-libs doesn't work
with thin archives.  I'm not completely happy with this part of the
patch and may revist this to avoid the hack in
_bfd_look_for_bfd_in_cache.

PR ld/17973
include/
* bfdlink.h (struct bfd_link_info): Delete loading_lto_outputs.
bfd/
* bfd.c (struct bfd): Add lto_output.
* linker.c (_bfd_handle_already_linked): Explicitly test for
objects added by the lto plugin.
* opncls.c (_bfd_new_bfd_contained_in): Copy lto_output and
no_export flags from archive.
* archive.c (open_nested_file): New function, setting lto_output
and no_export, extracted from..
(find_nested_archive): ..here.  Flip params.  Rename from
_bfd_find_nested_archive.
(_bfd_get_elt_at_filepos): Correct var typo.  Use open_nested_file.
(_bfd_look_for_bfd_in_cache): Copy no_export.
* elflink.c (elf_link_add_object_symbols): Remove now unnecessary
my_archive->no_export test.
(elf_link_input_bfd): Drop existing lto_output STT_FILE syms.
Don't use the file name when adding lto_output STT_FILE sym.
* bfd-in2.h: Regenerate.
ld/
* ldlang.h (struct lang_input_statement_flags): Add lto_output.
* ldlang.c (lang_process): Don't set loading_lto_outputs.
* ldfile.c (ldfile_try_open_bfd): Transfer entry flags.lto_output
to bfd.
* plugin.c (add_input_file, add_input_library): Set flags.lto_output.

14 files changed:
bfd/ChangeLog
bfd/archive.c
bfd/bfd-in2.h
bfd/bfd.c
bfd/elflink.c
bfd/linker.c
bfd/opncls.c
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/ldfile.c
ld/ldlang.c
ld/ldlang.h
ld/plugin.c

index cb08b7738f3ce94b5ce8559e183ad0cff888f432..9f6fb2767725bb807c661837bb893eb234a1887c 100644 (file)
@@ -1,3 +1,23 @@
+2015-02-14  Alan Modra  <amodra@gmail.com>
+
+       PR ld/17973
+       * bfd.c (struct bfd): Add lto_output.
+       * linker.c (_bfd_handle_already_linked): Explicitly test for
+       objects added by the lto plugin.
+       * opncls.c (_bfd_new_bfd_contained_in): Copy lto_output and
+       no_export flags from archive.
+       * archive.c (open_nested_file): New function, setting lto_output
+       and no_export, extracted from..
+       (find_nested_archive): ..here.  Flip params.  Rename from
+       _bfd_find_nested_archive.
+       (_bfd_get_elt_at_filepos): Correct var typo.  Use open_nested_file.
+       (_bfd_look_for_bfd_in_cache): Copy no_export.
+       * elflink.c (elf_link_add_object_symbols): Remove now unnecessary
+       my_archive->no_export test.
+       (elf_link_input_bfd): Drop existing lto_output STT_FILE syms.
+       Don't use the file name when adding lto_output STT_FILE sym.
+       * bfd-in2.h: Regenerate.
+
 2015-02-13  Alan Modra  <amodra@gmail.com>
 
        PR binutils/17512
index cc4c52f7be334ab873ad6bfbc8c8eb9d6eaff63c..3899d84757449b91f50765aa02e85c449dd16e03 100644 (file)
@@ -311,8 +311,12 @@ _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
       struct ar_cache *entry = (struct ar_cache *) htab_find (hash_table, &m);
       if (!entry)
        return NULL;
-      else
-       return entry->arbfd;
+
+      /* Unfortunately this flag is set after checking that we have
+        an archive, and checking for an archive means one element has
+        sneaked into the cache.  */
+      entry->arbfd->no_export = arch_bfd->no_export;
+      return entry->arbfd;
     }
   else
     return NULL;
@@ -375,10 +379,27 @@ _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
 }
 \f
 static bfd *
-_bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
+open_nested_file (const char *filename, bfd *archive)
 {
-  bfd *abfd;
   const char *target;
+  bfd *n_bfd;
+
+  target = NULL;
+  if (!archive->target_defaulted)
+    target = archive->xvec->name;
+  n_bfd = bfd_openr (filename, target);
+  if (n_bfd != NULL)
+    {
+      n_bfd->lto_output = archive->lto_output;
+      n_bfd->no_export = archive->no_export;
+    }
+  return n_bfd;
+}
+
+static bfd *
+find_nested_archive (const char *filename, bfd *arch_bfd)
+{
+  bfd *abfd;
 
   /* PR 15140: Don't allow a nested archive pointing to itself.  */
   if (filename_cmp (filename, arch_bfd->filename) == 0)
@@ -394,10 +415,7 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
       if (filename_cmp (filename, abfd->filename) == 0)
        return abfd;
     }
-  target = NULL;
-  if (!arch_bfd->target_defaulted)
-    target = arch_bfd->xvec->name;
-  abfd = bfd_openr (filename, target);
+  abfd = open_nested_file (filename, arch_bfd);
   if (abfd)
     {
       abfd->archive_next = arch_bfd->nested_archives;
@@ -626,12 +644,12 @@ bfd *
 _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
 {
   struct areltdata *new_areldata;
-  bfd *n_nfd;
+  bfd *n_bfd;
   char *filename;
 
-  n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
-  if (n_nfd)
-    return n_nfd;
+  n_bfd = _bfd_look_for_bfd_in_cache (archive, filepos);
+  if (n_bfd)
+    return n_bfd;
 
   if (0 > bfd_seek (archive, filepos, SEEK_SET))
     return NULL;
@@ -643,8 +661,6 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
 
   if (bfd_is_thin_archive (archive))
     {
-      const char *target;
-
       /* This is a proxy entry for an external file.  */
       if (! IS_ABSOLUTE_PATH (filename))
        {
@@ -660,7 +676,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
        {
          /* This proxy entry refers to an element of a nested archive.
             Locate the member of that archive and return a bfd for it.  */
-         bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
+         bfd *ext_arch = find_nested_archive (filename, archive);
 
          if (ext_arch == NULL
              || ! bfd_check_format (ext_arch, bfd_archive))
@@ -668,57 +684,55 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
              free (new_areldata);
              return NULL;
            }
-         n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
-         if (n_nfd == NULL)
+         n_bfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
+         if (n_bfd == NULL)
            {
              free (new_areldata);
              return NULL;
            }
-         n_nfd->proxy_origin = bfd_tell (archive);
-         return n_nfd;
+         n_bfd->proxy_origin = bfd_tell (archive);
+         return n_bfd;
        }
+
       /* It's not an element of a nested archive;
         open the external file as a bfd.  */
-      target = NULL;
-      if (!archive->target_defaulted)
-       target = archive->xvec->name;
-      n_nfd = bfd_openr (filename, target);
-      if (n_nfd == NULL)
+      n_bfd = open_nested_file (filename, archive);
+      if (n_bfd == NULL)
        bfd_set_error (bfd_error_malformed_archive);
     }
   else
     {
-      n_nfd = _bfd_create_empty_archive_element_shell (archive);
+      n_bfd = _bfd_create_empty_archive_element_shell (archive);
     }
 
-  if (n_nfd == NULL)
+  if (n_bfd == NULL)
     {
       free (new_areldata);
       return NULL;
     }
 
-  n_nfd->proxy_origin = bfd_tell (archive);
+  n_bfd->proxy_origin = bfd_tell (archive);
 
   if (bfd_is_thin_archive (archive))
     {
-      n_nfd->origin = 0;
+      n_bfd->origin = 0;
     }
   else
     {
-      n_nfd->origin = n_nfd->proxy_origin;
-      n_nfd->filename = xstrdup (filename);
+      n_bfd->origin = n_bfd->proxy_origin;
+      n_bfd->filename = xstrdup (filename);
     }
 
-  n_nfd->arelt_data = new_areldata;
+  n_bfd->arelt_data = new_areldata;
 
   /* Copy BFD_COMPRESS and BFD_DECOMPRESS flags.  */
-  n_nfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
+  n_bfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
 
-  if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
-    return n_nfd;
+  if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_bfd))
+    return n_bfd;
 
   free (new_areldata);
-  n_nfd->arelt_data = NULL;
+  n_bfd->arelt_data = NULL;
   return NULL;
 }
 
index 678eaeda2e74615fe074401cba14efde69c5e02f..d02fc027078412b55a8930bf35d58e90818ddeb0 100644 (file)
@@ -6438,6 +6438,9 @@ struct bfd
   /* If this is an input for a compiler plug-in library.  */
   ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
 
+  /* Set if this is a plugin output file.  */
+  unsigned int lto_output : 1;
+
   /* Set to dummy BFD created when claimed by a compiler plug-in
      library.  */
   bfd *plugin_dummy_bfd;
index 69c6bde129a704599412fdf6c8d2ea20e7e655c6..5ae5ecac3c2380a5a61d6c7d619c74a78e110651 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -210,6 +210,9 @@ CODE_FRAGMENT
 .  {* If this is an input for a compiler plug-in library.  *}
 .  ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
 .
+.  {* Set if this is a plugin output file.  *}
+.  unsigned int lto_output : 1;
+.
 .  {* Set to dummy BFD created when claimed by a compiler plug-in
 .     library.  *}
 .  bfd *plugin_dummy_bfd;
index 16d9f20a40f032265b71147da78f0f188c0425b7..bf28885548f7b953d2755f9cb41337a52d6ae305 100644 (file)
@@ -4085,8 +4085,7 @@ error_free_dyn:
             requested we not re-export it, then mark it as hidden.  */
          if (definition
              && !dynamic
-             && (abfd->no_export
-                 || (abfd->my_archive && abfd->my_archive->no_export))
+             && abfd->no_export
              && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
            isym->st_other = (STV_HIDDEN
                              | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
@@ -9520,6 +9519,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
       if (ELF_ST_TYPE (isym->st_info) == STT_FILE)
        {
+         if (input_bfd->lto_output)
+           /* -flto puts a temp file name here.  This means builds
+              are not reproducible.  Discard the symbol.  */
+           continue;
          have_file_sym = TRUE;
          flinfo->filesym_count += 1;
        }
@@ -9536,8 +9539,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          memset (&osym, 0, sizeof (osym));
          osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
          osym.st_shndx = SHN_ABS;
-         if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym,
-                                   bfd_abs_section_ptr, NULL))
+         if (!elf_link_output_sym (flinfo,
+                                   (input_bfd->lto_output ? NULL
+                                    : input_bfd->filename),
+                                   &osym, bfd_abs_section_ptr, NULL))
            return FALSE;
        }
 
index c1a2e8232bcb9453261f08b8ffe05f441851a3d7..dec6d1d0ace372ebdb04662139ee16c6a09d4e49 100644 (file)
@@ -2896,7 +2896,7 @@ _bfd_handle_already_linked (asection *sec,
         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
+      if (sec->owner->lto_output
          && (l->sec->owner->flags & BFD_PLUGIN) != 0)
        {
          l->sec = sec;
index 1320ee153d39be7e0a8f5ce7f36248fecae8f5d0..f0f2e64b319a5fafbbef48ef8e6a2d856705c6c5 100644 (file)
@@ -109,6 +109,8 @@ _bfd_new_bfd_contained_in (bfd *obfd)
   nbfd->my_archive = obfd;
   nbfd->direction = read_direction;
   nbfd->target_defaulted = obfd->target_defaulted;
+  nbfd->lto_output = obfd->lto_output;
+  nbfd->no_export = obfd->no_export;
   return nbfd;
 }
 
index 24a141dba511a222c5bd49618cce0f87b5c3517f..606ed90681666f9ff78d2309fd0faf303ebfbfb0 100644 (file)
@@ -1,3 +1,8 @@
+2015-02-14  Alan Modra  <amodra@gmail.com>
+
+       PR ld/17973
+       * bfdlink.h (struct bfd_link_info): Delete loading_lto_outputs.
+
 2015-02-09  Mark Wielaard  <mjw@redhat.com>
 
        * dwarf2.h: Add DW_LANG_Fortran03 and DW_LANG_Fortran08.
index add4971df84dd6860169df10b009020e99b659be..6a02a3c43bfa747c0905178726e6e6e5f17c8e7f 100644 (file)
@@ -301,9 +301,6 @@ struct bfd_link_info
   /* TRUE if the LTO plugin is active.  */
   unsigned int lto_plugin_active: 1;
 
-  /* TRUE if we are loading LTO outputs.  */
-  unsigned int loading_lto_outputs: 1;
-
   /* TRUE if global symbols in discarded sections should be stripped.  */
   unsigned int strip_discarded: 1;
 
index c30426db570996ae0eefbfb220957558ff9b808f..4803ec3ba7e64d180efa9b52dc02c20709d246a6 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-14  Alan Modra  <amodra@gmail.com>
+
+       PR ld/17973
+       * ldlang.h (struct lang_input_statement_flags): Add lto_output.
+       * ldlang.c (lang_process): Don't set loading_lto_outputs.
+       * ldfile.c (ldfile_try_open_bfd): Transfer entry flags.lto_output
+       to bfd.
+       * plugin.c (add_input_file, add_input_library): Set flags.lto_output.
+
 2015-02-13  H.J. Lu  <hongjiu.lu@intel.com>
 
        * NEWS: Mention support for LLVM plugin.
index e19f55e6e04d4308d8bf5b6dd55c79ee2102706c..21bdbf404710ab57e735cd805daf4f9fc9de04d1 100644 (file)
@@ -142,6 +142,11 @@ ldfile_try_open_bfd (const char *attempt,
   /* Linker needs to decompress sections.  */
   entry->the_bfd->flags |= BFD_DECOMPRESS;
 
+#ifdef ENABLE_PLUGINS
+  if (entry->flags.lto_output)
+    entry->the_bfd->lto_output = 1;
+#endif
+
   /* If we are searching for this file, see if the architecture is
      compatible with the output file.  If it isn't, keep searching.
      If we can't open the file as an object file, stop the search
index 5c4581f0e8d12e049104a3fa05575aa63e3d9c3b..ce333b426cd9370580bbe8d2870eb1cc85b4fd27 100644 (file)
@@ -6643,7 +6643,6 @@ lang_process (void)
        einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
               plugin_error_plugin ());
       /* Open any newly added files, updating the file chains.  */
-      link_info.loading_lto_outputs = TRUE;
       open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
       /* Restore the global list pointer now they have all been added.  */
       lang_list_remove_tail (stat_ptr, &added);
index 69d21a723096cc7ead383c1d426d0369b7ed674c..7cb7610e477a51330a64e89f4c0b4e2b8e58e29d 100644 (file)
@@ -283,6 +283,9 @@ struct lang_input_statement_flags
 
   /* Set if the file was claimed from an archive.  */
   unsigned int claim_archive : 1;
+
+  /* Set if added by the lto plugin add_input_file callback.  */
+  unsigned int lto_output : 1;
 #endif /* ENABLE_PLUGINS */
 
   /* Head of list of pushed flags.  */
index 4fee305b698c844f9e717a843dd17dcb89c383f7..31527ae64493d8f7bd39fabd8e42a31374f3024b 100644 (file)
@@ -772,10 +772,14 @@ get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
 static enum ld_plugin_status
 add_input_file (const char *pathname)
 {
+  lang_input_statement_type *is;
+
   ASSERT (called_plugin);
-  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
-                           NULL))
+  is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
+                           NULL);
+  if (!is)
     return LDPS_ERR;
+  is->flags.lto_output = 1;
   return LDPS_OK;
 }
 
@@ -783,10 +787,14 @@ add_input_file (const char *pathname)
 static enum ld_plugin_status
 add_input_library (const char *pathname)
 {
+  lang_input_statement_type *is;
+
   ASSERT (called_plugin);
-  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
-                           NULL))
+  is = lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
+                           NULL);
+  if (!is)
     return LDPS_ERR;
+  is->flags.lto_output = 1;
   return LDPS_OK;
 }