https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84521
Bug ID: 84521
Summary: [8 Regression] aarch64: Frame-pointer corruption with
setjmp/longjmp and -fomit-frame-pointer
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: dmalcolm at gcc dot gnu.org
CC: jgreenhalgh at gcc dot gnu.org, marcus.shawcroft at arm dot
com,
rearnsha at gcc dot gnu.org, wilco at gcc dot gnu.org
Target Milestone: ---
Host: aarch64-unknown-linux-gnu
Target: aarch64-unknown-linux-gnu
Build: aarch64-unknown-linux-gnu
The downstream bug report here:
https://bugzilla.redhat.com/show_bug.cgi?id=1545239
describes a problem seen on aarch64 with gcc 8 that breaks the build of Ruby at
-O1 and above.
Bisection shows that the problem started with r254815, which made
-fomit-frame-pointer the default.
Jakub reported:
> It is actually much older, I get the same crash if vm.c is compiled with
> -mlittle-endian -mabi=lp64 -g -grecord-gcc-switches -O1 -Wall
> -Werror=format-security
> -fexceptions -fPIC -fstack-protector -fno-strict-overflow
> -fexcess-precision=standard -fomit-frame-pointer
> with r204770, so already GCC 4.9 behaves that way too.
> Note ruby uses -fno-omit-frame-pointer already, but only on mingw32.
The issue is that the code generated for __builtin_longjmp reads a value for
x29 (the frame pointer) from the jmp_buf, but the code generated for
__builtin_setjmp doesn't actually write x29 to the jmp_buf, leading to
corruption of x29 when a longjmp occurs.
This corruption seems to be short-lived when -fno-omit-frame-pointer (the old
default), as every function restores x29 from the stack on exit.
With the new default of -fomit-frame-pointer the corruption can survive long
enough to cause crashes.
There's a lot more analysis at the downstream bug report in the URL above.
I'm about to attach a reproducer.
I'm marking this as "[8 Regression]" since although this is appears to be a
long-standing bug, the change of default in r254815 exposes it by default.