https://gcc.gnu.org/g:45a17e3081120f51f8e8b1d7cda73c7d89453e85
commit r16-1834-g45a17e3081120f51f8e8b1d7cda73c7d89453e85 Author: Alexey Merzlyakov <alexey.merzlya...@samsung.com> Date: Mon Jun 30 13:58:29 2025 -0600 [RISC-V] Correct CFA notes for stack-clash protection [PR120714] Fixes incorrect SP-addresses used in CFA notes for the stack probes unrelative to the frame's top. It applied to the RISC-V targets code generation when the stack-clash protection is enabled. PR target/120714 gcc/ChangeLog: * config/riscv/riscv.cc (riscv_allocate_and_probe_stack_space): Fix SP-addresses in REG_CFA_DEF_CFA notes for stack-clash case. gcc/testsuite/ChangeLog: * gcc.target/riscv/pr120714.c: New test. Diff: --- gcc/config/riscv/riscv.cc | 13 ++++++++-- gcc/testsuite/gcc.target/riscv/pr120714.c | 40 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f5d2b2e74aed..cd6d6b992b50 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8978,12 +8978,20 @@ riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size) temp2 = riscv_force_temporary (temp2, gen_int_mode (rounded_size, Pmode)); insn = emit_insn (gen_sub3_insn (temp2, stack_pointer_rtx, temp2)); + /* The size does not represent actual stack pointer address shift + from the top of the frame, as it might be lowered before. + To consider the correct SP addresses for the CFA notes, it is needed + to correct them with the initial offset value. */ + HOST_WIDE_INT initial_cfa_offset + = cfun->machine->frame.total_size.to_constant () - size; + if (!frame_pointer_needed) { /* We want the CFA independent of the stack pointer for the duration of the loop. */ add_reg_note (insn, REG_CFA_DEF_CFA, - plus_constant (Pmode, temp1, rounded_size)); + plus_constant (Pmode, temp1, + initial_cfa_offset + rounded_size)); RTX_FRAME_RELATED_P (insn) = 1; } @@ -8996,7 +9004,8 @@ riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size) { insn = get_last_insn (); add_reg_note (insn, REG_CFA_DEF_CFA, - plus_constant (Pmode, stack_pointer_rtx, rounded_size)); + plus_constant (Pmode, stack_pointer_rtx, + initial_cfa_offset + rounded_size)); RTX_FRAME_RELATED_P (insn) = 1; } diff --git a/gcc/testsuite/gcc.target/riscv/pr120714.c b/gcc/testsuite/gcc.target/riscv/pr120714.c new file mode 100644 index 000000000000..dd71a3e11d3d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr120714.c @@ -0,0 +1,40 @@ +/* Test checking that the backtrace on large frame size with additional + SP shift in the prologue won't broken when compiled with the + -fstack-clash-protection option. */ +/* { dg-do run { target { *-*-linux* } } } */ +/* -O0 does not have enough optimizations. + -O2/-O3 does inline and reduces number of addresses in the backtrace. */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O2" "-O3" } } */ +/* { dg-options "-g -fstack-clash-protection" } */ + +#include <execinfo.h> + +#define MAX 4000 + +void goo () +{ + int addresses; + void *buffer[10]; + + addresses = backtrace (buffer, 10); + if (addresses != 6) + __builtin_abort (); +} + +int foo (int a) +{ + long long A[MAX]; + for (int i = 0; i < MAX; i++) + A[i] = i; + + goo (); + + return A[a % MAX]; +} + +int main () +{ + if (foo (20) != 20) + __builtin_abort (); + return 0; +}