[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