https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128297

            Bug ID: 128297
           Summary: [LoongArch] loongarch_emit_probe_stack_range omits
                    RTX_FRAME_RELATED_P/CFI notes on intermediate SP
                    adjustments
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
  Target Milestone: ---
            Target: loongarch64-*-*

Summary
-------
Under `-O2 -fstack-clash-protection` (with default
`-fasynchronous-unwind-tables`),
the LoongArch prologue emits intermediate stack-pointer decrements during stack
probing without `RTX_FRAME_RELATED_P` or `REG_CFA_*` notes.

In `gcc/config/loongarch/loongarch.cc:1177-1221`
(`loongarch_emit_probe_stack_range`),
every `sub.d $r3, $r3, $r14` instruction is emitted via plain `emit_insn (...)`
without marking the insn frame-related. The total frame adjustment is only
recorded retroactively on the trailing blockage insn via
`loongarch_set_frame_expr`
(`loongarch.cc:1354-1360`).

Because `dwarf2cfi` only inspects frame-related instructions, the DWARF FDE
claims `CFA = $r3 + 16` across the entire multi-instruction (or multi-iteration
loop) probe sequence even after `$r3` has been decremented by thousands of
bytes.
Any asynchronous unwind (e.g. `perf`, `SIGPROF`, crash backtrace, or debugger
step) landing inside the probe sequence computes a bogus CFA.

Reproducer
----------
$ cat trigger.c
__attribute__((noinline)) void leaf (void);

void caller (void) {
    volatile char pad[8160];
    leaf ();
    pad[0] = 1;
}

Compile flag: loongarch64-linux-gnu-gcc -O2 -fstack-clash-protection
-fasynchronous-unwind-tables -S trigger.c

$ cat trigger.s
caller:
.LFB0:
        .cfi_startproc
        addi.d  $r3,$r3,-16
        .cfi_def_cfa_offset 16
        lu12i.w $r14,1
        st.d    $r1,$r3,8
        sub.d   $r3,$r3,$r14            # sp -= 4096 (missing
.cfi_def_cfa_offset!)
        st.d    $r0,$r3,0
        ori     $r14,$r0,4064
        sub.d   $r3,$r3,$r14            # sp -= 4064 (missing
.cfi_def_cfa_offset!)
        .cfi_def_cfa_offset 8176        # emitted only at the end of the probe
sequence
        la.local        $r12,leaf
        jirl    $r1,$r12,0

Suggested Fix
-------------
Attach `RTX_FRAME_RELATED_P` and `REG_CFA_ADJUST_CFA` notes to each
stack-pointer
adjustment emitted in `loongarch_emit_probe_stack_range` (or switch to a
frame-related scratch register for loop probing).

Reply via email to