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;
}
{
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;
}
--- /dev/null
+/* 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;
+}