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 <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.
This commit is contained in:
Indu Bhagat
2025-11-04 22:59:11 -08:00
parent 58fedddb89
commit 6384e241e8
4 changed files with 64 additions and 5 deletions

View 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
{

View File

@@ -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

View File

@@ -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

View 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"
}