objcopy/strip of IR files and is_strip_input

Alan Modra amodra@gmail.com
Mon Aug 11 10:23:31 GMT 2025


This tidies objcopy/strip handling of IR objects, in the process of
removing the unnecessary is_strip_input flag.

The first thing I noticed when looking at is_strip_input code was that
the abfd->my_archive test in bfd_check_format_matches meant that
plugins were disabled when reading archive elements.  We can instead
disable plugins by setting bfd_no_plugin, so there doesn't seem to be
a need for is_strip_input in objcopy.c:copy_archive.  This isn't
exactly the same, because bfd_no_plugin prevents the plugin target
recognising archive elements in the bfd_check_format_matches loop over
all targets as well as just the first !target_defaulted test.  But
that turns out to be fine.  IR code is handled in copy_archive as for
other unknown format files.  In fact, the only need for the plugin
target when copying archives is when reading symbols for the archive
map.  I've made that plain by moving the plugin target override and
commenting on why it is really needed.

So on to plain object files.  Here, IR code is also copied unchanged,
so there doesn't seem a need for the plugin target there either.  It
isn't quite so simple though, because the objcopy/strip code handling
object files wants to verify the format of the object file.  Allowing
objcopy/strip to copy unknown format files would be a change in
behaviour (and results in mmix testsuite fails, ld-mmix/b-badfil1 and
others).  However, always excluding the plugin target results in a
fail of tests added in commit c2729c37f10a.  So I've enabled a plugin
format check only for files that are otherwise unrecognised, and
commented why this is done.  I question the need to objcopy LLVM
bytecode files.

Another thing (not done in this patch): I think that both places where
we do something special with lto_slim_ir_object can be removed too,
but that causes
FAIL: pr33246 with --strip-debug --enable-deterministic-archives (strip tmpdir/pr33246.o)
due to strip-debug removing the FILE symbol but otherwise leaving the
object file good.  ie. the test is too restrictive IMO.  Is it true
that no one will ever want to manipulate slim IR files?  (Apart from
the currently allowed removal of all IR sections.)

bfd/
	* bfd.c (struct bfd<is_strip_input>): Delete.
	* format.c (bfd_check_format_matches): Delete is_strip_input
	special case code.
	* bfd-in2.h: Regenerate.
binutils/
	* objcopy.c (copy_archive): Don't set is_strip_input.  Always
	set bfd_plugin_no when reading elements.  Enable plugins when
	opening copied elements.
	(check_format_object): Delete.
	(copy_file): Don't enable plugin target here.  Don't set
	is_strip_input.  Set bfd_plugin_no.  Move bfd_core handling
	code earlier to remove goto.  Enable plugin for llvm bytecode.
	Copy slim IR files as unknown objects.

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 12512a3962c..b013ef954da 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2131,9 +2131,6 @@ struct bfd
   /* Set if this is the linker input BFD.  */
   unsigned int is_linker_input : 1;
 
-  /* Set if this is the strip input BFD.  */
-  unsigned int is_strip_input : 1;
-
   /* If this is an input for a compiler plug-in library.  */
   ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
 
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 4aded6809bb..858ab5ce017 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -296,9 +296,6 @@ CODE_FRAGMENT
 .  {* Set if this is the linker input BFD.  *}
 .  unsigned int is_linker_input : 1;
 .
-.  {* Set if this is the strip input BFD.  *}
-.  unsigned int is_strip_input : 1;
-.
 .  {* If this is an input for a compiler plug-in library.  *}
 .  ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
 .
diff --git a/bfd/format.c b/bfd/format.c
index fba8d2a3d37..25feb5266df 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -511,20 +511,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 
       cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
 
-      /* When called from strip, don't treat archive member nor
-	 standalone fat IR object as an IR object.  For archive
-	 member, it will be copied as an unknown object if the
-	 plugin target is in use or it is a slim IR object.  For
-	 standalone fat IR object, it will be copied as non-IR
-	 object.  */
-      if (cleanup
-#if BFD_SUPPORTS_PLUGINS
-	  && (!abfd->is_strip_input
-	      || !bfd_plugin_target_p (abfd->xvec)
-	      || (abfd->lto_type != lto_fat_ir_object
-		  && abfd->my_archive == NULL))
-#endif
-	  )
+      if (cleanup)
 	goto ok_ret;
 
       /* For a long time the code has dropped through to check all
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 654d2b9b44a..bc07176799a 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3690,8 +3690,6 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
       bool ok_object;
       const char *element_name;
 
-      this_element->is_strip_input = 1;
-
       element_name = bfd_get_filename (this_element);
       /* PR binutils/17533: Do not allow directory traversal
 	 outside of the current directory tree by archive members.  */
@@ -3748,11 +3746,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
       l->obfd = NULL;
       list = l;
 
-#if BFD_SUPPORTS_PLUGINS
-      /* Ignore plugin target if all LTO sections should be removed.  */
-      if (lto_sections_removed)
-	this_element->plugin_format = bfd_plugin_no;
-#endif
+      this_element->plugin_format = bfd_plugin_no;
       ok_object = bfd_check_format (this_element, bfd_object);
 
       /* PR binutils/3110: Cope with archives
@@ -3772,11 +3766,9 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
 
 #if BFD_SUPPORTS_PLUGINS
       /* Copy LTO IR file as unknown object.  */
-      if ((!lto_sections_removed
-	   && this_element->lto_type == lto_slim_ir_object)
-	  || bfd_plugin_target_p (this_element->xvec))
+      if (!lto_sections_removed
+	  && this_element->lto_type == lto_slim_ir_object)
 	ok_object = false;
-      else
 #endif
       if (ok_object)
 	{
@@ -3811,8 +3803,15 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
 	  if (preserve_dates && stat_status == 0)
 	    set_times (output_name, &buf);
 
-	  /* Open the newly created output file and attach to our list.  */
-	  output_element = bfd_openr (output_name, output_target);
+	  /* Open the newly created output file and attach to our
+	     list.  We must enable the plugin target here in order to
+	     read IR symbols for the archive map.  */
+	  const char *targ = output_target;
+#if BFD_SUPPORTS_PLUGINS
+	  if (!force_output_target)
+	    targ = "plugin";
+#endif
+	  output_element = bfd_openr (output_name, targ);
 
 	  list->obfd = output_element;
 
@@ -3869,25 +3868,6 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
   return ok;
 }
 
-static bool
-check_format_object (bfd *ibfd, char ***obj_matching,
-		     bool no_plugins ATTRIBUTE_UNUSED)
-{
-#if BFD_SUPPORTS_PLUGINS
-  /* Ignore plugin target first if all LTO sections should be
-     removed.  Try with plugin target next if ignoring plugin
-     target fails to match the format.  */
-  if (no_plugins && ibfd->plugin_format == bfd_plugin_unknown)
-    {
-      ibfd->plugin_format = bfd_plugin_no;
-      if (bfd_check_format_matches (ibfd, bfd_object, obj_matching))
-	return true;
-      ibfd->plugin_format = bfd_plugin_unknown;
-    }
-#endif
-  return bfd_check_format_matches (ibfd, bfd_object, obj_matching);
-}
-
 /* The top-level control.  */
 
 static void
@@ -3912,12 +3892,6 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
       return;
     }
 
-#if BFD_SUPPORTS_PLUGINS
-  /* Enable LTO plugin in strip.  */
-  if (is_strip && !target)
-    target = "plugin";
-#endif
-
   /* To allow us to do "strip *" without dying on the first
      non-object file, failures are nonfatal.  */
   ibfd = bfd_openr (input_filename, target);
@@ -3971,7 +3945,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
       break;
     }
 
-  ibfd->is_strip_input = 1;
+  ibfd->plugin_format = bfd_plugin_no;
 
   if (bfd_check_format (ibfd, bfd_archive))
     {
@@ -4014,16 +3988,66 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
       if (!copy_archive (ibfd, obfd, output_target, force_output_target,
 			 input_arch, target_defaulted))
 	status = 1;
+      return;
+    }
+
+  bool ok_plugin = false;
+  bool ok_object = bfd_check_format_matches (ibfd, bfd_object, &obj_matching);
+  bfd_error_type obj_error = bfd_get_error ();
+  bfd_error_type core_error = bfd_error_no_error;
+  if (!ok_object)
+    {
+      ok_object = bfd_check_format_matches (ibfd, bfd_core, &core_matching);
+      core_error = bfd_get_error ();
+      if (ok_object)
+	{
+	  if (obj_error == bfd_error_file_ambiguously_recognized)
+	    free (obj_matching);
+	  obj_error = bfd_error_no_error;
+	}
+#if BFD_SUPPORTS_PLUGINS
+      else
+	{
+	  /* This is for LLVM bytecode files, which are not ELF objects.
+	     Since objcopy/strip does nothing with these files except
+	     copy them whole perhaps we ought to just reject them?  */
+	  bfd_find_target ("plugin", ibfd);
+	  ibfd->plugin_format = bfd_plugin_unknown;
+	  ok_plugin = bfd_check_format (ibfd, bfd_object);
+	}
+#endif
+    }
+
+  if (obj_error == bfd_error_file_ambiguously_recognized)
+    {
+      if (core_error == bfd_error_file_ambiguously_recognized)
+	free (core_matching);
+      bfd_set_error (obj_error);
+      status = 1;
+      bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+      list_matching_formats (obj_matching);
     }
-  else if (check_format_object (ibfd, &obj_matching, lto_sections_removed))
+  else if (core_error == bfd_error_file_ambiguously_recognized)
+    {
+      status = 1;
+      bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+      list_matching_formats (core_matching);
+    }
+  else if (!ok_object && !ok_plugin)
+    {
+      status = 1;
+      bfd_set_error (obj_error);
+      bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+    }
+  else
     {
       bfd *obfd;
-    do_copy:
 
       /* bfd_get_target does not return the correct value until
 	 bfd_check_format succeeds.  */
-      if (output_target == NULL
-	  || strcmp (output_target, "default") == 0)
+      if (ok_object
+	  && (output_target == NULL
+	      || strcmp (output_target, "default") == 0))
 	output_target = bfd_get_target (ibfd);
 
       if (ofd >= 0)
@@ -4042,65 +4066,32 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
  	}
 
 #if BFD_SUPPORTS_PLUGINS
-      if (bfd_plugin_target_p (ibfd->xvec))
-	{
-	  /* Copy LTO IR file as unknown file.  */
-	  if (!copy_unknown_file (ibfd, obfd, in_stat->st_size,
-				  in_stat->st_mode))
-	    status = 1;
-	  else if (!bfd_close_all_done (obfd))
-	    status = 1;
-	}
-      else
+      /* Copy LTO IR file as unknown object.  */
+      if (!lto_sections_removed
+	  && ibfd->lto_type == lto_slim_ir_object)
+	ok_object = false;
 #endif
-	{
-	  if (! copy_object (ibfd, obfd, input_arch, target_defaulted))
-	    status = 1;
-
-	  /* PR 17512: file: 0f15796a.
-	     If the file could not be copied it may not be in a writeable
-	     state.  So use bfd_close_all_done to avoid the possibility of
-	     writing uninitialised data into the file.  */
-	  if (! (status ? bfd_close_all_done (obfd) : bfd_close (obfd)))
-	    {
-	      status = 1;
-	      bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
-	    }
-	}
+      if (ok_object
+	  ? !copy_object (ibfd, obfd, input_arch, target_defaulted)
+	  : !copy_unknown_file (ibfd, obfd,
+				in_stat->st_size, in_stat->st_mode))
+	status = 1;
 
-      if (!bfd_close (ibfd))
+      /* PR 17512: file: 0f15796a.
+	 If the file could not be copied it may not be in a writeable
+	 state.  So use bfd_close_all_done to avoid the possibility of
+	 writing uninitialised data into the file.  */
+      if (!(ok_object && !status ? bfd_close : bfd_close_all_done) (obfd))
 	{
 	  status = 1;
-	  bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+	  bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
 	}
     }
-  else
-    {
-      bfd_error_type obj_error = bfd_get_error ();
-      bfd_error_type core_error;
-
-      if (bfd_check_format_matches (ibfd, bfd_core, &core_matching))
-	{
-	  /* This probably can't happen..  */
-	  if (obj_error == bfd_error_file_ambiguously_recognized)
-	    free (obj_matching);
-	  goto do_copy;
-	}
 
-      core_error = bfd_get_error ();
-      /* Report the object error in preference to the core error.  */
-      if (obj_error != core_error)
-	bfd_set_error (obj_error);
-
-      bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
-
-      if (obj_error == bfd_error_file_ambiguously_recognized)
-	list_matching_formats (obj_matching);
-      if (core_error == bfd_error_file_ambiguously_recognized)
-	list_matching_formats (core_matching);
-
-      bfd_close (ibfd);
+  if (!bfd_close (ibfd))
+    {
       status = 1;
+      bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
     }
 }
 

-- 
Alan Modra


More information about the Binutils mailing list