The red zone still exists even if you compile code not to use it. gcc -mno-red-zone
is purely a code-gen option, similar to -fno-omit-frame-pointer
, or MIPS GCC's -fno-delayed-branch
to leave delay slots only filled with NOP instead of useful instructions. gcc -mno-red-zone
merely avoids relying on space below RSP to keep its value, just like GCC always does in non-leaf functions.
Code compiled with -mno-red-zone
is ABI-compatible with code compiled with the default -mred-zone
. You can freely mix these options and link the resulting .o
files together into the same executable / library, or into different libraries or whatever.
The kernel's signal-delivery code and whatever else will still leave the 128 byte red zone below RSP unmodified. It doesn't know or care that the currently executing machine code isn't going to reload that data (in this case because the compiler chose not to keep anything there.) There's no mechanism for an executable to signal to the kernel that it shouldn't leave a gap of 128 bytes below the current stack pointer when delivering signals not using an alt-stack. (Because saving that small amount of stack space once is unimportant, and not worth having any extra kernel code to make it conditional. Signal handlers don't nest deeply, if at all, so it doesn't add up to a significant amount of total unused space.)
Despite it being a -m
option, it doesn't have to change the ABI (the way gcc -m32 -mregparm=3
does), just not optimize in ways that take advantage of that part of the ABI.
However, kernel code usually can't use a red-zone (unless it uses the TSS and IDT machinery to use alternate stacks for interrupts even when in kernel mode, which Linux doesn't), so must be compiled with -mno-red-zone
to match that ABI. Probably that's why it's a -m
option: you can think of it as telling GCC that the ABI its targeting doesn't provide a red zone. x86-64 SysV with a red-zone can run code compiled for x86-64 SysV without a red-zone, but not vice versa.
Related: