[PATCH v2 1/3] ld: bfd: sframe: KEEP .sframe sections and support gc-sections

claudiu.zissulescu-ianculescu@oracle.com claudiu.zissulescu-ianculescu@oracle.com
Wed Jan 14 10:05:31 GMT 2026


From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>

Fix PR ld/32769

Currently, specifying --gc-sections causes the linker to discard all
input .sframe sections.  Fix this behaviour by adding KEEP for .sframe
sections in the default ELF linker script.

Additionally, add logic in the linker to gc mark .sframe sections.
_bfd_elf_gc_mark () now is aware of SFrame sections. It relies on
elf_section_sframe () to get the SFrame section associated with the text
section.

The stub changes in bfd_elf_discard_info skip checking the return
value of _bfd_elf_parse_sframe because it may have already been
parsed.  Remove redundant call to _bfd_elf_set_section_sframe.

ld/
	PR ld/32769
	* scripttempl/elf.sc: KEEP .sframe sections.
bfd/
	* elf-bfd.h (struct elf_obj_tdata): Add sframe section pointer.
	(elf_sframe_section): New macro.
	* elflink.c (_bfd_elf_gc_mark): Handle SFrame sections.
	(bfd_elf_gc_sections): Likewise.
	(bfd_elf_discard_info): Update for handling gc operations.

Co-authored-by: Indu Bhagat <indu.bhagat@oracle.com>
Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
---
 bfd/elf-bfd.h         |  5 +++++
 bfd/elflink.c         | 43 ++++++++++++++++++++++++++++---------------
 ld/scripttempl/elf.sc |  4 ++--
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b2aeb2ba0ca..4a9d87f03a2 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2177,6 +2177,9 @@ struct elf_obj_tdata
   /* A pointer to the .eh_frame section.  */
   asection *eh_frame_section;
 
+  /* A pointer to the .sframe section.  */
+  asection *sframe_section;
+
   /* Symbol buffer.  */
   void *symbuf;
 
@@ -2258,6 +2261,8 @@ struct elf_obj_tdata
 #define elf_dynverref(bfd)	(elf_tdata(bfd) -> dynverref_section)
 #define elf_eh_frame_section(bfd) \
 				(elf_tdata(bfd) -> eh_frame_section)
+#define elf_sframe_section(bfd) \
+				(elf_tdata(bfd) -> sframe_section)
 #define elf_section_syms(bfd)	(elf_tdata(bfd) -> o->section_syms)
 #define elf_num_section_syms(bfd) (elf_tdata(bfd) -> o->num_section_syms)
 #define core_prpsinfo(bfd)	(elf_tdata(bfd) -> prpsinfo)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 64c1a57b465..7614dc7d4af 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -14151,7 +14151,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
 		  elf_gc_mark_hook_fn gc_mark_hook)
 {
   bool ret;
-  asection *group_sec, *eh_frame;
+  asection *group_sec, *eh_frame, *sframe;
 
   sec->gc_mark = 1;
 
@@ -14164,9 +14164,12 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
   /* Look through the section relocs.  */
   ret = true;
   eh_frame = elf_eh_frame_section (sec->owner);
+  sframe = elf_sframe_section (sec->owner);
+
   if ((sec->flags & SEC_RELOC) != 0
       && sec->reloc_count > 0
-      && sec != eh_frame)
+      && sec != eh_frame
+      && sec != sframe)
     {
       struct elf_reloc_cookie cookie;
 
@@ -14697,12 +14700,28 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
 						   false))
 	{
 	  _bfd_elf_parse_eh_frame (sub, info, sec, &cookie);
+	  if (sec->sec_info && (sec->flags & SEC_LINKER_CREATED) == 0)
+	    elf_eh_frame_section (sub) = sec;
+	  fini_reloc_cookie_for_section (&cookie, sec);
+	  sec = bfd_get_next_section_by_name (NULL, sec);
+	}
+
+      /* Now parse each .sframe section. Point each .sframe secto to
+	 each bfd.  */
+      sec = bfd_get_section_by_name (sub, ".sframe");
+      while (sec
+	     && init_reloc_cookie_for_section (&cookie, info, sec, false))
+	{
+	  _bfd_elf_parse_sframe (sub, info, sec, &cookie);
+
 	  if (sec->sec_info
 	      && (sec->flags & SEC_LINKER_CREATED) == 0)
-	    elf_eh_frame_section (sub) = sec;
+	    elf_sframe_section (sub) = sec;
+
 	  fini_reloc_cookie_for_section (&cookie, sec);
 	  sec = bfd_get_next_section_by_name (NULL, sec);
 	}
+
     }
 
   /* Apply transitive closure to the vtable entry usage info.  */
@@ -15302,22 +15321,16 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
 	  if (!init_reloc_cookie_for_section (&cookie, info, i, false))
 	    return -1;
 
-	  if (_bfd_elf_parse_sframe (abfd, info, i, &cookie))
+	  _bfd_elf_parse_sframe (abfd, info, i, &cookie);
+	  if (_bfd_elf_discard_section_sframe (i,
+					       bfd_elf_reloc_symbol_deleted_p,
+					       &cookie))
 	    {
-	      if (_bfd_elf_discard_section_sframe (i,
-						   bfd_elf_reloc_symbol_deleted_p,
-						   &cookie))
-		{
-		  if (i->size != i->rawsize)
-		    changed = 1;
-		}
+	      if (i->size != i->rawsize)
+		changed = 1;
 	    }
 	  fini_reloc_cookie_for_section (&cookie, i);
 	}
-      /* Update the reference to the output .sframe section.  Used to
-	 determine later if PT_GNU_SFRAME segment is to be generated.  */
-      if (!_bfd_elf_set_section_sframe (output_bfd, info))
-	return -1;
     }
 
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 80b4b512536..8a0efc02c86 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -719,7 +719,7 @@ cat <<EOF
   ${OTHER_READONLY_SECTIONS}
   .eh_frame_hdr ${RELOCATING-0} : { *(.eh_frame_hdr)${RELOCATING+ *(.eh_frame_entry .eh_frame_entry.*)} }
   .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame))${RELOCATING+ *(.eh_frame.*)} }
-  .sframe       ${RELOCATING-0} : ONLY_IF_RO { *(.sframe)${RELOCATING+ *(.sframe.*)} }
+  .sframe       ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.sframe))${RELOCATING+ *(.sframe.*)} }
   .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table${RELOCATING+ .gcc_except_table.*}) }
   .gnu_extab ${RELOCATING-0} : ONLY_IF_RO { *(.gnu_extab*) }
 
@@ -794,7 +794,7 @@ emit_data()
 cat <<EOF
   /* Exception handling.  */
   .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame))${RELOCATING+ *(.eh_frame.*)} }
-  .sframe       ${RELOCATING-0} : ONLY_IF_RW { *(.sframe)${RELOCATING+ *(.sframe.*)} }
+  .sframe       ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.sframe))${RELOCATING+ *(.sframe.*)} }
   .gnu_extab    ${RELOCATING-0} : ONLY_IF_RW { *(.gnu_extab) }
   .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table${RELOCATING+ .gcc_except_table.*}) }
   .exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges${RELOCATING+*}) }
-- 
2.52.0



More information about the Binutils mailing list