]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Remove bfd_check_format_lto
authorAlan Modra <amodra@gmail.com>
Tue, 5 Aug 2025 11:48:44 +0000 (21:18 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 5 Aug 2025 23:23:19 +0000 (08:53 +0930)
Tidy changes to bfd_check_format_matches made by commit 9b854f169df9
which added a bfd_plugin_specified_p test and commit f752be8f916e
which added an lto_sections_removed arg.  Both of these changes are
unnecessary if plugin_format is set to bfd_plugin_no before calling
bfd_check_format.  bfd_plugin_no will prevent the plugin object_p
function from returning a match (and in the first case from a segfault
when loading plugins while a plugin is running).  The plugin object_p
function already protected itself from recursive calls by setting
bfd_plugin_no before loading a plugin, but commit 9b854f169df9 opened
new bfds so they were unprotected.

It isn't strictly necessary to test for bfd_plugin_no in
bfd_check_format_matches but I kept the check to minimise functional
changes.  Close inspection of the patch will notice I've added an
is_linker_input test too.  That also isn't strictly necessary, I
think, but the match_count test was for the linker.  See commit
999d6dff80fa.

PR 12291
PR 12430
PR 13298
PR 33198
bfd/
* format.c (bfd_check_format_lto): Revert to bfd_check_format.
(bfd_check_format_matches_lto): Revert to bfd_check_format_matches.
Correct comments.  Manage both the lto_sections_removed and
bfd_plugin_specified_p cases by testing for bfd_plugin_no.
* plugin.c (bfd_plugin_get_symbols_in_object_only): Set
plugin_format to bfd_plugin_no before checking new bfds.
(try_load_plugin): Comment setting bfd_plugin_no.
(bfd_plugin_specified_p): Delete.
* plugin.h (bfd_plugin_specified_p): Delete.
* bfd-in2.h: Regenerate.
binutils/
* objcopy.c (copy_archive): Replace bfd_check_format_lto calls
with bfd_check_format using plugin_format set to bfd_plugin_no.
(check_format_object): New function.
(copy_file): Use it.

bfd/bfd-in2.h
bfd/format.c
bfd/plugin.c
bfd/plugin.h
binutils/objcopy.c

index 2ff3e930bfa2fb441aa68bc81618747a576571a2..b013ef954da34a0b3c5a826e057691b0873efe25 100644 (file)
@@ -2903,15 +2903,8 @@ bool generic_core_file_matches_executable_p
    (bfd *core_bfd, bfd *exec_bfd);
 
 /* Extracted from format.c.  */
-bool bfd_check_format_lto (bfd *abfd, bfd_format format,
-    bool lto_sections_removed);
-
 bool bfd_check_format (bfd *abfd, bfd_format format);
 
-bool bfd_check_format_matches_lto
-   (bfd *abfd, bfd_format format, char ***matching,
-    bool lto_sections_removed);
-
 bool bfd_check_format_matches
    (bfd *abfd, bfd_format format, char ***matching);
 
index f3a0774af081ce445eeea1788b8cb97774a6dd46..d2bc318977c5ff645d2b16494976ecf15329fb44 100644 (file)
@@ -56,19 +56,16 @@ extern const size_t _bfd_target_vector_entries;
 
 /*
 FUNCTION
-       bfd_check_format_lto
+       bfd_check_format
 
 SYNOPSIS
-       bool bfd_check_format_lto (bfd *abfd, bfd_format format,
-                                  bool lto_sections_removed);
+       bool bfd_check_format (bfd *abfd, bfd_format format);
 
 DESCRIPTION
        Verify if the file attached to the BFD @var{abfd} is compatible
        with the format @var{format} (i.e., one of <<bfd_object>>,
        <<bfd_archive>> or <<bfd_core>>).
 
-       If LTO_SECTION_REMOVED is true, ignore plugin target.
-
        If the BFD has been set to a specific target before the
        call, only the named target and format combination is
        checked. If the target has not been set, or has been set to
@@ -102,31 +99,10 @@ DESCRIPTION
        itself.
 */
 
-bool
-bfd_check_format_lto (bfd *abfd, bfd_format format,
-                     bool lto_sections_removed)
-{
-  return bfd_check_format_matches_lto (abfd, format, NULL,
-                                      lto_sections_removed);
-}
-
-
-/*
-FUNCTION
-       bfd_check_format
-
-SYNOPSIS
-       bool bfd_check_format (bfd *abfd, bfd_format format);
-
-DESCRIPTION
-       Similar to bfd_check_format_plugin, except plugin target isn't
-       ignored.
-*/
-
 bool
 bfd_check_format (bfd *abfd, bfd_format format)
 {
-  return bfd_check_format_matches_lto (abfd, format, NULL, false);
+  return bfd_check_format_matches (abfd, format, NULL);
 }
 
 struct bfd_preserve
@@ -431,36 +407,32 @@ bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED)
 
 /*
 FUNCTION
-       bfd_check_format_matches_lto
+       bfd_check_format_matches
 
 SYNOPSIS
-       bool bfd_check_format_matches_lto
-         (bfd *abfd, bfd_format format, char ***matching,
-          bool lto_sections_removed);
+       bool bfd_check_format_matches
+         (bfd *abfd, bfd_format format, char ***matching);
 
 DESCRIPTION
        Like <<bfd_check_format>>, except when it returns FALSE with
-       <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
-       case, if @var{matching} is not NULL, it will be filled in with
-       a NULL-terminated list of the names of the formats that matched,
-       allocated with <<malloc>>.
+       <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.
+       In that case, if @var{matching} is not NULL, it will be filled
+       in with a NULL-terminated list of the names of the formats
+       that matched, allocated with <<malloc>>.
        Then the user may choose a format and try again.
 
        When done with the list that @var{matching} points to, the caller
        should free it.
-
-       If LTO_SECTION_REMOVED is true, ignore plugin target.
 */
 
 bool
-bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
-                             char ***matching,
-                             bool lto_sections_removed ATTRIBUTE_UNUSED)
+bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
 {
   extern const bfd_target binary_vec;
   const bfd_target * const *target;
   const bfd_target **matching_vector = NULL;
   const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
+  const bfd_target *fail_targ;
   int match_count, best_count, best_match;
   int ar_match_index;
   unsigned int initial_section_id = _bfd_section_id;
@@ -524,13 +496,14 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
   if (!bfd_preserve_save (abfd, &preserve, NULL))
     goto err_ret;
 
-  /* If the target type was explicitly specified, just check that target.
-     If LTO_SECTION_REMOVED is true, don't match the plugin target.  */
+  /* If the target type was explicitly specified, just check that target.  */
+  fail_targ = NULL;
   if (!abfd->target_defaulted
 #if BFD_SUPPORTS_PLUGINS
-      && (!lto_sections_removed || !bfd_plugin_target_p (abfd->xvec))
+      && !(abfd->plugin_format == bfd_plugin_no
+          && bfd_plugin_target_p (save_targ))
 #endif
-     )
+      )
     {
       if (bfd_seek (abfd, 0, SEEK_SET) != 0)   /* rewind! */
        goto err_ret;
@@ -554,10 +527,10 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
         target.  */
       if (format == bfd_archive && save_targ == &binary_vec)
        goto err_unrecog;
+      fail_targ = save_targ;
     }
 
-  /* Since the target type was defaulted, check them all in the hope
-     that one will be uniquely recognized.  */
+  /* Check all targets in the hope that one will be recognized.  */
   right_targ = NULL;
   ar_right_targ = NULL;
   match_targ = NULL;
@@ -571,25 +544,25 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
       void **high_water;
 
       /* The binary target matches anything, so don't return it when
-        searching.  Don't match the plugin target if we have another
-        alternative since we want to properly set the input format
-        before allowing a plugin to claim the file.  Also, don't
-        check the default target twice.   If LTO_SECTION_REMOVED is
-        true, don't match the plugin target.  */
+        searching.  Also, don't check the current target twice when
+        it has failed already.
+        Don't match the plugin target during linking if we have
+        another alternative since we want to properly set the input
+        format before allowing a plugin to claim the file.
+        Also as an optimisation don't match the plugin target when
+        abfd->plugin_format is set to bfd_plugin_no.  (This occurs
+        when LTO sections have been stripped or when we have a
+        recursive call here from the plugin object_p via
+        bfd_plugin_get_symbols_in_object_only.)  */
       if (*target == &binary_vec
+         || *target == fail_targ
 #if BFD_SUPPORTS_PLUGINS
-         || ((lto_sections_removed || match_count != 0)
+         || (((abfd->is_linker_input && match_count != 0)
+              || abfd->plugin_format == bfd_plugin_no)
              && bfd_plugin_target_p (*target))
 #endif
-         || (!abfd->target_defaulted && *target == save_targ))
-       continue;
-
-#if BFD_SUPPORTS_PLUGINS
-      /* If the plugin target is explicitly specified when a BFD file
-        is opened, don't check it twice.  */
-      if (bfd_plugin_specified_p () && bfd_plugin_target_p (*target))
+         )
        continue;
-#endif
 
       /* If we already tried a match, the bfd is modified and may
         have sections attached, which will confuse the next
@@ -831,32 +804,6 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
   return false;
 }
 
-/*
-FUNCTION
-       bfd_check_format_matches
-
-SYNOPSIS
-       bool bfd_check_format_matches
-         (bfd *abfd, bfd_format format, char ***matching);
-
-DESCRIPTION
-       Like <<bfd_check_format>>, except when it returns FALSE with
-       <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>.  In that
-       case, if @var{matching} is not NULL, it will be filled in with
-       a NULL-terminated list of the names of the formats that matched,
-       allocated with <<malloc>>.
-       Then the user may choose a format and try again.
-
-       When done with the list that @var{matching} points to, the caller
-       should free it.
-*/
-
-bool
-bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
-{
-  return bfd_check_format_matches_lto (abfd, format, matching, false);
-}
-
 /*
 FUNCTION
        bfd_set_format
index 1c72b748a8fa639348aa665dbb3b0995d53a4d05..ebdf2505cbc6c62908ba0605c58f09a59e6cf64a 100644 (file)
@@ -196,7 +196,10 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd)
             abfd->filename, bfd_errmsg (bfd_get_error ()));
          return;
        }
-      else if (!bfd_check_format (nbfd, bfd_object))
+      /* Prevent this recursive call into bfd_check_format from
+        attempting to load the plugin again while it is running.  */
+      nbfd->plugin_format = bfd_plugin_no;
+      if (!bfd_check_format (nbfd, bfd_object))
        {
          /* There is no object only section if it isn't a bfd_object
             file.  */
@@ -206,6 +209,7 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd)
     }
   else
     {
+      BFD_ASSERT (abfd->plugin_format == bfd_plugin_no);
       if (!bfd_check_format (abfd, bfd_object))
        {
          (*_bfd_error_handler)
@@ -239,6 +243,9 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd)
 
   /* Open the file containing object only section.  */
   nbfd = bfd_openr (object_only_file, NULL);
+  /* Prevent this recursive call into bfd_check_format from
+     attempting to load the plugin again while it is running.  */
+  nbfd->plugin_format = bfd_plugin_no;
   if (!bfd_check_format (nbfd, bfd_object))
     {
       (*_bfd_error_handler)
@@ -598,6 +605,10 @@ try_load_plugin (const char *pname,
   if (status != LDPS_OK)
     goto short_circuit;
 
+  /* Setting bfd_plugin_no here prevents recursive calls into
+     bfd_check_format from within the plugin (unless the plugin opens
+     another bfd.)  Attempting to load the plugin again while it is
+     running is *not* a good idea.  */
   abfd->plugin_format = bfd_plugin_no;
 
   if (!current_plugin->claim_file)
@@ -627,14 +638,6 @@ bfd_plugin_set_plugin (const char *p)
   plugin_name = p;
 }
 
-/* Return TRUE if a plugin library is used.  */
-
-bool
-bfd_plugin_specified_p (void)
-{
-  return plugin_list != NULL;
-}
-
 /* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
 
 bool
index f61e6168e2bbc76aef4214e62940675e4a484971..6acb5fa9c86b12189599730a6a62615b5345773f 100644 (file)
@@ -25,7 +25,6 @@ void bfd_plugin_set_program_name (const char *);
 int bfd_plugin_open_input (bfd *, struct ld_plugin_input_file *);
 void bfd_plugin_set_plugin (const char *);
 bool bfd_plugin_target_p (const bfd_target *);
-bool bfd_plugin_specified_p (void);
 bool bfd_link_plugin_object_p (bfd *);
 void register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *, bool));
 void bfd_plugin_close_file_descriptor (bfd *, int);
index 5774711abe63f5d6a5450241005c8bfa9aabe5c1..8bd523aba138c31274f5a11ed8a15751e057fe9c 100644 (file)
@@ -170,6 +170,8 @@ static bool sections_removed;
 #if BFD_SUPPORTS_PLUGINS
 /* TRUE if all GCC LTO sections are to be removed.  */
 static bool lto_sections_removed;
+#else
+#define lto_sections_removed false
 #endif
 
 /* TRUE if only some sections are to be copied.  */
@@ -3745,11 +3747,10 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
 
 #if BFD_SUPPORTS_PLUGINS
       /* Ignore plugin target if all LTO sections should be removed.  */
-      ok_object = bfd_check_format_lto (this_element, bfd_object,
-                                       lto_sections_removed);
-#else
-      ok_object = bfd_check_format (this_element, bfd_object);
+      if (lto_sections_removed)
+       this_element->plugin_format = bfd_plugin_no;
 #endif
+      ok_object = bfd_check_format (this_element, bfd_object);
 
       /* PR binutils/3110: Cope with archives
         containing multiple target types.  */
@@ -3863,6 +3864,25 @@ 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
@@ -3988,21 +4008,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
                         input_arch, target_defaulted))
        status = 1;
     }
-  else if (
-#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.  */
-          bfd_check_format_matches_lto (ibfd, bfd_object, &obj_matching,
-                                        lto_sections_removed)
-          || (lto_sections_removed
-              && bfd_check_format_matches_lto (ibfd, bfd_object,
-                                               &obj_matching, false))
-#else
-          bfd_check_format_matches_lto (ibfd, bfd_object, &obj_matching,
-                                        false)
-#endif
-          )
+  else if (check_format_object (ibfd, &obj_matching, lto_sections_removed))
     {
       bfd *obfd;
     do_copy: