Fix a conflict between the linker's need to rename some PE format input libraries...
authorAlan Modra <amodra@gmail.com>
Wed, 3 Aug 2022 12:31:57 +0000 (13:31 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 3 Aug 2022 12:31:57 +0000 (13:31 +0100)
PR 29389
bfd * bfd.c (BFD_CLOSED_BY_CACHE): New bfd flag.
* cache.c (bfd_cache_delete): Set BFD_CLOSED_BY_DELETE on the
closed bfd.
(bfd_cache_lookup_worker): Clear BFD_CLOSED_BY_DELETE on the newly
reopened bfd.
* opncls.c (bfd_set_filename): Refuse to change the name of a bfd
that has been closed by bfd_cache_delete.  Mark changed bfds as
uncacheable.
* bfd-in2.h: Regenerate.

ld * ldlang.h (lang_input_statement_struct): Add sort_key field.
* emultempl/pe.em (after_open): If multiple import libraries refer
to the same bfd, store their names in the sort_key field.
* emultempl/pep.em (after_open): Likewise.
* ldlang.c (sort_filename): New function.  Returns the filename to
be used when sorting input files.
(wild_sort): Use the sort_filename function.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/bfd.c
bfd/cache.c
bfd/opncls.c
ld/ChangeLog
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/ldlang.c
ld/ldlang.h

index afabbc0f56aa5964ff7947ceace4625c1b9b3c99..cb1f48ba4819272f98516bd8cb447285f44e31ea 100644 (file)
@@ -1,3 +1,16 @@
+2022-08-03  Nick Clifton  <nickc@redhat.com>
+
+       PR 29389
+       * bfd.c (BFD_CLOSED_BY_CACHE): New bfd flag.
+       * cache.c (bfd_cache_delete): Set BFD_CLOSED_BY_DELETE on the
+       closed bfd.
+       (bfd_cache_lookup_worker): Clear BFD_CLOSED_BY_DELETE on the newly
+       reopened bfd.
+       * opncls.c (bfd_set_filename): Refuse to change the name of a bfd
+       that has been closed by bfd_cache_delete.  Mark changed bfds as
+       uncacheable.
+       * bfd-in2.h: Regenerate.
+
 2022-07-29  Nick Clifton  <nickc@redhat.com>
 
        PR 29424
index 91ada0e3a94a31b29cb88bd01385afcf506eed5e..a95e4a24cad0df968b64e5c0fc02101bc91fdf43 100644 (file)
@@ -6638,6 +6638,8 @@ struct bfd
   /* Put pathnames into archives (non-POSIX).  */
 #define BFD_ARCHIVE_FULL_PATH  0x100000
 
+#define BFD_CLOSED_BY_CACHE    0x200000
+
   /* Flags bits to be saved in bfd_preserve_save.  */
 #define BFD_FLAGS_SAVED \
   (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
index 3e85e171e3f3c2f944d79d1e9a2d19eec4ce5c38..5e5272b9080cac762f173188363cc6680121d572 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -176,6 +176,8 @@ CODE_FRAGMENT
 .  {* Put pathnames into archives (non-POSIX).  *}
 .#define BFD_ARCHIVE_FULL_PATH  0x100000
 .
+.#define BFD_CLOSED_BY_CACHE    0x200000
+.
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
index 8a6d359a789f2f4247442eb785a4a7dcd2e166ee..73b68c7aff90cbaa185b71055557fbc1d28e10af 100644 (file)
@@ -177,6 +177,7 @@ bfd_cache_delete (bfd *abfd)
 
   abfd->iostream = NULL;
   --open_files;
+  abfd->flags |= BFD_CLOSED_BY_CACHE;
 
   return ret;
 }
@@ -265,10 +266,13 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
           && !(flag & CACHE_NO_SEEK_ERROR))
     bfd_set_error (bfd_error_system_call);
   else
-    return (FILE *) abfd->iostream;
+    {
+      abfd->flags &= ~BFD_CLOSED_BY_CACHE;
+      return (FILE *) abfd->iostream;
+    }
 
   /* xgettext:c-format */
-  _bfd_error_handler (_("reopening %pB: %s\n"),
+  _bfd_error_handler (_("reopening %pB: %s"),
                      abfd, bfd_errmsg (bfd_get_error ()));
   return NULL;
 }
index f0ca9048f68e270f04b1df6a60fd536ac20e5136..a5bc2de3648135e2a304041b169c7c1d827f1b87 100644 (file)
@@ -2107,10 +2107,28 @@ bfd_set_filename (bfd *abfd, const char *filename)
 {
   size_t len = strlen (filename) + 1;
   char *n = bfd_alloc (abfd, len);
-  if (n)
+
+  if (n == NULL)
+    return NULL;
+
+  if (abfd->filename != NULL)
     {
-      memcpy (n, filename, len);
-      abfd->filename = n;
+      /* PR 29389.  If we attempt to rename a file that has been closed due
+        to caching, then we will not be able to reopen it later on.  */
+      if (abfd->iostream == NULL && (abfd->flags & BFD_CLOSED_BY_CACHE))
+       {
+         bfd_set_error (bfd_error_invalid_operation);
+         return NULL;
+       }
+
+      /* Similarly if we attempt to close a renamed file because the
+        cache is now full, we will not be able to reopen it later on.  */
+      if (abfd->iostream != NULL)
+       abfd->cacheable = 0;
     }
+
+  memcpy (n, filename, len);
+  abfd->filename = n;
+
   return n;
 }
index 30fc1937d069ff47c0bf4306e66148b94f88ffc1..06dd21bfd47bb3a2e3fdbd8d4d35e5a90ae81d99 100644 (file)
@@ -1,3 +1,14 @@
+2022-08-03  Alan Modra  <amodra@gmail.com>
+
+       PR 29389
+       * ldlang.h (lang_input_statement_struct): Add sort_key field.
+       * emultempl/pe.em (after_open): If multiple import libraries refer
+       to the same bfd, store their names in the sort_key field.
+       * emultempl/pep.em (after_open): Likewise.
+       * ldlang.c (sort_filename): New function.  Returns the filename to
+       be used when sorting input files.
+       (wild_sort): Use the sort_filename function.
+
 2022-07-29  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        PR ld/29411
index 2fd4ff4acafaa73d5e9d9ec3dd914d0a4696c3c7..ad969ccec131f0f29cf54eaf821322880fe71f93 100644 (file)
@@ -1583,6 +1583,7 @@ gld${EMULATION_NAME}_after_open (void)
                      {
                        struct bfd_symbol *s;
                        struct bfd_link_hash_entry * blhe;
+                       bfd *other_bfd;
                        const char *other_bfd_filename;
 
                        s = (relocs[i]->sym_ptr_ptr)[0];
@@ -1599,20 +1600,25 @@ gld${EMULATION_NAME}_after_open (void)
                            || blhe->type != bfd_link_hash_defined)
                          continue;
 
+                       other_bfd = blhe->u.def.section->owner;
+                       if (other_bfd->my_archive == is->the_bfd->my_archive)
+                         continue;
+
                        other_bfd_filename
-                         = blhe->u.def.section->owner->my_archive
-                           ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
-                           : bfd_get_filename (blhe->u.def.section->owner);
+                         = (other_bfd->my_archive
+                            ? bfd_get_filename (other_bfd->my_archive)
+                            : bfd_get_filename (other_bfd));
 
                        if (filename_cmp (bfd_get_filename
                                            (is->the_bfd->my_archive),
                                          other_bfd_filename) == 0)
                          continue;
 
-                       /* Rename this implib to match the other one.  */
-                       if (!bfd_set_filename (is->the_bfd->my_archive,
-                                              other_bfd_filename))
-                         einfo ("%F%P: %pB: %E\n", is->the_bfd);
+                       /* Sort this implib to match the other one.  */
+                       lang_input_statement_type *arch_is
+                         = bfd_usrdata (is->the_bfd->my_archive);
+                       arch_is->sort_key = other_bfd_filename;
+                       break;
                      }
 
                    free (relocs);
@@ -1719,10 +1725,7 @@ gld${EMULATION_NAME}_after_open (void)
                  = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
                sprintf (new_name, "%s.%c",
                         bfd_get_filename (is->the_bfd), seq);
-               is->filename = bfd_set_filename (is->the_bfd, new_name);
-               free (new_name);
-               if (!is->filename)
-                 einfo ("%F%P: %pB: %E\n", is->the_bfd);
+               is->sort_key = new_name;
              }
          }
       }
index e68d1e69f17ad73af065b6bed19ae89ded913172..ee36a9a7e564fdcc117bd2d599927382906c1446 100644 (file)
@@ -1547,6 +1547,7 @@ gld${EMULATION_NAME}_after_open (void)
                      {
                        struct bfd_symbol *s;
                        struct bfd_link_hash_entry * blhe;
+                       bfd *other_bfd;
                        const char *other_bfd_filename;
 
                        s = (relocs[i]->sym_ptr_ptr)[0];
@@ -1563,20 +1564,25 @@ gld${EMULATION_NAME}_after_open (void)
                            || blhe->type != bfd_link_hash_defined)
                          continue;
 
+                       other_bfd = blhe->u.def.section->owner;
+                       if (other_bfd->my_archive == is->the_bfd->my_archive)
+                         continue;
+
                        other_bfd_filename
-                         = blhe->u.def.section->owner->my_archive
-                           ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
-                           : bfd_get_filename (blhe->u.def.section->owner);
+                         = (other_bfd->my_archive
+                            ? bfd_get_filename (other_bfd->my_archive)
+                            : bfd_get_filename (other_bfd));
 
                        if (filename_cmp (bfd_get_filename
                                            (is->the_bfd->my_archive),
                                          other_bfd_filename) == 0)
                          continue;
 
-                       /* Rename this implib to match the other one.  */
-                       if (!bfd_set_filename (is->the_bfd->my_archive,
-                                              other_bfd_filename))
-                         einfo ("%F%P: %pB: %E\n", is->the_bfd);
+                       /* Sort this implib to match the other one.  */
+                       lang_input_statement_type *arch_is
+                         = bfd_usrdata (is->the_bfd->my_archive);
+                       arch_is->sort_key = other_bfd_filename;
+                       break;
                      }
 
                    free (relocs);
@@ -1683,10 +1689,7 @@ gld${EMULATION_NAME}_after_open (void)
                  = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3);
                sprintf (new_name, "%s.%c",
                         bfd_get_filename (is->the_bfd), seq);
-               is->filename = bfd_set_filename (is->the_bfd, new_name);
-               free (new_name);
-               if (!is->filename)
-                 einfo ("%F%P: %pB: %E\n", is->the_bfd);
+               is->sort_key = new_name;
              }
          }
       }
index e7bc9f2d268a46fc61753e8e42a1fff8b48875ad..b7bb4a3aedad405488b31e4c95a3cb61d04b512a 100644 (file)
@@ -1125,6 +1125,7 @@ new_afile (const char *name,
   p->flags.add_DT_NEEDED_for_regular = input_flags.add_DT_NEEDED_for_regular;
   p->flags.whole_archive = input_flags.whole_archive;
   p->flags.sysrooted = input_flags.sysrooted;
+  p->sort_key = NULL;
 
   switch (file_type)
     {
@@ -2723,6 +2724,17 @@ lang_add_section (lang_statement_list_type *ptr,
   new_section->pattern = pattern;
 }
 
+/* PE puts the sort key in the input statement.  */
+
+static const char *
+sort_filename (bfd *abfd)
+{
+  lang_input_statement_type *is = bfd_usrdata (abfd);
+  if (is->sort_key)
+    return is->sort_key;
+  return bfd_get_filename (abfd);
+}
+
 /* Handle wildcard sorting.  This returns the lang_input_section which
    should follow the one we are going to create for SECTION and FILE,
    based on the sorting requirements of WILD.  It returns NULL if the
@@ -2762,28 +2774,17 @@ wild_sort (lang_wild_statement_type *wild,
             the archive and then the name of the file within the
             archive.  */
 
-         if (file->the_bfd != NULL
-             && file->the_bfd->my_archive != NULL)
-           {
-             fn = bfd_get_filename (file->the_bfd->my_archive);
-             fa = true;
-           }
+         fa = file->the_bfd->my_archive != NULL;
+         if (fa)
+           fn = sort_filename (file->the_bfd->my_archive);
          else
-           {
-             fn = file->filename;
-             fa = false;
-           }
+           fn = sort_filename (file->the_bfd);
 
-         if (ls->section->owner->my_archive != NULL)
-           {
-             ln = bfd_get_filename (ls->section->owner->my_archive);
-             la = true;
-           }
+         la = ls->section->owner->my_archive != NULL;
+         if (la)
+           ln = sort_filename (ls->section->owner->my_archive);
          else
-           {
-             ln = bfd_get_filename (ls->section->owner);
-             la = false;
-           }
+           ln = sort_filename (ls->section->owner);
 
          i = filename_cmp (fn, ln);
          if (i > 0)
@@ -2794,9 +2795,9 @@ wild_sort (lang_wild_statement_type *wild,
          if (fa || la)
            {
              if (fa)
-               fn = file->filename;
+               fn = sort_filename (file->the_bfd);
              if (la)
-               ln = bfd_get_filename (ls->section->owner);
+               ln = sort_filename (ls->section->owner);
 
              i = filename_cmp (fn, ln);
              if (i > 0)
index 95f6e468b300c688a764df2c56cc1cf35702c5ce..b853cdbd45f406e540a42786912df8e9a17396f9 100644 (file)
@@ -305,6 +305,8 @@ typedef struct lang_input_statement_struct
      Usually the same as filename, but for a file spec'd with
      -l this is the -l switch itself rather than the filename.  */
   const char *local_sym_name;
+  /* Name to use when sorting.  */
+  const char *sort_key;
   /* Extra search path. Used to find a file relative to the
      directory of the current linker script.  */
   const char *extra_search_path;