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

            Bug ID: 128395
           Summary: [sparc] load from the function's own frame placed in
                    the delay slot of return
           Product: gcc
           Version: 16.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stian at itx dot no
  Target Milestone: ---
            Target: sparc64-unknown-linux-gnu

Created attachment 66076
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=66076&action=edit
rdc4.c

On sparc64 with -O2 -fno-stack-protector, returning an element of a local array
indexed by
an argument gives

        return  %i7+8
         ldx    [%o0+1999], %o0

The delay slot runs after the window restore, so this reads the dead frame
below the new
%sp. A signal or trap taken on that instruction overwrites it and the load
returns garbage.

rds4.c (compile with -O2 -fno-stack-protector, see cpu_clock_sample_group in
the -S output)
reproduces it at runtime with SIGALRM at 10 kHz (about 150
wrong results in 60 million calls on an M7). The Linux sparc64 kernel is built
this way and
cpu_clock_sample_group() in kernel/time/posix-cpu-timers.c gets exactly this
sequence, so
clock_gettime(CLOCK_PROCESS_CPUTIME_ID) returns a trap's TSTATE about once a
second. A
kernel built with the patched compiler does not.

eligible_for_restore_insn() accepts any insn without local or output registers
in the return
case, including a load through an incoming register that now holds a frame
address. The
patch allows a memory reference there only when every address register is an
unmodified
incoming argument register, which keeps "return p->field". Tested on
sparc64-unknown-linux-gnu, new test gcc.target/sparc/return-delay-mem.c, no
change in
sparc.exp.

Reply via email to