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

            Bug ID: 106153
           Summary: Generated arm64 code writing below stack pointer
                    without updating SP
           Product: gcc
           Version: 10.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: andy at plausible dot org
  Target Milestone: ---

The compiler is a arm64 gcc 10.3.0 from the Zephyr project SDK.  It's
a pretty standard crosstools-ng build.  Binaries at zephyrproject.org,
config/source at https://github.com/zephyrproject-rtos/sdk-ng

The short summary is that variable length array usage is generating
incorrect stack pointers; the memory gets used before the SP register
is decremented, leading to a race with the Zephyr interrupt handling
(which uses the interrupted stack during interrupt entry in some
configurations) that then corrupts the interrupted context.

See upstream Zephyr bug here:
https://github.com/zephyrproject-rtos/zephyr/pull/46967

A preprocessed "main.i" is attached that shows the bug fairly easily.
We build it with these arguments:

   aarch64-zephyr-elf-gcc -Os -fno-common -g -gdwarf-4 -mcpu=cortex-a53
-mabi=lp64 -Wall -Wformat -Wformat-security -Wno-format-zero-length -Wno-main
-Wno-pointer-sign -Wpointer-arith -Wexpansion-to-defined
-Wno-unused-but-set-variable -Werror=implicit-int
-fno-asynchronous-unwind-tables -fno-pie -fno-pic -ftls-model=local-exec
-fno-reorder-functions -fno-defer-pop -ffunction-sections -fdata-sections
-std=c99 -S -o - main.i

Doing so, it's easy to see constructions like this (scan down for the
"log_msgs:" function):

        mov     x19, sp           ;<-- x19 == sp
        mov     x22, x19          ;<-- x22 == sp
        str     xzr, [x29, 128]
        str     wzr, [x29, 136]
        str     x0, [x19, 24]
        mov     x0, x20
        str     x23, [x22, 16]!   ;<-- store through x22 into memory BELOW sp!
        strh    wzr, [x29, 140]
        mov     x2, x22
        bl      z_log_msg_static_create ;<-- and hand it to a function as an
argument!

We've worked around it with a compiler barrier for now.  As far as I can tell
it's only happening with arm64, plausibly because of the auto indexed "push"
addressing mode generation?

Reply via email to