public inbox for binutils-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Fix a conflict between the linker's need to rename some PE format input libraries and the BFD librar
@ 2022-08-03 12:33 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2022-08-03 12:33 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a6ad7914429a22d3d835bd998b032212b776a08a

commit a6ad7914429a22d3d835bd998b032212b776a08a
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Aug 3 13:31:57 2022 +0100

    Fix a conflict between the linker's need to rename some PE format input libraries and the BFD library's file caching mechanism.
    
            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.

Diff:
---
 bfd/ChangeLog       | 13 +++++++++++++
 bfd/bfd-in2.h       |  2 ++
 bfd/bfd.c           |  2 ++
 bfd/cache.c         |  8 ++++++--
 bfd/opncls.c        | 24 +++++++++++++++++++++---
 ld/ChangeLog        | 11 +++++++++++
 ld/emultempl/pe.em  | 25 ++++++++++++++-----------
 ld/emultempl/pep.em | 25 ++++++++++++++-----------
 ld/ldlang.c         | 43 ++++++++++++++++++++++---------------------
 ld/ldlang.h         |  2 ++
 10 files changed, 107 insertions(+), 48 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index afabbc0f56a..cb1f48ba481 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 91ada0e3a94..a95e4a24cad 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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 \
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 3e85e171e3f..5e5272b9080 100644
--- 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 \
diff --git a/bfd/cache.c b/bfd/cache.c
index 8a6d359a789..73b68c7aff9 100644
--- a/bfd/cache.c
+++ b/bfd/cache.c
@@ -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;
 }
diff --git a/bfd/opncls.c b/bfd/opncls.c
index f0ca9048f68..a5bc2de3648 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -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;
 }
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 30fc1937d06..06dd21bfd47 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 2fd4ff4acaf..ad969ccec13 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -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;
 	      }
 	  }
       }
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index e68d1e69f17..ee36a9a7e56 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -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;
 	      }
 	  }
       }
diff --git a/ld/ldlang.c b/ld/ldlang.c
index e7bc9f2d268..b7bb4a3aeda 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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)
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 95f6e468b30..b853cdbd45f 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -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;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-03 12:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-03 12:33 [binutils-gdb] Fix a conflict between the linker's need to rename some PE format input libraries and the BFD librar Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).