[PATCH] gas: sframe: fix PR gas/33277

Indu Bhagat indu.bhagat@oracle.com
Mon Nov 3 20:25:44 GMT 2025


In SFrame stack trace format, the representation of stack offsets allows
for either 1-byte, 2-byte or 4-byte integers.

Add new internal function sframe_fre_stack_offset_bound_p () which
checks if the given offset is within bounds (at most as a 4-byte
integer).  Use this to check if CFA offset is within bounds, if not skip
emitting the FDE, and warn the user.

gas/
	PR gas/33277
        * gen-sframe.c (sframe_fre_stack_offset_bound_p): New
	definition.
        (sframe_xlate_do_def_cfa): Check bounds of offset.
        (sframe_xlate_do_def_cfa_offset): Likewise.

gas/testsuite/
	PR gas/33277
        * gas/cfi-sframe/cfi-sframe.exp: Add new test.
        * gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d: Likewise.
        * gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.s: Likewise.
---
 gas/gen-sframe.c                              | 46 +++++++++++++++++--
 .../cfi-sframe-x86_64-empty-pr33277.d         | 17 +++++++
 .../cfi-sframe-x86_64-empty-pr33277.s         |  5 ++
 gas/testsuite/gas/cfi-sframe/cfi-sframe.exp   |  1 +
 4 files changed, 64 insertions(+), 5 deletions(-)
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d
 create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.s

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 3ac1cf4338c..0d6edd362cb 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -147,6 +147,24 @@ sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
   return offset;
 }
 
+/* All stack offsets in SFrame stack trace format must be representable as a
+   1-byte (SFRAME_FRE_OFFSET_1B), 2-byte (SFRAME_FRE_OFFSET_2B) or 4-byte
+   (SFRAME_FRE_OFFSET_4B) value.
+
+   At the moment, sanity check on CFA offset (only) is performed to address PR
+   gas/33277.  Arguably, such updates to ra_offset or fp_offset will only
+   follow after updates to cfa_offset in a real-world, useful program.  */
+
+static bool
+sframe_fre_stack_offset_bound_p (offsetT offset, bool cfa_reg_p)
+{
+  /* For s390x, CFA offset is adjusted to enable 8-bit offsets.  */
+  if (cfa_reg_p && sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
+    offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (offset);
+
+  return (offset >= INT32_MIN && offset <= INT32_MAX);
+}
+
 static void
 sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
 			   offsetT cfa_offset)
@@ -1059,9 +1077,18 @@ sframe_xlate_do_def_cfa (struct sframe_xlate_ctx *xlate_ctx,
 	       cfi_insn->u.ri.reg);
       return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented.  */
     }
-  sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
-  sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
-  cur_fre->merge_candidate = false;
+  else if (sframe_fre_stack_offset_bound_p (cfi_insn->u.ri.offset, true))
+    {
+      sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.ri.reg);
+      sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.ri.offset);
+      cur_fre->merge_candidate = false;
+    }
+  else
+    {
+      as_warn (_("no SFrame FDE emitted; "
+		 ".cfi_def_cfa with unsupported offset value"));
+      return SFRAME_XLATE_ERR_NOTREPRESENTED;
+    }
 
   return SFRAME_XLATE_OK;
 }
@@ -1117,8 +1144,17 @@ sframe_xlate_do_def_cfa_offset (struct sframe_xlate_ctx *xlate_ctx,
   if ((cur_fre->cfa_base_reg == SFRAME_CFA_FP_REG)
       || (cur_fre->cfa_base_reg == SFRAME_CFA_SP_REG))
     {
-      sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
-      cur_fre->merge_candidate = false;
+      if (sframe_fre_stack_offset_bound_p (cfi_insn->u.i, true))
+	{
+	  sframe_fre_set_cfa_offset (cur_fre, cfi_insn->u.i);
+	  cur_fre->merge_candidate = false;
+	}
+      else
+	{
+	  as_warn (_("no SFrame FDE emitted; "
+		     ".cfi_def_cfa_offset with unsupported offset value"));
+	  return SFRAME_XLATE_ERR_NOTREPRESENTED;
+	}
     }
   else
     {
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d
new file mode 100644
index 00000000000..a04d84d7cc3
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d
@@ -0,0 +1,17 @@
+#as: --gsframe
+#warning: cfi_def_cfa_offset with unsupported offset value
+#objdump: --sframe=.sframe
+#name: DW_CFA_def_cfa_offset with unsupported offset value
+#...
+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/cfi-sframe-x86_64-empty-pr33277.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.s
new file mode 100644
index 00000000000..aed084bf5da
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.s
@@ -0,0 +1,5 @@
+## CFA stack offset must be representable as a max 4-byte int.
+## No SFrame stack trace info for this function will be generated.
+	.cfi_startproc
+	.cfi_def_cfa_offset 1099511627808
+	.cfi_endproc
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 20828516546..96d34bfc17a 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -66,6 +66,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then {
 	run_dump_test "cfi-sframe-x86_64-empty-2"
 	run_dump_test "cfi-sframe-x86_64-empty-3"
 	run_dump_test "cfi-sframe-x86_64-empty-4"
+	run_dump_test "cfi-sframe-x86_64-empty-pr33277"
 	run_dump_test "cfi-sframe-x86_64-ra-undefined-1"
 	set ASFLAGS "$old_ASFLAGS"
     }
-- 
2.43.0



More information about the Binutils mailing list