]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[SFrame-V3] ld: add --discard-sframe command line option
authorIndu Bhagat <indu.bhagat@oracle.com>
Fri, 16 Jan 2026 00:43:35 +0000 (16:43 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Fri, 16 Jan 2026 01:02:27 +0000 (17:02 -0800)
Add a new command line option --discard-sframe to the linker.
This option allows users to prevent the linker from generating an output
.sframe section.

The rationale for this option is: Consider the case when say, the distro
is shipped with SFrame sections in the installed binaries/libraries. A
user application using these installed libraries, but not enabling
.sframe for itself just yet, will see an output .sframe corresponding to
the pulled in libraries.  This is "partial" .sframe information for the
application.  Adding such an option to the linker, gives user a way to
turn off the .sframe section completely without relying on a linker
script.

Previously, the existing --no-ld-generated-unwind-info option
controlled whether (not just .eh_frame for PLT entries, but also) SFrame
for PLT entries. The new command line option,
--discard-sframe now decouples SFrame from other unwind
formats (like .eh_frame), allowing for more control over the output
binary's SFrame data.

The option is added for architectures that currently support SFrame:
AArch64, s390x, and x86_64.

bfd/
* elf-sframe.c (_bfd_elf_parse_sframe): Mark with SEC_EXCLUDE if
--discard-sframe is in effect.
* elf64-s390.c (elf_s390_create_dynamic_sections): Use
discard_sframe to guard .sframe section creation.
* elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Likewise.
include/
* bfdlink.h (struct bfd_link_info): Add discard_sframe bitfield.
ld/
* ldlex.h (enum option_values): Add OPTION_NO_LD_SFRAME_INFO.
* lexsup.c (elf_sframe_list_options): New function.
(ld_list_options): Add sframe_info argument. Update callers.
* ld.texi: Update documentation.
* emulparams/sframe-info.sh: New file.
* emultempl/aarch64elf.em: Add --discard-sframe option
listing and handling.
* emulparams/elf64_s390.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* Makefile.am: Update to handle sframe-info.sh and new list options.
* configure.ac: Handle SFRAME_INFO target variable.
* Makefile.in: Regenerate.
* configure: Regenerate.
ld/testsuite/
* ld-x86-64/x86-64.exp: New test.
* ld-x86-64/sframe-command-line-1.d: New test.
* ld-aarch64/aarch64-elf.exp: New test.
* ld-s390/s390.exp: New test.
* ld-x86-64/x86-64.exp: New test.
* ld-aarch64/sframe-command-line-1.d: New test.
* ld-s390/sframe-command-line-1.d: New test.
* ld-x86-64/sframe-command-line-1.d: New test.

21 files changed:
bfd/elf-sframe.c
bfd/elf64-s390.c
bfd/elfxx-x86.c
include/bfdlink.h
ld/Makefile.am
ld/Makefile.in
ld/configure
ld/configure.ac
ld/emulparams/elf64_s390.sh
ld/emulparams/elf_x86_64.sh
ld/emulparams/sframe-info.sh [new file with mode: 0644]
ld/emultempl/aarch64elf.em
ld/ld.texi
ld/ldlex.h
ld/lexsup.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/sframe-command-line-1.d [new file with mode: 0644]
ld/testsuite/ld-s390/s390.exp
ld/testsuite/ld-s390/sframe-command-line-1.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/sframe-command-line-1.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 511a297054b8f8d9260288dfb23c9ed4f22d82ba..33e4df5b1c751367439ced3ab88cba36a5f1c6dd 100644 (file)
@@ -211,6 +211,9 @@ _bfd_elf_parse_sframe (bfd *abfd,
   bfd_size_type sf_size;
   int decerr = 0;
 
+  if (info->discard_sframe)
+    sec->flags |= SEC_EXCLUDE;
+
   /* Prior versions of assembler and ld were generating SFrame sections with
      section type SHT_PROGBITS.  Issue an error for lack of support for such
      objects now.  Even if section size is zero, a valid section type is
index 012457827e0aae215aa190900538597433de1452..8ad10ce6bd1d289992d55206e7180433b484620f 100644 (file)
@@ -4309,7 +4309,7 @@ elf_s390_create_dynamic_sections (bfd *dynobj,
         }
 
       /* Create .sframe section for .plt section.  */
-      if (!info->no_ld_generated_unwind_info)
+      if (!info->discard_sframe)
        {
          flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
                            | SEC_HAS_CONTENTS | SEC_IN_MEMORY
index 0348da9f0a151673e9011d3fdf70fe5d1f8e569a..901b858fb3446c1e9afb0b489016cc494d664e45 100644 (file)
@@ -4827,7 +4827,7 @@ _bfd_x86_elf_link_setup_gnu_properties
        }
 
       /* .sframe sections are emitted for AMD64 ABI only.  */
-      if (ABI_64_P (info->output_bfd) && !info->no_ld_generated_unwind_info)
+      if (ABI_64_P (info->output_bfd) && !info->discard_sframe)
        {
          flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
                            | SEC_HAS_CONTENTS | SEC_IN_MEMORY
index d715fcbd6fb201a2b2bd01184a10b61b16e19854..eac72b8c3885ff1ac996eead9e00bcf87ea7e7fe 100644 (file)
@@ -475,6 +475,10 @@ struct bfd_link_info
      linker created sections, TRUE if it should be omitted.  */
   unsigned int no_ld_generated_unwind_info: 1;
 
+  /* TRUE if no .sframe stack trace info should be generated for the output.
+     This includes linker generated SFrame info as well.  */
+  unsigned int discard_sframe: 1;
+
   /* TRUE if BFD should generate a "task linked" object file,
      similar to relocatable but also with globals converted to
      statics.  */
index 3f2a9ae98324ae0425b22426cbda669a3f0fc395..c219662d2e3b84368c7c83fff1df83a051619a14 100644 (file)
@@ -42,7 +42,8 @@ ZLIBINC = @zlibinc@
 
 ELF_CFLAGS=-DELF_LIST_OPTIONS=@elf_list_options@ \
           -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
-          -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
+          -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@ \
+          -DELF_SFRAME_LIST_OPTIONS=@elf_sframe_list_options@
 WARN_CFLAGS = @WARN_CFLAGS@
 NO_WERROR = @NO_WERROR@
 AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS) $(JANSSON_CFLAGS) $(ZSTD_CFLAGS)
index 0af36e9e310b9261b5588bd5f15c399a1f408957..f1ba6af52694035fcb8d5e22198da6cea4c28c46 100644 (file)
@@ -520,6 +520,7 @@ docdir = @docdir@
 dvidir = @dvidir@
 elf_list_options = @elf_list_options@
 elf_plt_unwind_list_options = @elf_plt_unwind_list_options@
+elf_sframe_list_options = @elf_sframe_list_options@
 elf_shlib_list_options = @elf_shlib_list_options@
 enable_initfini_array = @enable_initfini_array@
 enable_libctf = @enable_libctf@
@@ -579,7 +580,8 @@ ZLIB = @zlibdir@ -lz
 ZLIBINC = @zlibinc@
 ELF_CFLAGS = -DELF_LIST_OPTIONS=@elf_list_options@ \
           -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
-          -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
+          -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@ \
+          -DELF_SFRAME_LIST_OPTIONS=@elf_sframe_list_options@
 
 AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS) $(JANSSON_CFLAGS) $(ZSTD_CFLAGS)
 
index 3dcd0aaca723f38e488a6f07bef15b017da18dfe..bd10f0a145ba43f33a9946992c714a55a7db1776 100755 (executable)
@@ -644,6 +644,7 @@ EMUL_EXTRA_OFILES
 EMULATION_OFILES
 TDIRS
 EMUL
+elf_sframe_list_options
 elf_plt_unwind_list_options
 elf_shlib_list_options
 elf_list_options
@@ -11893,7 +11894,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11896 "configure"
+#line 11897 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11999,7 +12000,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12002 "configure"
+#line 12003 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19211,6 +19212,7 @@ TDIRS=
 elf_list_options=false
 elf_shlib_list_options=false
 elf_plt_unwind_list_options=false
+elf_sframe_list_options=false
 for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
 do
   if test "$targ_alias" = "all"; then
@@ -19218,6 +19220,7 @@ do
     elf_list_options=true
     elf_shlib_list_options=true
     elf_plt_unwind_list_options=true
+    elf_sframe_list_options=true
   else
     # Canonicalize the secondary target names.
     result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -19273,6 +19276,9 @@ tdir_$i=$result"
            if test x${PLT_UNWIND} = xyes; then
              elf_plt_unwind_list_options=true
            fi
+           if test x${SFRAME_INFO} = xyes; then
+             elf_sframe_list_options=true
+           fi
          fi
          ;;
        esac
@@ -19481,6 +19487,7 @@ _ACEOF
 
 
 
+
 if test x${all_targets} = xtrue; then
   if test x${have_64_bit_bfd} = xyes; then
     EMULATION_OFILES='$(ALL_EMULATIONS) $(ALL_64_EMULATIONS)'
index a0a1361a0eb92273bcf4f9ab9c0fbb1b74e814b3..8c5e9606ac0d69689de3b9a23cc1e6c090ad12d3 100644 (file)
@@ -506,6 +506,7 @@ TDIRS=
 elf_list_options=false
 elf_shlib_list_options=false
 elf_plt_unwind_list_options=false
+elf_sframe_list_options=false
 for targ_alias in `echo $target_alias $enable_targets | sed 's/,/ /g'`
 do
   if test "$targ_alias" = "all"; then
@@ -513,6 +514,7 @@ do
     elf_list_options=true
     elf_shlib_list_options=true
     elf_plt_unwind_list_options=true
+    elf_sframe_list_options=true
   else
     # Canonicalize the secondary target names.
     result=`$ac_config_sub $targ_alias 2>/dev/null`
@@ -568,6 +570,9 @@ tdir_$i=$result"
            if test x${PLT_UNWIND} = xyes; then
              elf_plt_unwind_list_options=true
            fi
+           if test x${SFRAME_INFO} = xyes; then
+             elf_sframe_list_options=true
+           fi
          fi
          ;;
        esac
@@ -730,6 +735,7 @@ AC_DEFINE_UNQUOTED([DEFAULT_EMIT_GNU_HASH],
 AC_SUBST(elf_list_options)
 AC_SUBST(elf_shlib_list_options)
 AC_SUBST(elf_plt_unwind_list_options)
+AC_SUBST(elf_sframe_list_options)
 AC_SUBST(EMUL)
 
 AC_SUBST(TDIRS)
index b58314800d10b44ec01b1e5915a5cacbd2a2f44f..750e83b714fee7548877e3c706a89cfe983a8404 100644 (file)
@@ -1,4 +1,5 @@
 source_sh ${srcdir}/emulparams/plt_unwind.sh
+source_sh ${srcdir}/emulparams/sframe-info.sh
 SCRIPT_NAME=elf
 ELFSIZE=64
 OUTPUT_FORMAT="elf64-s390"
index fb4fcd6ae1740531aa181e5c5e28c4e4b95b3e37..747114bc4b443c32bb314623ce23442b9540b416 100644 (file)
@@ -1,4 +1,5 @@
 source_sh ${srcdir}/emulparams/plt_unwind.sh
+source_sh ${srcdir}/emulparams/sframe-info.sh
 source_sh ${srcdir}/emulparams/extern_protected_data.sh
 source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
 source_sh ${srcdir}/emulparams/reloc_overflow.sh
diff --git a/ld/emulparams/sframe-info.sh b/ld/emulparams/sframe-info.sh
new file mode 100644 (file)
index 0000000..b7cc10b
--- /dev/null
@@ -0,0 +1,15 @@
+SFRAME_INFO=yes
+
+PARSE_AND_LIST_LONGOPTS_SFRAME='
+  {"discard-sframe", no_argument, NULL,
+   OPTION_DISCARD_SFRAME},
+'
+
+PARSE_AND_LIST_ARGS_CASES_SFRAME='
+    case OPTION_DISCARD_SFRAME:
+      link_info.discard_sframe = true;
+      break;
+'
+
+PARSE_AND_LIST_LONGOPTS="$PARSE_AND_LIST_LONGOPTS $PARSE_AND_LIST_LONGOPTS_SFRAME"
+PARSE_AND_LIST_ARGS_CASES="$PARSE_AND_LIST_ARGS_CASES $PARSE_AND_LIST_ARGS_CASES_SFRAME"
index e15eb432458948971573ad39fb67af86203ac3f8..cd3a6c63d99a5f3ca5a9d7a3e7ad2a41fee74f6e 100644 (file)
@@ -487,6 +487,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "fix-cortex-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
   { "fix-cortex-a53-843419", optional_argument, NULL, OPTION_FIX_ERRATUM_843419},
   { "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
+  { "discard-sframe", no_argument, NULL, OPTION_DISCARD_SFRAME},
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -495,6 +496,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  --no-wchar-size-warning     Don'\''t warn about objects with incompatible\n"
                   "                                wchar_t sizes\n"));
   fprintf (file, _("  --pic-veneer                Always generate PIC interworking veneers\n"));
+  fprintf (file, _("  --discard-sframe            Don'\''t generate SFrame stack trace info in output\n"));
   fprintf (file, _("\
   --stub-group-size=N         Maximum size of a group of input sections that\n\
                                 can be handled by one stub section.  A negative\n\
@@ -632,6 +634,11 @@ PARSE_AND_LIST_ARGS_CASES='
          fatal (_("%P: invalid number `%s'\''\n"), optarg);
       }
       break;
+
+    case OPTION_DISCARD_SFRAME:
+      link_info.discard_sframe = true;
+      break;
+
 '
 
 # We have our own before_allocation etc. functions, but they call
index 1ec56c08337b9443f2374bf302ecda7398b53140..7cadc853af90539e2f6fddb8337b7ffc33d6b880 100644 (file)
@@ -3251,9 +3251,13 @@ section and ELF @code{PT_GNU_EH_FRAME} segment header.
 @item --no-ld-generated-unwind-info
 Request creation of @code{.eh_frame} unwind info for linker
 generated code sections like PLT.  This option is on by default
-if linker generated unwind info is supported.  This option also
-controls the generation of @code{.sframe} stack trace info for linker
-generated code sections like PLT.
+if linker generated unwind info is supported.
+
+@kindex --discard-sframe
+@item --discard-sframe
+Discard @code{.sframe} stack trace info from the output.  This option also
+prohibits the creation of SFrame stack trace data for linker generated code
+sections like PLT.  This option is off by default.
 
 @kindex --enable-new-dtags
 @kindex --disable-new-dtags
index 1efbe58002bff688b6684a9b7171311472ec60d6..85e06b6fcc48d15b90e4490311a40d258920cbc4 100644 (file)
@@ -215,6 +215,8 @@ enum option_values
   /* Used by emulparams/plt_unwind.sh.  */
   OPTION_LD_GENERATED_UNWIND_INFO,
   OPTION_NO_LD_GENERATED_UNWIND_INFO,
+  /* Used by emulparams/sframe-info.sh.  */
+  OPTION_DISCARD_SFRAME,
   /* Used by emultempl/aarch64elf.em.  */
   OPTION_FIX_ERRATUM_835769,
   OPTION_FIX_ERRATUM_843419,
index 843b809bacb936da61aad3d70794378fba2a2283..158abb6dd8ff3993fa5d6673f3c009c22dfb104f 100644 (file)
@@ -2364,13 +2364,23 @@ elf_plt_unwind_list_options (FILE *file)
 }
 
 static void
-ld_list_options (FILE *file, bool elf, bool shlib, bool plt_unwind)
+elf_sframe_list_options (FILE *file)
+{
+  fprintf (file, _("\
+  --discard-sframe            Don't generate SFrame stack trace info in output\n"));
+}
+
+static void
+ld_list_options (FILE *file, bool elf, bool shlib, bool plt_unwind,
+                bool sframe_info)
 {
   if (!elf)
     return;
   printf (_("ELF emulations:\n"));
   if (plt_unwind)
     elf_plt_unwind_list_options (file);
+  if (sframe_info)
+    elf_sframe_list_options (file);
   elf_static_list_options (file);
   if (shlib)
     elf_shlib_list_options (file);
@@ -2495,7 +2505,8 @@ help (void)
   /* xgettext:c-format */
   printf (_("%s: emulation specific options:\n"), program_name);
   ld_list_options (stdout, ELF_LIST_OPTIONS, ELF_SHLIB_LIST_OPTIONS,
-                  ELF_PLT_UNWIND_LIST_OPTIONS);
+                  ELF_PLT_UNWIND_LIST_OPTIONS,
+                  ELF_SFRAME_LIST_OPTIONS);
   ldemul_list_emulation_options (stdout);
   printf ("\n");
 
index 8791df3f3d3ed6e805bfb798c7f8337ec43e63eb..a0a8867dca1bb876fa2efd3088e30db22f8b67a3 100644 (file)
@@ -430,4 +430,5 @@ if { [supports_dt_relr] } {
 
 if { ![skip_sframe_tests] } {
   run_dump_test "sframe-simple-1"
+  run_dump_test "sframe-command-line-1"
 }
diff --git a/ld/testsuite/ld-aarch64/sframe-command-line-1.d b/ld/testsuite/ld-aarch64/sframe-command-line-1.d
new file mode 100644 (file)
index 0000000..a9255d4
--- /dev/null
@@ -0,0 +1,8 @@
+#as: --gsframe
+#source: sframe-foo.s
+#source: sframe-bar.s
+#readelf: --sframe
+#ld: -shared --discard-sframe
+#name: Command line option --discard-sframe
+
+Section '.sframe' has no debugging data.
index b81ebe280da59bc1300d0130462249c9a2ed27ae..0fdfb39c5aa2026c792e534831a4879a2b8ffdd5 100644 (file)
@@ -192,5 +192,6 @@ if [istarget "s390x-*-*"] {
     if { ![skip_sframe_tests] } {
        run_dump_test "sframe-simple-1"
        run_dump_test "sframe-plt-1"
+       run_dump_test "sframe-command-line-1"
     }
 }
diff --git a/ld/testsuite/ld-s390/sframe-command-line-1.d b/ld/testsuite/ld-s390/sframe-command-line-1.d
new file mode 100644 (file)
index 0000000..90ce394
--- /dev/null
@@ -0,0 +1,8 @@
+#as: --gsframe
+#source: sframe-foo.s
+#source: sframe-bar.s
+#readelf: --sframe
+#ld: -shared --no-rosegment --discard-sframe
+#name: Command line option --discard-sframe
+
+Section '.sframe' has no debugging data.
diff --git a/ld/testsuite/ld-x86-64/sframe-command-line-1.d b/ld/testsuite/ld-x86-64/sframe-command-line-1.d
new file mode 100644 (file)
index 0000000..3f54ff9
--- /dev/null
@@ -0,0 +1,8 @@
+#as: --gsframe
+#source: sframe-foo.s
+#source: sframe-bar.s
+#readelf: --sframe
+#ld: -shared --no-rosegment -z separate-code --discard-sframe
+#name: Command line option --discard-sframe
+
+Section '.sframe' has no debugging data.
index f80f718c15b5f4ac06cf143a692195af58b052f3..df2bb5ea1bd7ca0ae814fc27120da968e5a8d975 100644 (file)
@@ -587,6 +587,7 @@ run_dump_test "tls-le-pic-3-x32"
 
 if { ![skip_sframe_tests] } {
     run_dump_test "sframe-simple-1"
+    run_dump_test "sframe-command-line-1"
     run_dump_test "sframe-reloc-1"
     run_dump_test "sframe-plt-1"
     run_dump_test "sframe-ibt-plt-1"