[COMMITTED 12/36] [SFrame-V3] gas: sframe: allow SFrame FDEs with 0 FREs for signal frames

Indu Bhagat indu.bhagat@oracle.com
Fri Jan 16 06:10:12 GMT 2026


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.
---
 gas/gen-sframe.c                              | 20 +++++++++++++------
 .../cfi-sframe/cfi-sframe-x86_64-signal-1.d   | 18 +++++++++++++++++
 .../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(-)
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s

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"
-- 
2.43.0



More information about the Binutils mailing list