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

Jens Remus jremus@linux.ibm.com
Thu Jan 22 08:45:46 GMT 2026


On 1/22/2026 9:00 AM, claudiu.zissulescu-ianculescu@oracle.com wrote:
> 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.

Maybe add: "like it is being done for .eh_frame sections" to explain
that this is a proven solution.

> 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.
> 
> 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         | 38 ++++++++++++++++++++++++++++----------
>  ld/scripttempl/elf.sc |  4 ++--
>  3 files changed, 35 insertions(+), 12 deletions(-)

Reviewed-by: Jens Remus <jremus@linux.ibm.com>

> 
> diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> index c833b7d101b..94525b3606e 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..db74591489d 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;
>  
> @@ -14703,6 +14706,23 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
>  	  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_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,15 +15322,13 @@ 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);
>  	}
> 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+*}) }

Regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



More information about the Binutils mailing list