commit:     de495ba52b3a319cc60b6092f29134d7f6c77cfd
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Sun Aug  3 23:42:40 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sun Aug  3 23:42:40 2025 +0000
URL:        
https://gitweb.gentoo.org/proj/toolchain/binutils-patches.git/commit/?id=de495ba5

9999: add another strip LTO patch

Bug: https://sourceware.org/PR33246
Signed-off-by: Sam James <sam <AT> gentoo.org>

 ...-strip-Don-t-use-plugin-on-fat-IR-objects.patch | 427 +++++++++++++++++++++
 1 file changed, 427 insertions(+)

diff --git a/9999/0006-strip-Don-t-use-plugin-on-fat-IR-objects.patch 
b/9999/0006-strip-Don-t-use-plugin-on-fat-IR-objects.patch
new file mode 100644
index 0000000..5347343
--- /dev/null
+++ b/9999/0006-strip-Don-t-use-plugin-on-fat-IR-objects.patch
@@ -0,0 +1,427 @@
+https://sourceware.org/bugzilla/show_bug.cgi?id=33246#c10
+
+From d499c2eea8d7f74f89f55a5a740f0d43e0c46c9b Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <[email protected]>
+Date: Sun, 3 Aug 2025 10:28:40 -0700
+Subject: [PATCH] strip: Don't use plugin on fat IR objects
+
+Fat IR objects contains both regular sections and IR sections.  After
+
+717a38e9a02109fcbcb18bb2ec3aa251e2ad0a0d is the first bad commit
+commit 717a38e9a02109fcbcb18bb2ec3aa251e2ad0a0d (HEAD)
+Author: H.J. Lu <[email protected]>
+Date:   Sun May 4 05:12:46 2025 +0800
+
+    strip: Add GCC LTO IR support
+
+"strip --strip-debug" no longer strips debug sections in fat IR objects.
+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 it isn't a fat IR object.  For standalone fat IR
+object, it will be copied as non-IR object.  Debug sections and IR
+sections can be removed by strip as usual.
+
+bfd/
+
+       PR binutils/33246
+       * archive.c: Include "plugin-api.h" and "plugin.h" if plugin is
+       enabled.
+       (_bfd_compute_and_write_armap): Don't complain plugin is needed
+       when the plugin target is in use.
+       * bfd-in2.h: Regenerated.
+       * bfd.c (bfd): Add is_strip_input.
+       * format.c (bfd_set_lto_type): If there is .llvm.lto section,
+       set LTO type to lto_fat_ir_object.
+       (bfd_check_format_matches_lto): When called from strip, don't
+       treat archive member nor standalone fat IR object as an IR
+       object.  Set LTO type if IR sections won't be removed.
+       * plugin.c (bfd_plugin_get_symbols_in_object_only): Copy LTO
+       type derived from input sections.
+
+nm/
+
+       PR binutils/33246
+       * nm.c (filter_symbols): Don't complain plugin is needed when
+       the plugin target is in use.
+       (display_rel_file): Likewise.
+       * objcopy.c (copy_archive): Set the is_strip_input field to 1
+       on input archive member.
+       (copy_file): Set the is_strip_input field to 1 on input object.
+       (strip_main): Keep .gnu.debuglto_* sections unless all GCC LTO
+       sections will be removed.
+
+ld/
+
+       PR binutils/33246
+       * testsuite/ld-plugin/lto-binutils.exp (run_pr33246_test): New.
+       Run binutils/33246 tests with GCC and Clang.
+       * testsuite/ld-plugin/pr33246.c: New file.
+
+Signed-off-by: H.J. Lu <[email protected]>
+---
+ bfd/archive.c                           |  10 +-
+ bfd/bfd-in2.h                           |   3 +
+ bfd/bfd.c                               |   3 +
+ bfd/format.c                            |  21 +++-
+ bfd/plugin.c                            |   3 +
+ binutils/nm.c                           |   6 +-
+ binutils/objcopy.c                      |   9 ++
+ ld/testsuite/ld-plugin/lto-binutils.exp | 153 ++++++++++++++++++++++++
+ ld/testsuite/ld-plugin/pr33246.c        |   4 +
+ 9 files changed, 207 insertions(+), 5 deletions(-)
+ create mode 100644 ld/testsuite/ld-plugin/pr33246.c
+
+diff --git a/bfd/archive.c b/bfd/archive.c
+index c61d4b12658..c323fb4fbd3 100644
+--- a/bfd/archive.c
++++ b/bfd/archive.c
+@@ -141,6 +141,10 @@ SUBSECTION
+ #include "hashtab.h"
+ #include "filenames.h"
+ #include "bfdlink.h"
++#if BFD_SUPPORTS_PLUGINS
++#include "plugin-api.h"
++#include "plugin.h"
++#endif
+ 
+ #ifndef errno
+ extern int errno;
+@@ -2342,7 +2346,8 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int 
elength)
+         long symcount;
+         long src_count;
+ 
+-        if (bfd_get_lto_type (current) == lto_slim_ir_object
++        if (!bfd_plugin_target_p (current->xvec)
++            && bfd_get_lto_type (current) == lto_slim_ir_object
+             && report_plugin_err)
+           {
+             report_plugin_err = false;
+@@ -2398,7 +2403,8 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int 
elength)
+                         map = new_map;
+                       }
+ 
+-                    if (bfd_lto_slim_symbol_p (current,
++                    if (!bfd_plugin_target_p (current->xvec)
++                        && bfd_lto_slim_symbol_p (current,
+                                                syms[src_count]->name)
+                         && report_plugin_err)
+                       {
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 2ff3e930bfa..bcff44a0f44 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -2131,6 +2131,9 @@ 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 858ab5ce017..4aded6809bb 100644
+--- a/bfd/bfd.c
++++ b/bfd/bfd.c
+@@ -296,6 +296,9 @@ 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 f3a0774af08..f88b9be1adc 100644
+--- a/bfd/format.c
++++ b/bfd/format.c
+@@ -413,6 +413,11 @@ bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED)
+           abfd->object_only_section = sec;
+           break;
+         }
++      else if (strcmp (sec->name, ".llvm.lto") == 0)
++        {
++          type = lto_fat_ir_object;
++          break;
++        }
+       else if (lsection.major_version == 0
+                && startswith (sec->name, ".gnu.lto_.lto.")
+                && bfd_get_section_contents (abfd, sec, &lsection, 0,
+@@ -537,7 +542,16 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format 
format,
+ 
+       cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+ 
+-      if (cleanup)
++      /* 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 it
++       isn't a fat IR object.  For standalone fat IR object,
++       it will be copied as non-IR object.  */
++      if (cleanup
++        && (!abfd->is_strip_input
++            || !bfd_plugin_target_p (abfd->xvec)
++            || (abfd->lto_type != lto_fat_ir_object
++                && abfd->my_archive == NULL)))
+       goto ok_ret;
+ 
+       /* For a long time the code has dropped through to check all
+@@ -621,6 +635,11 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format 
format,
+       {
+         int match_priority = abfd->xvec->match_priority;
+ 
++        /* Set LTO type if IR sections won't be removed so that it
++           can be checked for fat and slim IR objects.  */
++        if (!lto_sections_removed)
++          bfd_set_lto_type (abfd);
++
+         if (abfd->format != bfd_archive
+             || (bfd_has_map (abfd)
+                 && bfd_get_error () != bfd_error_wrong_object_format))
+diff --git a/bfd/plugin.c b/bfd/plugin.c
+index 1c72b748a8f..6dd22d75137 100644
+--- a/bfd/plugin.c
++++ b/bfd/plugin.c
+@@ -203,6 +203,9 @@ bfd_plugin_get_symbols_in_object_only (bfd *abfd)
+         bfd_close (nbfd);
+         return;
+       }
++
++      /* Copy LTO type derived from input sections.  */
++      abfd->lto_type = nbfd->lto_type;
+     }
+   else
+     {
+diff --git a/binutils/nm.c b/binutils/nm.c
+index a5d56311dde..94333042ee2 100644
+--- a/binutils/nm.c
++++ b/binutils/nm.c
+@@ -801,7 +801,8 @@ filter_symbols (bfd *abfd, bool is_dynamic, void *minisyms,
+       if (sym == NULL)
+       continue;
+ 
+-      if (bfd_lto_slim_symbol_p (abfd, sym->name)
++      if (!bfd_plugin_target_p (abfd->xvec)
++        && bfd_lto_slim_symbol_p (abfd, sym->name)
+         && report_plugin_err)
+       {
+         report_plugin_err = false;
+@@ -1484,7 +1485,8 @@ display_rel_file (bfd *abfd, bfd *archive_bfd)
+ 
+   /* lto_type is set to lto_non_ir_object when a bfd is loaded with a
+      compiler LTO plugin.  */
+-  if (bfd_get_lto_type (abfd) == lto_slim_ir_object)
++  if (!bfd_plugin_target_p (abfd->xvec)
++      && bfd_get_lto_type (abfd) == lto_slim_ir_object)
+     {
+       report_plugin_err = false;
+       non_fatal (_("%s: plugin needed to handle lto object"),
+diff --git a/binutils/objcopy.c b/binutils/objcopy.c
+index 5774711abe6..1f3b288be00 100644
+--- a/binutils/objcopy.c
++++ b/binutils/objcopy.c
+@@ -3687,6 +3687,8 @@ 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.  */
+@@ -3946,6 +3948,8 @@ copy_file (const char *input_filename, const char 
*output_filename, int ofd,
+       break;
+     }
+ 
++  ibfd->is_strip_input = 1;
++
+   if (bfd_check_format (ibfd, bfd_archive))
+     {
+       bool force_output_target;
+@@ -5066,6 +5070,11 @@ strip_main (int argc, char *argv[])
+                                              SECTION_CONTEXT_REMOVE)
+                         || !!find_section_list (".llvm.lto", false,
+                                              SECTION_CONTEXT_REMOVE));
++  /* NB: Must keep .gnu.debuglto_* sections unless all GCC LTO sections
++     will be removed to avoid undefined references to symbols in GCC LTO
++     debug sections.  */
++  if (!lto_sections_removed)
++    find_section_list (".gnu.debuglto_*", true, SECTION_CONTEXT_KEEP);
+ #endif
+ 
+   i = optind;
+diff --git a/ld/testsuite/ld-plugin/lto-binutils.exp 
b/ld/testsuite/ld-plugin/lto-binutils.exp
+index 88d35171045..9d19aa0c57e 100644
+--- a/ld/testsuite/ld-plugin/lto-binutils.exp
++++ b/ld/testsuite/ld-plugin/lto-binutils.exp
+@@ -355,3 +355,156 @@ run_cc_link_tests [list \
+       "tmpdir/libstrip-1b-fat-s.a" \
+     ] \
+ ]
++
++proc run_pr33246_test { llvm fat } {
++    global srcdir
++    global subdir
++    global plug_opt
++    global llvm_plug_opt
++    global ar
++    global CLANG_FOR_TARGET
++    global CC_FOR_TARGET
++    global NM
++    global READELF
++    global strip
++
++    set strip_flags "--strip-debug"
++
++    set test pr33246
++    set testname "${test}${llvm}${fat} with $strip_flags"
++
++    if { "$llvm" == "-llvm" } {
++      # Skip native x32 and i?86 targets since system LLVMgold.so may
++      # not be compatible with native x32 and i?86 targets binutils.
++      if { [istarget "x86_64-*-linux*-gnux32"]
++           || [istarget "i?86-*-*"]
++           || ![info exists CLANG_FOR_TARGET]
++           || [string match "" $llvm_plug_opt] } then {
++          untested $testname
++          return
++      }
++      set CC $CLANG_FOR_TARGET
++      set binutils_plug_opt "$llvm_plug_opt"
++    } else {
++      if { ![info exists CC_FOR_TARGET]
++           || [string match "" $plug_opt] } then {
++          untested $testname
++          return
++      }
++      set CC $CC_FOR_TARGET
++      set binutils_plug_opt "$plug_opt"
++    }
++
++    append strip_flags " $binutils_plug_opt"
++
++    set src $srcdir/$subdir/${test}.c
++    set obj tmpdir/${test}${llvm}${fat}.o
++    set archive tmpdir/${test}${llvm}${fat}.a
++    set CFLAGS "-c -g -O2 -flto"
++    if { "$fat" == "-fat" } {
++      append CFLAGS " -ffat-lto-objects"
++    } else {
++      append CFLAGS " -fno-fat-lto-objects"
++    }
++
++    set cmd "$CC $CFLAGS -o $obj $src"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![string match "" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname ($obj)"
++      return
++    }
++
++    set cmd "$strip $strip_flags $obj -o ${obj}.strip"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![string match "" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname (strip $obj)"
++      return
++    }
++
++    set cmd "$NM $binutils_plug_opt ${obj}.strip"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![regexp "0+ T foo" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname (strip $obj)"
++      return
++    }
++
++    if { "$fat" == "-fat" } {
++      set cmd "$READELF -SW ${obj}.strip"
++      send_log "$cmd\n"
++      verbose "$cmd" 1
++      catch "exec $cmd" got
++      if [regexp " \.debug_" $got] then {
++          send_log "$got\n"
++          verbose "$got" 1
++          fail "$testname (strip $obj)"
++          return
++      }
++    }
++
++    pass "$testname (strip $obj)"
++
++    set cmd "$ar $binutils_plug_opt -s -r -c $archive $obj"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![string match "" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname ($archive)"
++      return
++    }
++
++    set cmd "$strip $strip_flags $archive -o ${archive}.strip"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![string match "" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname (strip $archive)"
++      return
++    }
++
++    set cmd "$NM $binutils_plug_opt ${archive}.strip"
++    send_log "$cmd\n"
++    verbose "$cmd" 1
++    catch "exec $cmd" got
++    if ![regexp "0+ T foo" $got] then {
++      send_log "$got\n"
++      verbose "$got" 1
++      fail "$testname (strip $archive)"
++      return
++    }
++
++    if { "$fat" == "-fat" } {
++      set cmd "$READELF -SW ${archive}.strip"
++      send_log "$cmd\n"
++      verbose "$cmd" 1
++      catch "exec $cmd" got
++      if [regexp " \.debug_" $got] then {
++          send_log "$got\n"
++          verbose "$got" 1
++          fail "$testname (strip $archive)"
++          return
++      }
++    }
++
++    pass "$testname (strip $archive)"
++}
++
++run_pr33246_test "" ""
++run_pr33246_test "" "-fat"
++run_pr33246_test "-llvm" ""
++run_pr33246_test "-llvm" "-fat"
+diff --git a/ld/testsuite/ld-plugin/pr33246.c 
b/ld/testsuite/ld-plugin/pr33246.c
+new file mode 100644
+index 00000000000..cd0130cacdf
+--- /dev/null
++++ b/ld/testsuite/ld-plugin/pr33246.c
+@@ -0,0 +1,4 @@
++void
++foo (void)
++{
++}
+-- 
+2.50.1

Reply via email to