From 6384e241e8fd037e2aab1da34da7a0bf0b2ea521 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Tue, 4 Nov 2025 22:59:11 -0800 Subject: [PATCH] gas: sframe: fix PR gas/33277 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 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.47.3