From: Indu Bhagat Date: Thu, 8 Jan 2026 20:11:17 +0000 (-0800) Subject: gas: sframe: fix PR gas/33756 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1674e47227965dbf85c5fee59b0858afd191284c;p=thirdparty%2Fbinutils-gdb.git gas: sframe: fix PR gas/33756 Previously, sframe_xlate_do_remember_state () relied exclusively on last_fre (the last Frame Row Entry for the previous PC range block). At the start of a function (before an advance in location), last_fre is NULL. The intent of DW_CFA_remember_state, however, is to simply snapshot the state of the call frame information at the time. In terms of SFrame generation, this means that we should simply look at cur_fre (the scratchpad FRE currently being built from initial CFI instructions in the current context). Remove the common-empty-1.s which assumed that .cfi_startproc, immediately followed by a .cfi_remember_state is not present out in the wild. Its best to not make such an assumption, as such a sequence is valid CFI, FWIW. Initial CFI are arch-specific, so add a new testcase for x86_64 to check .cfi_remember_state handling for SFrame is sensible. While at at, also add a new testcase for s390x. Co-Authored-by: Jens Remus Reviewed-by: Jens Remus gas/ PR gas/33756 * gen-sframe.c (sframe_xlate_do_remember_state): Use cur_fre. gas/testsuite/ * gas/cfi-sframe/cfi-sframe.exp: Adjust common-empty-1 test to be repurposed as cfi-sframe-x86_64-pr33756. Add s390x testcase. * gas/cfi-sframe/common-empty-1.d: Removed. * gas/cfi-sframe/common-empty-1.s: Removed. * gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d: New test. * gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s: New test. * gas/cfi-sframe/cfi-sframe-s390x-pr33756.d: New test. * gas/cfi-sframe/cfi-sframe-s390x-pr33756.s: New test. --- diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c index 3e329c92001..4a70ae13ff5 100644 --- a/gas/gen-sframe.c +++ b/gas/gen-sframe.c @@ -1349,12 +1349,12 @@ sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx, static int sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx) { - const struct sframe_row_entry *last_fre = xlate_ctx->last_fre; + const struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre; /* If there is no FRE state to remember, nothing to do here. Return early with non-zero error code, this will cause no SFrame stack trace info for the function involved. */ - if (!last_fre) + if (!cur_fre) { as_warn (_("no SFrame FDE emitted; " ".cfi_remember_state without prior SFrame FRE state")); @@ -1363,7 +1363,7 @@ sframe_xlate_do_remember_state (struct sframe_xlate_ctx *xlate_ctx) if (!xlate_ctx->remember_fre) xlate_ctx->remember_fre = sframe_row_entry_new (); - sframe_row_entry_initialize (xlate_ctx->remember_fre, last_fre); + sframe_row_entry_initialize (xlate_ctx->remember_fre, cur_fre); return SFRAME_XLATE_OK; } diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d new file mode 100644 index 00000000000..e572592a06b --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.d @@ -0,0 +1,23 @@ +#as: --gsframe +#objdump: --sframe=.sframe +#name: SFrame generation on s390x - .cfi_remember_state after .cfi_startproc PR gas/33756 +#... +Contents of the SFrame section .sframe: + + Header : + + Version: SFRAME_VERSION_2 + Flags: SFRAME_F_FDE_FUNC_START_PCREL + Num FDEs: 1 + Num FREs: 4 + + Function Index : + + func idx \[0\]: pc = 0x0, size = 20 bytes + STARTPC +CFA +FP +RA + + 0+0000 +sp\+160 +u +u + + 0+0006 +sp\+160 +c-72 +c-48 + + 0+000c +sp\+320 +c-72 +c-48 + + 0+0012 +sp\+160 +u +u + + +#pass diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s new file mode 100644 index 00000000000..7126d30284e --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-pr33756.s @@ -0,0 +1,23 @@ + .text + .type foo, @function +foo: + .cfi_startproc + .cfi_remember_state + stmg %r6,%r15,48(%r15) + .cfi_rel_offset 6, 48 + .cfi_rel_offset 7, 56 + .cfi_rel_offset 8, 64 + .cfi_rel_offset 9, 72 + .cfi_rel_offset 10, 80 + .cfi_rel_offset 11, 88 + .cfi_rel_offset 12, 96 + .cfi_rel_offset 13, 104 + .cfi_rel_offset 14, 112 + .cfi_rel_offset 15, 120 + lay %r15,-160(%r15) + .cfi_adjust_cfa_offset 160 + lmg %r6,%r15,160+48(%r15) + .cfi_restore_state + br %r14 + .cfi_endproc + .size foo, .-foo diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d new file mode 100644 index 00000000000..3ae3aeb0e57 --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.d @@ -0,0 +1,24 @@ +#as: --gsframe +#objdump: --sframe=.sframe +#name: cfi_remember_state after cfi_startproc PR gas/33756 +#... +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: 1 + Num FREs: 3 + + Function Index : + + func idx \[0\]: pc = 0x0, size = 16 bytes + STARTPC +CFA +FP +RA + + 0+0000 +sp\+8 +u +[uf] + + 0+0004 +sp\+16 +u +[uf] + + 0+000c +sp\+8 +u +[uf] + + +#pass diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s new file mode 100644 index 00000000000..c31b443932d --- /dev/null +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-x86_64-pr33756.s @@ -0,0 +1,13 @@ + .text + .type foo, @function +foo: + .cfi_startproc + .cfi_remember_state + .long 0 + .cfi_def_cfa_offset 16 + .long 0 + .long 0 + .cfi_restore_state + .long 0 + .cfi_endproc + .size foo, .-foo diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp index d2fa2d82f18..4dbe69bc097 100644 --- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp +++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp @@ -49,7 +49,6 @@ if { ([istarget "x86_64-*-*"] || [istarget "aarch64*-*-*"] run_dump_test "cfi-sframe-common-11" run_dump_test "cfi-sframe-common-12" - run_dump_test "common-empty-1" run_dump_test "common-empty-2" run_dump_test "common-empty-3" } @@ -62,6 +61,7 @@ if { [istarget "x86_64-*-*"] && [gas_sframe_check] } then { run_dump_test "cfi-sframe-x86_64-2" run_dump_test "cfi-sframe-x86_64-3" run_dump_test "cfi-sframe-x86_64-pr33170" + run_dump_test "cfi-sframe-x86_64-pr33756" run_dump_test "cfi-sframe-x86_64-empty-1" run_dump_test "cfi-sframe-x86_64-empty-2" run_dump_test "cfi-sframe-x86_64-empty-3" @@ -95,4 +95,5 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then { run_dump_test "cfi-sframe-s390x-fpra-register-1" run_dump_test "cfi-sframe-s390x-fpra-register-2" run_dump_test "cfi-sframe-s390x-ra-undefined-1" + run_dump_test "cfi-sframe-s390x-pr33756" } diff --git a/gas/testsuite/gas/cfi-sframe/common-empty-1.d b/gas/testsuite/gas/cfi-sframe/common-empty-1.d deleted file mode 100644 index c64dd92e003..00000000000 --- a/gas/testsuite/gas/cfi-sframe/common-empty-1.d +++ /dev/null @@ -1,17 +0,0 @@ -#as: --gsframe -#warning: \.cfi_remember_state without prior SFrame FRE state -#objdump: --sframe=.sframe -#name: Uninteresting cfi directives generate an empty SFrame section -#... -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/common-empty-1.s b/gas/testsuite/gas/cfi-sframe/common-empty-1.s deleted file mode 100644 index e26e998189f..00000000000 --- a/gas/testsuite/gas/cfi-sframe/common-empty-1.s +++ /dev/null @@ -1,5 +0,0 @@ - .cfi_sections .sframe - .cfi_startproc - .cfi_remember_state - .cfi_restore_state - .cfi_endproc