https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127318
Bug ID: 127318
Summary: [riscv64] RVV stack-clash probe loop sets CFA base to
t3 before t3 is initialised
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220255623 at seu dot edu.cn
CC: 220245569 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Created attachment 65556
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65556&action=edit
Minimal reproducer, assembly/FDE evidence, and complete GCC 17.0.0 20260531 and
GCC 16.1.0 compiler output for the RISC-V RVV stack-clash CFI ordering defect.
Compiling the attached trigger with:
riscv64-linux-gnu-gcc -O3 -march=rv64gcv -mabi=lp64d \
-fstack-clash-protection -funwind-tables -fno-stack-protector \
-c trigger.c -o trigger.o
produces this prologue:
.cfi_def_cfa 28, 0
...
mv t3,sp
Register 28 is t3. The decoded FDE therefore changes the CFA base to t3 at PC
offset 0xa, but mv t3,sp executes at 0x24. From 0xa through 0x23 the unwinder
uses the previous value of t3 as the CFA base.
Expected: the CFA change must not apply before mv t3,sp initializes t3.
Actual: unwind metadata describes t3 as the CFA base while t3 is still stale.
This reproduces with GCC 17.0.0 20260531 and GCC 16.1.0. The input is valid and
compiles cleanly with -Wall -Wextra -Werror. The attached zip contains the
minimal reproducer, the relevant assembly and readelf output, and complete
compiler output for both versions.
The source cause is in riscv_allocate_and_probe_space: it saves
get_last_insn() before emitting the sp-to-t3 move and attaches
REG_CFA_DEF_CFA to that older instruction. The analogous AArch64 SVE path
attaches the note to the emit_move_insn result.