[PATCH v3 1/3] ld: sframe: do not generate .sframe for PLT if no .sframe is in input BFDs

claudiu.zissulescu-ianculescu@oracle.com claudiu.zissulescu-ianculescu@oracle.com
Thu Jan 22 08:00:36 GMT 2026


From: Indu Bhagat <indu.bhagat@oracle.com>

GNU ld creates SFrame stack trace info for the .plt* sections.  These
linker created sections are created in
_bfd_x86_elf_link_setup_gnu_properties (), but data is emitted into
them a bit later in _bfd_x86_elf_late_size_sections ().

With SFrame sections now marked KEEP in scripttempl/elf.sc, and the
presence of these linker created SFrame sections cause emission of an
empty .sframe for all ELF targets (IIUC), even when all input bfd's
have no .sframe section.

This patch is an attempt to avoid creation of empty .sframe in linked
objects on x86_64 and s390x, when none of the inputs had SFrame sections.

bfd/
	* elf-bfd.h (_bfd_elf_sframe_present_input_bfds): New
	declaration.
	* elf-sframe.c (_bfd_elf_sframe_present_input_bfds): New
	definition.
	* elf64-s390.c (elf_s390_create_dynamic_sections): Do not
	generate .sframe for .plt unconditionally.
	* elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties):
	Likewise.
---
 bfd/elf-bfd.h    |  2 ++
 bfd/elf-sframe.c | 18 ++++++++++++++++++
 bfd/elf64-s390.c | 10 +++++++++-
 bfd/elfxx-x86.c  | 11 ++++++++++-
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4fa4461cba3..c833b7d101b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2581,6 +2581,8 @@ extern bool _bfd_elf_maybe_strip_eh_frame_hdr
 
 extern bool _bfd_elf_sframe_present
   (struct bfd_link_info *) ATTRIBUTE_HIDDEN;
+extern bool _bfd_elf_sframe_present_input_bfds
+  (struct bfd_link_info *) ATTRIBUTE_HIDDEN;
 extern bool _bfd_elf_parse_sframe
   (bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *)
   ATTRIBUTE_HIDDEN;
diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c
index 33e4df5b1c7..77d9d33d602 100644
--- a/bfd/elf-sframe.c
+++ b/bfd/elf-sframe.c
@@ -171,6 +171,24 @@ sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset,
   return value;
 }
 
+/* Return true if any of the input BFDs contains at least one .sframe
+   section.  */
+
+bool
+_bfd_elf_sframe_present_input_bfds (struct bfd_link_info *info)
+{
+  /* Find if any input file has an .sframe section.  */
+  for (bfd *pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next)
+    if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
+	&& bfd_count_sections (pbfd) != 0)
+      {
+	asection *sec = bfd_get_section_by_name (pbfd, ".sframe");
+	if (sec != NULL)
+	  return true;
+      }
+  return false;
+}
+
 /* Return true if there is at least one non-empty .sframe section in
    input files.  Can only be called after ld has mapped input to
    output sections, and before sections are stripped.  */
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 8ad10ce6bd1..b6a903db42a 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -4309,7 +4309,15 @@ elf_s390_create_dynamic_sections (bfd *dynobj,
         }
 
       /* Create .sframe section for .plt section.  */
-      if (!info->discard_sframe)
+      bool gen_plt_sframe_p = !info->discard_sframe
+	&& _bfd_elf_sframe_present_input_bfds (info);
+
+      /* Do not make SFrame sections for dynobj unconditionally.  If there
+	 are no SFrame sections for any input files, skip creating the linker
+	 created SFrame sections too.  Since SFrame sections are marked KEEP,
+	 prohibiting these linker-created SFrame sections when unnecessary,
+	 helps avoid creating of empty SFrame sections in the output.  */
+      if (gen_plt_sframe_p)
 	{
 	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
 			    | SEC_HAS_CONTENTS | SEC_IN_MEMORY
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 901b858fb34..b450aed4038 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -4827,7 +4827,16 @@ _bfd_x86_elf_link_setup_gnu_properties
 	}
 
       /* .sframe sections are emitted for AMD64 ABI only.  */
-      if (ABI_64_P (info->output_bfd) && !info->discard_sframe)
+      bool gen_plt_sframe_p = ABI_64_P (info->output_bfd)
+	&& !info->discard_sframe
+	&& _bfd_elf_sframe_present_input_bfds (info);
+
+      /* Do not make SFrame sections for dynobj unconditionally.  If there
+	 are no SFrame sections for any input files, skip creating the linker
+	 created SFrame sections too.  Since SFrame sections are marked KEEP,
+	 prohibiting these linker-created SFrame sections, when unnecessary,
+	 helps avoid creation of empty SFrame sections in the output.  */
+      if (gen_plt_sframe_p)
 	{
 	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
 			    | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-- 
2.52.0



More information about the Binutils mailing list