提问人:alessio solari 提问时间:8/28/2023 最后编辑:Peter Cordesalessio solari 更新时间:8/29/2023 访问量:113
即使我们在 gcc 中使用 -mno-red-zone 标志,红色区域是否仍然存在?
Does the red zone still exist even if we use the -mno-red-zone flag in gcc?
问:
我的系统:Ubuntu 22.04.3 在 x86_64上运行。GCC 版本 11.4.0
我读到System V ABI要求使用红色区域。来自 GCC 手册:
红色区域由 x86-64 ABI 强制执行,它是堆栈指针位置之外的 128 字节区域,不会被信号或中断处理程序修改,因此可用于临时数据,而无需调整堆栈指针。该标志禁用此红色区域。
-mno-red-zone
我的问题:
如果我在 gcc 中使用标志,红色区域是否仍然存在?
-mno-red-zone
如果红色区域为“禁用”,这是否意味着我不再遵守系统 V ABI?
这样做的后果是什么(不遵守系统 V ABI)?
答:
即使您编译代码以不使用它,红色区域仍然存在。 纯粹是一个代码生成选项,类似于 或 MIPS GCC,以仅使用 NOP 而不是有用的指令填充延迟槽。 只是避免依赖低于 RSP 的空间来保持其值,就像 GCC 在非叶函数中总是这样做一样。gcc -mno-red-zone
-fno-omit-frame-pointer
-fno-delayed-branch
gcc -mno-red-zone
使用 -mno-red-zone
编译的代码与使用默认 -mred-zone
编译的代码兼容。您可以自由混合这些选项,并将生成的文件链接到同一个可执行文件/库中,或链接到不同的库或其他任何内容中。.o
内核的信号传递代码和其他任何代码仍将保留 RSP 下方 128 字节的红色区域不变。它不知道也不关心当前正在执行的机器代码不会重新加载该数据(在这种情况下,因为编译器选择不保留任何内容)。没有机制让可执行文件向内核发出信号,表明在传递不使用 alt-stack 的信号时,它不应该在当前堆栈指针下方留下 128 个字节的间隙。(因为一次节省少量的堆栈空间并不重要,也不值得任何额外的内核代码来使其成为有条件的。信号处理程序不会嵌套得很深,因此它不会累积大量未使用的总空间。
尽管它是一个选项,但它不必更改 ABI(方式确实如此),只是不以利用 ABI 的那部分的方式进行优化。-m
gcc -m32 -mregparm=3
但是,内核代码通常不能使用红色区域(除非它使用 TSS 和 IDT 机制使用备用堆栈进行中断,即使在内核模式下也是如此,而 Linux 则不这样做),因此必须编译以匹配该 ABI。可能这就是为什么它是一个 -m
选项:你可以把它看作是告诉 GCC 它的 ABI 它的目标不提供红色区域。具有红色区域的 x86-64 SysV 可以运行为没有红色区域的 x86-64 SysV 编译的代码,反之亦然。-mno-red-zone
相关:
评论
-mno-red-zone
sys_rt_sigaction
-mno-red-zone