[binutils-gdb] [SFrame-V3] gas: sframe: allow SFrame FDEs with 0 FREs for signal frames

Indu Bhagat ibhagat@sourceware.org
Fri Jan 16 01:04:16 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5ed153a90a23949c0fb132cb7c6f54fb9f3dfcb3

commit 5ed153a90a23949c0fb132cb7c6f54fb9f3dfcb3
Author: Indu Bhagat <indu.bhagat@oracle.com>
Date:   Thu Jan 15 16:42:13 2026 -0800

    [SFrame-V3] gas: sframe: allow SFrame FDEs with 0 FREs for signal frames
    
    Update the SFrame generation logic in GAS to emit Function Descriptor Entries
    (FDEs) for signal frames even when no Frame Row Entries (FREs) could be
    generated.
    
    Previously, create_sframe_all () would discard any FDE that failed
    translation or resulted in zero FREs. However, for signal frames (marked
    with .cfi_signal_frame), preserving the FDE may be valuable even without
    stack offsets. The presence of the SFrame FDE with the 'Signal'
    attribute may allow stack tracers to identify the frame as a signal
    trampoline and potentially apply fallback handling, rather than treating
    the PC range as having no stack trace info at all.
    
    The patch modifies create_sframe_all () to detect translation errors for
    signal frames, effectively allowing the generation of an empty FDE (0 FREs)
    marked with the 'S' attribute.
    
    gas/
            * gen-sframe.c (sframe_fde_free): Add NULL check for safety.
            (create_sframe_all): Allow FDEs for signal frames even if translation
            encountered errors or produced no FREs.
    gas/testsuite/
            * gas/cfi-sframe/cfi-sframe.exp: New test.
            * gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d: New test ensuring
            signal frame FDE is emitted with 0 FREs.
            * gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s: New test.

Diff:
---
 gas/gen-sframe.c                                     | 20 ++++++++++++++------
 .../gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d      | 18 ++++++++++++++++++
 .../gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s      | 12 ++++++++++++
 gas/testsuite/gas/cfi-sframe/cfi-sframe.exp          |  1 +
 4 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index f79f5cdd97f..6818407683a 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -564,7 +564,12 @@ sframe_fde_alloc (void)
 static void
 sframe_fde_free (struct sframe_func_entry *sframe_fde)
 {
-  sframe_row_entry_free (sframe_fde->sframe_fres);
+  if (sframe_fde == NULL)
+    return;
+
+  if (sframe_fde->sframe_fres)
+    sframe_row_entry_free (sframe_fde->sframe_fres);
+
   XDELETE (sframe_fde);
 }
 
@@ -2098,12 +2103,15 @@ create_sframe_all (void)
       /* Initialize the translation context with information anew.  */
       sframe_xlate_ctx_init (xlate_ctx);
 
-      /* Process and link SFrame FDEs if no error.  Also skip adding an SFrame
-	 FDE if it does not contain any SFrame FREs.  There is little use of an
-	 SFrame FDE if there is no stack tracing information for the
-	 function.  */
+      /* Process and link SFrame FDEs if no error.  */
       int err = sframe_do_fde (xlate_ctx, dw_fde);
-      if (err || xlate_ctx->num_xlate_fres == 0)
+      if (err && get_dw_fde_signal_p (dw_fde))
+	{
+	  sframe_xlate_ctx_cleanup (xlate_ctx);
+	  err = SFRAME_XLATE_OK;
+	}
+
+      if (err)
 	{
 	  sframe_xlate_ctx_cleanup (xlate_ctx);
 	  sframe_fde_free (sframe_fde);
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d
new file mode 100644
index 00000000000..adffa7dc64e
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d
@@ -0,0 +1,18 @@
+#as: --gsframe
+#warning: \.cfi\_escape with op \(0xf\)
+#objdump: --sframe=.sframe
+#name: Signal Frame with no FREs
+#...
+Contents of the SFrame section .sframe:
+  Header :
+
+    Version: SFRAME_VERSION_3
+    Flags: SFRAME_F_FDE_FUNC_START_PCREL
+    CFA fixed RA offset: -8
+    Num FDEs: 1
+    Num FREs: 0
+
+  Function Index :
+
+    func idx \[0\]: pc = 0x0, size = 3 bytes, attr = "S"
+    STARTPC + CFA + FP + RA +
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s
new file mode 100644
index 00000000000..9394577a9e6
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s
@@ -0,0 +1,12 @@
+	.type	foo, @function
+foo:
+	.cfi_startproc
+	.cfi_signal_frame
+# DW_CFA_def_cfa_expression, length, DW_OP_breg9, (sleb)offset, DW_OP_deref
+	.cfi_escape 0xf,0x3,0x79,0x78,0x6
+	nop
+	pop	%rbp
+	.cfi_offset rbp, -16
+	ret
+	.cfi_endproc
+	.size	foo, .-foo
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index f7c5abf01b2..d42d2ecae18 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -63,6 +63,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
 	run_dump_test "cfi-sframe-x86_64-3"
 	run_dump_test "cfi-sframe-x86_64-pr33170"
 	run_dump_test "cfi-sframe-x86_64-pr33756"
+	run_dump_test "cfi-sframe-x86_64-signal-1"
 	run_dump_test "cfi-sframe-x86_64-empty-1"
 	run_dump_test "cfi-sframe-x86_64-empty-2"
 	run_dump_test "cfi-sframe-x86_64-empty-3"


More information about the Binutils-cvs mailing list