From: Alexey Merzlyakov <[email protected]>
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.
(cherry picked from commit 45a17e3081120f51f8e8b1d7cda73c7d89453e85)
---
gcc/config/riscv/riscv.cc | 13 ++++++--
gcc/testsuite/gcc.target/riscv/pr120714.c | 40 +++++++++++++++++++++++
2 files changed, 51 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/pr120714.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d3656a7a430..962bfe3aea5 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8686,12 +8686,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;
}
@@ -8704,7 +8712,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 00000000000..dd71a3e11d3
--- /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;
+}
--
2.50.1
--
Andreas Schwab, SUSE Labs, [email protected]
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."