]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[SFrame-V3] gas: sframe: allow SFrame FDEs with 0 FREs for signal frames
authorIndu Bhagat <indu.bhagat@oracle.com>
Sun, 7 Dec 2025 04:35:45 +0000 (20:35 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Tue, 9 Dec 2025 08:26:13 +0000 (00:26 -0800)
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.

TBD:
 - But the warnings are already issued, we may emit SFrame FDE with no
   FREs.  Somewhat misleading.

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
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-signal-1.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp

index 7a92c0d26a10cdb457875fafc773ed864cf888a1..21994590f3f7b61a94c70ef6f842e9960ac033b8 100644 (file)
@@ -573,7 +573,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);
 }
 
@@ -2100,12 +2105,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 (file)
index 0000000..adffa7d
--- /dev/null
@@ -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 (file)
index 0000000..2dc6e91
--- /dev/null
@@ -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 6, -16
+       ret
+       .cfi_endproc
+       .size   foo, .-foo
index a352b325fd6ae372c64d24bafe97a8c7af32474f..f86150574c90521c94835656cf43204e18d04342 100644 (file)
@@ -63,6 +63,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
        run_dump_test "cfi-sframe-x86_64-2"
        run_dump_test "cfi-sframe-x86_64-3"
        run_dump_test "cfi-sframe-x86_64-pr33170"
+       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"