[binutils-gdb] gas: sframe: fix PR gas/33756

Indu Bhagat ibhagat@sourceware.org
Thu Jan 8 20:18:16 GMT 2026


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

commit 1674e47227965dbf85c5fee59b0858afd191284c
Author: Indu Bhagat <indu.bhagat@oracle.com>
Date:   Thu Jan 8 12:11:17 2026 -0800

    gas: sframe: fix PR gas/33756
    
    Previously, sframe_xlate_do_remember_state () relied exclusively on
    last_fre (the last Frame Row Entry for the previous PC range block).  At
    the start of a function (before an advance in location), last_fre is
    NULL.  The intent of DW_CFA_remember_state, however, is to simply
    snapshot the state of the call frame information at the time.  In terms
    of SFrame generation, this means that we should simply look at cur_fre
    (the scratchpad FRE currently being built from initial CFI
    instructions in the current context).
    
    Remove the common-empty-1.s which assumed that .cfi_startproc,
    immediately followed by a .cfi_remember_state is not present out in the
    wild.  Its best to not make such an assumption, as such a sequence is
    valid CFI, FWIW.
    
    Initial CFI are arch-specific, so add a new testcase for x86_64 to check
    .cfi_remember_state handling for SFrame is sensible.  While at at, also
    add a new testcase for s390x.
    
    Co-Authored-by: Jens Remus <jremus@linux.ibm.com>
    Reviewed-by: Jens Remus <jremus@linux.ibm.com>
    
    gas/
            PR gas/33756
            * gen-sframe.c (sframe_xlate_do_remember_state): Use cur_fre.
    gas/testsuite/
            * gas/cfi-sframe/cfi-sframe.exp: Adjust common-empty-1 test to
            be repurposed as cfi-sframe-x86_64-pr33756.  Add s390x testcase.
            * gas/cfi-sframe/common-empty-1.d: Removed.
            * gas/cfi-sframe/common-empty-1.s: Removed.
            * gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d: New test.
            * gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s: New test.
            * gas/cfi-sframe/cfi-sframe-s390x-pr33756.d: New test.
            * gas/cfi-sframe/cfi-sframe-s390x-pr33756.s: New test.

Diff:
---
 gas/gen-sframe.c                                   |  6 +++---
 .../gas/cfi-sframe/cfi-sframe-s390x-pr33756.d      | 23 +++++++++++++++++++++
 .../gas/cfi-sframe/cfi-sframe-s390x-pr33756.s      | 23 +++++++++++++++++++++
 .../gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d     | 24 ++++++++++++++++++++++
 .../gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s     | 13 ++++++++++++
 gas/testsuite/gas/cfi-sframe/cfi-sframe.exp        |  3 ++-
 gas/testsuite/gas/cfi-sframe/common-empty-1.d      | 17 ---------------
 gas/testsuite/gas/cfi-sframe/common-empty-1.s      |  5 -----
 8 files changed, 88 insertions(+), 26 deletions(-)

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 3e329c92001..4a70ae13ff5 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1349,12 +1349,12 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
 static int
 sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
 {
-  const struct sframe_row_entry *last_fre = xlate_ctx->last_fre;
+  const struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
 
   /* If there is no FRE state to remember, nothing to do here.  Return
      early with non-zero error code, this will cause no SFrame stack trace
      info for the function involved.  */
-  if (!last_fre)
+  if (!cur_fre)
     {
       as_warn (_("no SFrame FDE emitted; "
 		 ".cfi_remember_state without prior SFrame FRE state"));
@@ -1363,7 +1363,7 @@ sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx)
 
   if (!xlate_ctx->remember_fre)
     xlate_ctx->remember_fre = sframe_row_entry_new ();
-  sframe_row_entry_initialize (xlate_ctx->remember_fre, last_fre);
+  sframe_row_entry_initialize (xlate_ctx->remember_fre, cur_fre);
 
   return SFRAME_XLATE_OK;
 }
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d
new file mode 100644
index 00000000000..e572592a06b
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d
@@ -0,0 +1,23 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: SFrame generation on s390x - .cfi_remember_state after .cfi_startproc PR gas/33756
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_2
+    Flags: SFRAME_F_FDE_FUNC_START_PCREL
+    Num FDEs: 1
+    Num FREs: 4
+
+  Function Index :
+
+    func idx \[0\]: pc = 0x0, size = 20 bytes
+    STARTPC +CFA +FP +RA +
+    0+0000 +sp\+160 +u +u +
+    0+0006 +sp\+160 +c-72 +c-48 +
+    0+000c +sp\+320 +c-72 +c-48 +
+    0+0012 +sp\+160 +u +u +
+
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s
new file mode 100644
index 00000000000..7126d30284e
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s
@@ -0,0 +1,23 @@
+	.text
+	.type foo, @function
+foo:
+	.cfi_startproc
+	.cfi_remember_state
+	stmg	%r6,%r15,48(%r15)
+	.cfi_rel_offset 6, 48
+	.cfi_rel_offset 7, 56
+	.cfi_rel_offset 8, 64
+	.cfi_rel_offset 9, 72
+	.cfi_rel_offset 10, 80
+	.cfi_rel_offset 11, 88
+	.cfi_rel_offset 12, 96
+	.cfi_rel_offset 13, 104
+	.cfi_rel_offset 14, 112
+	.cfi_rel_offset 15, 120
+	lay	%r15,-160(%r15)
+	.cfi_adjust_cfa_offset 160
+	lmg	%r6,%r15,160+48(%r15)
+	.cfi_restore_state
+	br	%r14
+	.cfi_endproc
+	.size foo, .-foo
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d
new file mode 100644
index 00000000000..3ae3aeb0e57
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d
@@ -0,0 +1,24 @@
+#as: --gsframe
+#objdump: --sframe=.sframe
+#name: cfi_remember_state after cfi_startproc PR gas/33756
+#...
+Contents of the SFrame section .sframe:
+
+  Header :
+
+    Version: SFRAME_VERSION_2
+    Flags: SFRAME_F_FDE_FUNC_START_PCREL
+#?    CFA fixed FP offset: \-?\d+
+#?    CFA fixed RA offset: \-?\d+
+    Num FDEs: 1
+    Num FREs: 3
+
+  Function Index :
+
+    func idx \[0\]: pc = 0x0, size = 16 bytes
+    STARTPC +CFA +FP +RA +
+    0+0000 +sp\+8 +u +[uf] +
+    0+0004 +sp\+16 +u +[uf] +
+    0+000c +sp\+8 +u +[uf] +
+
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s
new file mode 100644
index 00000000000..c31b443932d
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s
@@ -0,0 +1,13 @@
+	.text
+	.type	foo, @function
+foo:
+	.cfi_startproc
+	.cfi_remember_state
+	.long 0
+	.cfi_def_cfa_offset 16
+	.long 0
+	.long 0
+	.cfi_restore_state
+	.long 0
+	.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 d2fa2d82f18..4dbe69bc097 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -49,7 +49,6 @@ if  { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"]
     run_dump_test "cfi-sframe-common-11"
     run_dump_test "cfi-sframe-common-12"
 
-    run_dump_test "common-empty-1"
     run_dump_test "common-empty-2"
     run_dump_test "common-empty-3"
 }
@@ -62,6 +61,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-pr33756"
 	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"
@@ -95,4 +95,5 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
     run_dump_test "cfi-sframe-s390x-fpra-register-1"
     run_dump_test "cfi-sframe-s390x-fpra-register-2"
     run_dump_test "cfi-sframe-s390x-ra-undefined-1"
+    run_dump_test "cfi-sframe-s390x-pr33756"
 }
diff --git a/gas/testsuite/gas/cfi-sframe/common-empty-1.d b/gas/testsuite/gas/cfi-sframe/common-empty-1.d
deleted file mode 100644
index c64dd92e003..00000000000
--- a/gas/testsuite/gas/cfi-sframe/common-empty-1.d
+++ /dev/null
@@ -1,17 +0,0 @@
-#as: --gsframe
-#warning: \.cfi_remember_state without prior SFrame FRE state
-#objdump: --sframe=.sframe
-#name: Uninteresting cfi directives generate an empty SFrame section
-#...
-Contents of the SFrame section .sframe:
-
-  Header :
-
-    Version: SFRAME_VERSION_2
-    Flags: SFRAME_F_FDE_FUNC_START_PCREL
-#?    CFA fixed FP offset: \-?\d+
-#?    CFA fixed RA offset: \-?\d+
-    Num FDEs: 0
-    Num FREs: 0
-
-#pass
diff --git a/gas/testsuite/gas/cfi-sframe/common-empty-1.s b/gas/testsuite/gas/cfi-sframe/common-empty-1.s
deleted file mode 100644
index e26e998189f..00000000000
--- a/gas/testsuite/gas/cfi-sframe/common-empty-1.s
+++ /dev/null
@@ -1,5 +0,0 @@
-      .cfi_sections .sframe
-      .cfi_startproc
-      .cfi_remember_state
-      .cfi_restore_state
-      .cfi_endproc


More information about the Binutils-cvs mailing list