diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2025-08-12 12:02:08 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2025-08-14 18:12:36 -0700 |
commit | 9b383903e73cd01f2fbe9728d0c31fea765ba8d6 (patch) | |
tree | b8f340b8dbf1d8f45da4bf31f859b3b8baed9dd8 | |
parent | b8e690ef9e3f17e000acf5063daa016b660c6022 (diff) | |
download | binutils-master.zip binutils-master.tar.gz binutils-master.tar.bz2 |
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.c | 66 | ||||
-rw-r--r-- | binutils/objcopy.c | 32 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto-binutils.exp | 34 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1a-s-all.nd | 5 |
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 |