prepare stub bfd for use as dynobj

Alan Modra amodra@gmail.com
Thu Aug 6 04:21:08 GMT 2026


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.
---
 bfd/elf32-arm.c            | 37 ++++++++++++++++++-------------------
 bfd/elf32-metag.c          | 24 +++++++++++++-----------
 bfd/elfnn-aarch64.c        | 21 +++++++++++++--------
 bfd/elfxx-aarch64.h        |  8 ++++----
 ld/emultempl/aarch64elf.em | 22 +++++++++++-----------
 ld/emultempl/metagelf.em   |  1 +
 6 files changed, 60 insertions(+), 53 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;
+    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;
-    }
+	/* 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 06e103cf6de..ca0a4b67321 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 mailing list