[PATCH v2] strip: Treat slim GCC/LLVM IR objects the same

H.J. Lu hjl.tools@gmail.com
Thu Aug 14 22:27:54 GMT 2025


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 (copy_archive): Always copy slim IR object as unknown
	object.
	(copy_file): Likewise.

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                             | 66 +++++++++++++++---------
 binutils/objcopy.c                       | 10 ++--
 ld/testsuite/ld-plugin/lto-binutils.exp  | 34 ++++++------
 ld/testsuite/ld-plugin/strip-1a-s-all.nd |  5 +-
 4 files changed, 65 insertions(+), 50 deletions(-)

diff --git a/bfd/format.c b/bfd/format.c
index 25feb5266df..b74c6240f23 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -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;
     }
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index bc07176799a..cb894ca9262 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3765,9 +3765,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 +4065,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
diff --git a/ld/testsuite/ld-plugin/lto-binutils.exp b/ld/testsuite/ld-plugin/lto-binutils.exp
index 4970e2282cb..1e156e4fc78 100644
--- a/ld/testsuite/ld-plugin/lto-binutils.exp
+++ b/ld/testsuite/ld-plugin/lto-binutils.exp
@@ -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 \
diff --git a/ld/testsuite/ld-plugin/strip-1a-s-all.nd b/ld/testsuite/ld-plugin/strip-1a-s-all.nd
index 612ba6a39b1..52265c2eb3d 100644
--- a/ld/testsuite/ld-plugin/strip-1a-s-all.nd
+++ b/ld/testsuite/ld-plugin/strip-1a-s-all.nd
@@ -1,3 +1,6 @@
 #...
-[0-9a-f]* C _?__gnu_lto_slim
+ + U foo2
+ + U foo3
+0+ T foo1
+0+ T main
 #pass
-- 
2.50.1



More information about the Binutils mailing list