aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2025-08-12 12:02:08 -0700
committerH.J. Lu <hjl.tools@gmail.com>2025-08-14 18:12:36 -0700
commit9b383903e73cd01f2fbe9728d0c31fea765ba8d6 (patch)
treeb8f340b8dbf1d8f45da4bf31f859b3b8baed9dd8
parentb8e690ef9e3f17e000acf5063daa016b660c6022 (diff)
downloadbinutils-master.zip
binutils-master.tar.gz
binutils-master.tar.bz2
strip: Treat slim GCC/LLVM IR objects the sameHEADmaster
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>
-rw-r--r--bfd/format.c66
-rw-r--r--binutils/objcopy.c32
-rw-r--r--ld/testsuite/ld-plugin/lto-binutils.exp34
-rw-r--r--ld/testsuite/ld-plugin/strip-1a-s-all.nd5
4 files changed, 70 insertions, 67 deletions
diff --git a/bfd/format.c b/bfd/format.c
index 25feb52..b74c624 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 bc07176..6d6df02 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -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
diff --git a/ld/testsuite/ld-plugin/lto-binutils.exp b/ld/testsuite/ld-plugin/lto-binutils.exp
index 4970e22..1e156e4 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 612ba6a..52265c2 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