]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
strip: Treat slim GCC/LLVM IR objects the same
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 12 Aug 2025 19:02:08 +0000 (12:02 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 15 Aug 2025 01:12:36 +0000 (18:12 -0700)
Slim LLVM IR object is a standalone file whose first 4 bytes are 'B',
'C', 0xc0, 0xde.  GCC IR object is regular ELF object with sections
whose names start with .gnu.lto_.* or .gnu.debuglto_.*.  GCC IR object
uses a .gnu.lto_.lto.<some_hash> section to encode the LTO bytecode
information:

struct lto_section
{
  int16_t major_version;
  int16_t minor_version;
  unsigned char slim_object;

  /* Flags is a private field that is not defined publicly.  */
  uint16_t flags;
};

In slim GCC IR object, the slim_object field is non-zero.  Strip should
treat slim GCC/LLVM IR objects the same.  Since strip won't change slim
LLVM IR objects, it should leave slim GCC IR object unchanged even when
asked to remove all IR objects:

1. Set the lto_type field to lto_slim_ir_object for slim LLVM IR object.
2. Always copy slim IR object as unknown object.

bfd/

PR binutils/33271
* format.c (bfd_set_lto_type): Set the lto_type field to
lto_slim_ir_object for slim LLVM IR object.

binutils/

PR binutils/33271
* objcopy.c (lto_sections_removed): Removed.
(copy_archive): Always copy slim IR object as unknown object.
(copy_file): Likewise.
(strip_main): Updated.

ld/

PR binutils/33271
* testsuite/ld-plugin/lto-binutils.exp: Don't check if fat IR is
available when running slim IR tests.
* testsuite/ld-plugin/strip-1a-s-all.nd: Expect full symbol list.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
bfd/format.c
binutils/objcopy.c
ld/testsuite/ld-plugin/lto-binutils.exp
ld/testsuite/ld-plugin/strip-1a-s-all.nd

index 25feb5266df377afc846f504b7fde29c081cc2ca..b74c6240f239b0157fc261f6c3b37bcc8a56d665 100644 (file)
@@ -376,33 +376,49 @@ bfd_set_lto_type (bfd *abfd ATTRIBUTE_UNUSED)
             | (bfd_get_flavour (abfd) == bfd_target_elf_flavour
                ? EXEC_P : 0))) == 0)
     {
-      asection *sec;
+      asection *sec = abfd->sections;
       enum bfd_lto_object_type type = lto_non_ir_object;
-      struct lto_section lsection = { 0, 0, 0, 0 };
-      /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode information
-        section.  */
-      for (sec = abfd->sections; sec != NULL; sec = sec->next)
-       if (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
-         {
-           type = lto_mixed_object;
-           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,
-                                             sizeof (struct lto_section)))
-         {
-           if (lsection.slim_object)
-             type = lto_slim_ir_object;
-           else
-             type = lto_fat_ir_object;
+      if (sec == NULL)
+       {
+         /* If there are no sections, check for slim LLVM IR object whose
+            first 4 bytes are: 'B', 'C', 0xc0, 0xde.  */
+         bfd_byte llvm_ir_magic[4];
+         if (bfd_seek (abfd, 0, SEEK_SET) == 0
+             && bfd_read (llvm_ir_magic, 4, abfd) == 4
+             && llvm_ir_magic[0] == 'B'
+             && llvm_ir_magic[1] == 'C'
+             && llvm_ir_magic[2] == 0xc0
+             && llvm_ir_magic[3] == 0xde)
+           type = lto_slim_ir_object;
+       }
+      else
+       {
+         struct lto_section lsection = { 0, 0, 0, 0 };
+         /* GCC uses .gnu.lto_.lto.<some_hash> as a LTO bytecode
+            information section.  */
+         for (; sec != NULL; sec = sec->next)
+           if (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
+             {
+               type = lto_mixed_object;
+               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,
+                                                 sizeof (struct lto_section)))
+             {
+               if (lsection.slim_object)
+                 type = lto_slim_ir_object;
+               else
+                 type = lto_fat_ir_object;
          }
+       }
 
       abfd->lto_type = type;
     }
index bc07176799ae1e6a1cd0272aa3af20abb20a0793..6d6df024ec6533cae40945915ec7c38695018ece 100644 (file)
@@ -168,13 +168,6 @@ static struct section_list *change_sections;
 /* TRUE if some sections are to be removed.  */
 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.  */
 static bool sections_copied;
 
@@ -3765,9 +3758,8 @@ 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)
+      /* Copy slim LTO IR file as unknown object.  */
+      if (this_element->lto_type == lto_slim_ir_object)
        ok_object = false;
 #endif
       if (ok_object)
@@ -4066,9 +4058,8 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
        }
 
 #if BFD_SUPPORTS_PLUGINS
-      /* Copy LTO IR file as unknown object.  */
-      if (!lto_sections_removed
-         && ibfd->lto_type == lto_slim_ir_object)
+  /* Copy slim LTO IR file as unknown file.  */
+      if (ibfd->lto_type == lto_slim_ir_object)
        ok_object = false;
 #endif
       if (ok_object
@@ -5062,18 +5053,13 @@ strip_main (int argc, char *argv[])
 
 #if BFD_SUPPORTS_PLUGINS
   /* Check if all GCC LTO sections should be removed, assuming all LTO
-     sections will be removed with -R .gnu.lto_.*.  * Remove .gnu.lto_.*
-     sections will also remove .gnu.debuglto_.  sections.  LLVM IR
-     bitcode is stored in .llvm.lto section which will be removed with
-     -R .llvm.lto.  */
-  lto_sections_removed = (!!find_section_list (".gnu.lto_.*", false,
-                                              SECTION_CONTEXT_REMOVE)
-                         || !!find_section_list (".llvm.lto", false,
-                                              SECTION_CONTEXT_REMOVE));
-  /* NB: Must keep .gnu.debuglto_* sections unless all GCC LTO sections
+     sections will be removed with -R .gnu.lto_.*.  Remove .gnu.lto_.*
+     sections will also remove .gnu.debuglto_.* sections.
+
+     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)
+  if (!find_section_list (".gnu.lto_.*", false, SECTION_CONTEXT_REMOVE))
     find_section_list (".gnu.debuglto_*", true, SECTION_CONTEXT_KEEP);
 #endif
 
index 4970e2282cbf7e38bb6cd5abdd7183fb51e8ee67..1e156e4fc78e62d39bca934b9e2d33be06ce12dc 100644 (file)
@@ -254,24 +254,22 @@ run_lto_binutils_test [list \
     ] \
 ]
 
-if { [check_lto_fat_available] } {
-    run_lto_binutils_test [list \
-       [list \
-           "strip" \
-           "-R .gnu.*lto_* -N __gnu_lto_v1" \
-           "strip-1a.o" \
-           "strip-1a-s-all.o" \
-           {{nm -n strip-1a-s-all.nd}} \
-       ] \
-       [list \
-           "strip" \
-           "-R .gnu.*lto_* -N __gnu_lto_v1" \
-           "libstrip-1a.a" \
-           "libstrip-1a-s-all.a" \
-           {{nm -n strip-1a-s-all.nd}} \
-       ] \
-    ]
-}
+run_lto_binutils_test [list \
+    [list \
+       "strip" \
+       "-R .gnu.*lto_* -N __gnu_lto_v1" \
+       "strip-1a.o" \
+       "strip-1a-s-all.o" \
+       {{nm -n strip-1a-s-all.nd}} \
+    ] \
+    [list \
+       "strip" \
+       "-R .gnu.*lto_* -N __gnu_lto_v1" \
+       "libstrip-1a.a" \
+       "libstrip-1a-s-all.a" \
+       {{nm -n strip-1a-s-all.nd}} \
+    ] \
+]
 
 run_cc_link_tests [list \
     [list \
index 612ba6a39b13c9a375ef3ab71b0dbcc6b67e7829..52265c2eb3d4815b875cac2bd4fd1b81b5c5d47b 100644 (file)
@@ -1,3 +1,6 @@
 #...
-[0-9a-f]* C _?__gnu_lto_slim
+ + U foo2
+ + U foo3
+0+ T foo1
+0+ T main
 #pass