[PATCH v5 1/2] ld: bfd: sframe: KEEP .sframe sections and support gc-sections
Indu Bhagat
indu.bhagat@oracle.com
Thu Jan 29 07:07:43 GMT 2026
On 1/27/26 12:45 PM, 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, like it is being done for .eh_frame 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.
>
> Also, the _bfd_elf_parse_sframe is changed to return TRUE when the
> input sframe section is already parsed. It fixes calling
> _bfd_elf_discard_section_sframe function in bfd_elf_discard_info,
> enabling correct behavior for discarding unneeded sframe sections.
>
> 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.
> * elf-sframe.c (_bfd_elf_parse_sframe): Return TRUE for already
> parsed sframe sections.
>
> Co-authored-by: Indu Bhagat <indu.bhagat@oracle.com>
> Reviewed-by: Jens Remus <jremus@linux.ibm.com>
> Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
LGTM, one nit below.
Thanks
> ---
> bfd/elf-bfd.h | 5 +++++
> bfd/elf-sframe.c | 8 ++++++--
> bfd/elflink.c | 22 ++++++++++++++++++++--
> ld/scripttempl/elf.sc | 4 ++--
> 4 files changed, 33 insertions(+), 6 deletions(-)
>
> 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/elf-sframe.c b/bfd/elf-sframe.c
> index 77d9d33d602..afcf82f370b 100644
> --- a/bfd/elf-sframe.c
> +++ b/bfd/elf-sframe.c
> @@ -245,13 +245,17 @@ _bfd_elf_parse_sframe (bfd *abfd,
> }
>
> if (sec->size == 0
> - || (sec->flags & SEC_HAS_CONTENTS) == 0
> - || sec->sec_info_type != SEC_INFO_TYPE_NONE)
> + || (sec->flags & SEC_HAS_CONTENTS) == 0)
> {
> /* This file does not contain .sframe information. */
> return false;
> }
>
> + /* Check if this section is already parsed. */
> + if (sec->sec_info_type == SEC_INFO_TYPE_SFRAME)
> + return true;
> +
> +
Nit: Extra newline
> if (bfd_is_abs_section (sec->output_section))
> {
> /* At least one of the sections is being discarded from the
> diff --git a/bfd/elflink.c b/bfd/elflink.c
> index 64c1a57b465..b2a04631b7a 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,21 @@ 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);
> }
> +
> + /* Handle .sframe section. */
> + 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. */
> 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+*}) }
More information about the Binutils
mailing list