[binutils-gdb] prepare stub bfd for use as dynobj

Alan Modra amodra@sourceware.org
Mon Aug 17 01:24:45 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b04b71c9f4bba70c79f7f52793d2c09640648515

commit b04b71c9f4bba70c79f7f52793d2c09640648515
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Aug 6 11:17:25 2026 +0930

    prepare stub bfd for use as dynobj
    
    There are a few wrinkles to using the stub bfd.  Target code that
    assumes the stub bfd sections are all stub sections must be corrected
    to test SEC_LINKER_CREATED.  Those without the flag are stub sections,
    those with SEC_LINKER_CREATED are dynamic.  Arm and aarch64 checked
    for stub sections by name, which was necessary when those sections
    were attached to object file bfds.  This patch updates that old code
    (which still would work, but strstr is more expensive than checking a
    flag).
    
    Another requirement is to properly set EI_CLASS for the stub bfd,
    in order to pass checks in _bfd_elf_final_link.
    
    bfd/
            * elf32-arm.c (elf32_arm_size_stubs): Don't look for
            STUB_SUFFIX in stub section name, just test SEC_LINKER_CREATED.
            (elf32_arm_build_stubs): Likewise.
            (elf32_arm_output_arch_local_syms): Likewise.  Omit stub_bfd check.
            (elf32_arm_filter_cmse_symbols): Likewise.
            * elfnn-aarch64.c (_bfd_aarch64_resize_stubs): Don't look for
            STUB_SUFFIX in stub section name, just test SEC_LINKER_CREATED.
            (elfNN_aarch64_build_stubs): Likewise.
            (elfNN_aarch64_output_arch_local_syms): Likewise.
            (elfNN_aarch64_size_stubs): Don't set stub_bfd here..
            (bfd_elfNN_aarch64_set_options): ..do so here instead.  Add
            stub_bfd param.  Delete output_bfd param.  Set stub_bfd flags
            and EI_CLASS.
            * elfxx-aarch64.h (bfd_elf64_aarch64_set_options),
            (bfd_elf32_aarch64_set_options): Update prototypes.
            * elf32-metag.c (elf_metag_size_stubs): Don't reset size of
            SEC_LINKER_CREATED sections.
            (elf_metag_build_stubs): Don't process SEC_LINKER_CREATED sections.
    ld/
            * emultempl/aarch64elf.em (aarch64_elf_create_output_section_statements):
            Call aarch64_set_options after creating stub bfd.  Don't set
            stub bfd flags here.
            * emultempl/metagelf.em (metagelf_create_output_section_statements):
            Set stub bfd EI_CLASS.

Diff:
---
 bfd/elf32-arm.c            | 37 ++++++++++++++++++-------------------
 bfd/elf32-metag.c          | 26 ++++++++++++++------------
 bfd/elfnn-aarch64.c        | 21 +++++++++++++--------
 bfd/elfxx-aarch64.h        |  8 ++++----
 ld/emultempl/aarch64elf.em | 22 +++++++++++-----------
 ld/emultempl/metagelf.em   |  1 +
 6 files changed, 61 insertions(+), 54 deletions(-)

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 252029a0ebf..b280cf5e069 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -6796,7 +6796,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 	   stub_sec = stub_sec->next)
 	{
 	  /* Ignore non-stub sections.  */
-	  if (!strstr (stub_sec->name, STUB_SUFFIX))
+	  if ((stub_sec->flags & SEC_LINKER_CREATED) != 0)
 	    continue;
 
 	  stub_sec->size = 0;
@@ -6943,7 +6943,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
       bfd_size_type size;
 
       /* Ignore non-stub sections.  */
-      if (!strstr (stub_sec->name, STUB_SUFFIX))
+      if ((stub_sec->flags & SEC_LINKER_CREATED) != 0)
 	continue;
 
       /* Allocate memory to hold the linker stubs.  Zeroing the stub sections
@@ -18118,26 +18118,21 @@ elf32_arm_output_arch_local_syms (struct bfd_link_info *info,
       elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0);
     }
 
-  /* Long calls stubs.  */
-  if (htab->stub_bfd && htab->stub_bfd->sections)
+  /* Long call stubs.  */
+  for (asection* stub_sec = htab->stub_bfd->sections;
+       stub_sec != NULL;
+       stub_sec = stub_sec->next)
     {
-      asection* stub_sec;
-
-      for (stub_sec = htab->stub_bfd->sections;
-	   stub_sec != NULL;
-	   stub_sec = stub_sec->next)
-	{
-	  /* Ignore non-stub sections.  */
-	  if (!strstr (stub_sec->name, STUB_SUFFIX))
-	    continue;
+      /* Ignore non-stub sections.  */
+      if ((stub_sec->flags & SEC_LINKER_CREATED) != 0)
+	continue;
 
-	  osi.sec = stub_sec;
+      osi.sec = stub_sec;
 
-	  osi.sec_shndx = _bfd_elf_section_from_bfd_section
-	    (info->output_bfd, osi.sec->output_section);
+      osi.sec_shndx = _bfd_elf_section_from_bfd_section
+	(info->output_bfd, osi.sec->output_section);
 
-	  bfd_hash_traverse (&htab->stub_hash_table, arm_map_one_stub, &osi);
-	}
+      bfd_hash_traverse (&htab->stub_hash_table, arm_map_one_stub, &osi);
     }
 
   /* Finally, output mapping symbols for the PLT.  */
@@ -18255,9 +18250,13 @@ elf32_arm_filter_cmse_symbols (struct bfd_link_info *info,
   char *cmse_name;
   size_t src_count, dst_count = 0;
   struct elf32_arm_link_hash_table *htab;
+  asection *stub_sec;
 
   htab = elf32_arm_hash_table (info);
-  if (!htab->stub_bfd || !htab->stub_bfd->sections)
+  for (stub_sec = htab->stub_bfd->sections; stub_sec; stub_sec = stub_sec->next)
+    if (!(stub_sec->flags & SEC_LINKER_CREATED))
+      break;
+  if (!stub_sec)
     symcount = 0;
 
   maxnamelen = 128;
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index f4d765e614f..1288c97b385 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -3895,7 +3895,8 @@ elf_metag_size_stubs(bfd *output_bfd, bfd *stub_bfd,
       for (stub_sec = htab->stub_bfd->sections;
 	   stub_sec != NULL;
 	   stub_sec = stub_sec->next)
-	stub_sec->size = 0;
+	if (!(stub_sec->flags & SEC_LINKER_CREATED))
+	  stub_sec->size = 0;
 
       bfd_hash_traverse (&htab->bstab, metag_size_one_stub, htab);
 
@@ -3928,17 +3929,18 @@ elf_metag_build_stubs (struct bfd_link_info *info)
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
-    {
-      bfd_size_type size;
-
-      /* Allocate memory to hold the linker stubs.  */
-      size = stub_sec->size;
-      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
-      if (stub_sec->contents == NULL && size != 0)
-	return false;
-      stub_sec->alloced = 1;
-      stub_sec->size = 0;
-    }
+    if (!(stub_sec->flags & SEC_LINKER_CREATED))
+      {
+	bfd_size_type size;
+
+	/* Allocate memory to hold the linker stubs.  */
+	size = stub_sec->size;
+	stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+	if (stub_sec->contents == NULL && size != 0)
+	  return false;
+	stub_sec->alloced = 1;
+	stub_sec->size = 0;
+      }
 
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->bstab;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index a1119bfbf31..2bbf21e8dc1 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4172,7 +4172,7 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
        section != NULL; section = section->next)
     {
       /* Ignore non-stub sections.  */
-      if (!strstr (section->name, STUB_SUFFIX))
+      if ((section->flags & SEC_LINKER_CREATED) != 0)
 	continue;
 
       /* Add space for a branch.  Add 8 bytes to keep section 8 byte aligned,
@@ -4185,7 +4185,7 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
   for (section = htab->stub_bfd->sections;
        section != NULL; section = section->next)
     {
-      if (!strstr (section->name, STUB_SUFFIX))
+      if ((section->flags & SEC_LINKER_CREATED) != 0)
 	continue;
 
       /* Empty stub section.  */
@@ -4761,7 +4761,6 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 		     bfd_get_mach (output_bfd));
 
   /* Stash our params away.  */
-  htab->stub_bfd = stub_bfd;
   htab->add_stub_section = add_stub_section;
   htab->layout_sections_again = layout_sections_again;
   stubs_always_before_branch = group_size < 0;
@@ -4868,7 +4867,7 @@ elfNN_aarch64_build_stubs (struct bfd_link_info *info)
       bfd_size_type size;
 
       /* Ignore non-stub sections.  */
-      if (!strstr (stub_sec->name, STUB_SUFFIX))
+      if ((stub_sec->flags & SEC_LINKER_CREATED) != 0)
 	continue;
 
       /* Allocate memory to hold the linker stubs.  */
@@ -5017,17 +5016,18 @@ setup_plt_values (struct bfd_link_info *link_info,
 
 /* Set option values needed during linking.  */
 void
-bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
-			       struct bfd_link_info *link_info,
+bfd_elfNN_aarch64_set_options (struct bfd_link_info *link_info,
 			       int no_enum_warn,
 			       int no_wchar_warn, int pic_veneer,
 			       int fix_erratum_835769,
 			       erratum_84319_opts fix_erratum_843419,
 			       int no_apply_dynamic_relocs,
 			       const aarch64_protection_opts *sw_protections,
-			       const aarch64_memtag_opts *memtag_opts)
+			       const aarch64_memtag_opts *memtag_opts,
+			       bfd *stub_bfd)
 {
   struct elf_aarch64_link_hash_table *globals;
+  bfd *output_bfd;
 
   globals = elf_aarch64_hash_table (link_info);
   globals->pic_veneer = pic_veneer;
@@ -5039,6 +5039,11 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
   globals->fix_erratum_843419 = fix_erratum_843419;
   globals->no_apply_dynamic_relocs = no_apply_dynamic_relocs;
 
+  globals->stub_bfd = stub_bfd;
+  stub_bfd->flags |= BFD_LINKER_CREATED;
+  elf_elfheader (stub_bfd)->e_ident[EI_CLASS] = ELFCLASSNN;
+
+  output_bfd = link_info->output_bfd;
   BFD_ASSERT (is_aarch64_elf (output_bfd));
   elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
   elf_aarch64_tdata (output_bfd)->no_wchar_size_warning = no_wchar_warn;
@@ -8742,7 +8747,7 @@ elfNN_aarch64_output_arch_local_syms (struct bfd_link_info *info,
 	   stub_sec != NULL; stub_sec = stub_sec->next)
 	{
 	  /* Ignore non-stub sections.  */
-	  if (!strstr (stub_sec->name, STUB_SUFFIX))
+	  if ((stub_sec->flags & SEC_LINKER_CREATED) != 0)
 	    continue;
 
 	  osi.sec = stub_sec;
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index a312427bc75..2c760c05f5e 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -158,12 +158,12 @@ struct aarch64_memtag_opts
 typedef struct aarch64_memtag_opts aarch64_memtag_opts;
 
 extern void bfd_elf64_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
-   const aarch64_protection_opts *, const aarch64_memtag_opts *);
+  (struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
+   const aarch64_protection_opts *, const aarch64_memtag_opts *, bfd *);
 
 extern void bfd_elf32_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
-   const aarch64_protection_opts *, const aarch64_memtag_opts *);
+  (struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
+   const aarch64_protection_opts *, const aarch64_memtag_opts *, bfd *);
 
 /* AArch64 stub generation support for ELF64.  Called from the linker.  */
 extern int elf64_aarch64_setup_section_lists
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
index 28b91871958..bedabfe9aa1 100644
--- a/ld/emultempl/aarch64elf.em
+++ b/ld/emultempl/aarch64elf.em
@@ -335,15 +335,6 @@ aarch64_elf_create_output_section_statements (void)
       return;
     }
 
-  bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
-				 no_enum_size_warning,
-				 no_wchar_size_warning,
-				 pic_veneer,
-				 fix_erratum_835769, fix_erratum_843419,
-				 no_apply_dynamic_relocs,
-				 &sw_protections,
-				 &memtag_opts);
-
   stub_file = lang_add_input_file ("linker stubs",
 				   lang_input_file_is_fake_enum,
 				   NULL);
@@ -356,9 +347,18 @@ aarch64_elf_create_output_section_statements (void)
       fatal (_("%P: can not create BFD: %E\n"));
       return;
     }
-
-  stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
   ldlang_add_file (stub_file);
+
+  bfd_elf${ELFSIZE}_aarch64_set_options (&link_info,
+				 no_enum_size_warning,
+				 no_wchar_size_warning,
+				 pic_veneer,
+				 fix_erratum_835769, fix_erratum_843419,
+				 no_apply_dynamic_relocs,
+				 &sw_protections,
+				 &memtag_opts,
+				 stub_file->the_bfd);
+
 }
 
 static bool
diff --git a/ld/emultempl/metagelf.em b/ld/emultempl/metagelf.em
index c2a9844f521..d571e090751 100644
--- a/ld/emultempl/metagelf.em
+++ b/ld/emultempl/metagelf.em
@@ -64,6 +64,7 @@ metagelf_create_output_section_statements (void)
     }
 
   stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
+  elf_elfheader (stub_file->the_bfd)->e_ident[EI_CLASS] = ELFCLASS32;
   ldlang_add_file (stub_file);
 }


More information about the Binutils-cvs mailing list