]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: sframe: fix PR gas/33277
authorIndu Bhagat <indu.bhagat@oracle.com>
Wed, 5 Nov 2025 06:59:11 +0000 (22:59 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Wed, 5 Nov 2025 06:59:55 +0000 (22:59 -0800)
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.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
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
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.d [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-empty-pr33277.s [new file with mode: 0644]
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp

index 3ac1cf4338caf0541ddb84bf374546f8d8eaecf3..0d6edd362cbc54b977cda6f7c0a9d93bd6b72ec5 100644 (file)
@@ -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 (file)
index 0000000..a04d84d
--- /dev/null
@@ -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 (file)
index 0000000..aed084b
--- /dev/null
@@ -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
index 208285165469ad78cf8ffef6a352803ee672fe51..96d34bfc17a7288f60f681b7a96c8c2352fbd71f 100644 (file)
@@ -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"
     }