1

编译器如何确保红色区域没有被破坏?是否有空间过度分配?

什么因素导致选择 128 字节作为红色区域的大小?

4

1 回答 1

3

编译器没有,它只是利用保证低于 RSP 的空间不会被异步破坏(例如通过信号处理程序)。进行函数调用当然会同步破坏它。

事实上,在 Linux 上,只有信号处理程序在用户空间代码中异步运行。(内核堆栈获得中断:为什么内核代码不能使用红区

内核在向用户空间传递信号时实现了红色区域。 我想就是这样。这真的很容易实现。

另一件相关的事情是当您print foo(123)在 GDB 中执行类似操作时调试器运行一个函数。GDB 将使用当前线程的堆栈实际运行该函数。在带有红色区域的 ABI 中,GDB(或任何其他调试器)在调用该函数时必须尊重它,方法是在保存寄存器状态后执行操作以在用户执行或单步rsp -= 128执行时恢复。continue

在 i386 System V 中,print foo(123)将使用当前 ESP 正下方的空间,踩踏 ESP 下方的任何内容。(我认为;未测试)。

什么因素导致选择 128 字节作为红色区域的大小?

类似寻址模式中的有符号字节位移[rsp - 128]可以达到那么远。IIRC,我在回答为什么 Windows64 使用与 x86-64 上的所有其他操作系统不同的调用约定时正在查看的 amd64.org 邮件存档?实际上包含一条消息,引用该消息作为该特定选择的原因。

您希望它足够大,以至于许多简单的叶函数不需要移动 RSP。例如,至少 16 或 32 字节,如 MS 的 Windows x64 调用约定中的 32 字节影子空间。

您希望它足够小,以便跳过它来调用信号处理程序不需要触及大量更多空间,例如新页面。小于 4kB。

需要超过 128 字节的局部函数的叶函数可能足够大,以至于移动 RSP 是杯水车薪。然后 +-disp8 寻址模式的好处开始发挥作用,可以访问整个 256 字节的空间,使用紧凑的寻址模式从byte [rsp+127]byte [rsp-128]或在 dword/qword 块中。


进一步阅读

阅读为什么在 Windows 或没有红区的 Linux 上使用低于 ESP 的空间是不安全的,这很有启发性

Raymond Chen 的博客:为什么我们甚至需要定义一个红色区域?我不能将我的堆栈用于任何事情吗?

我的 SO 回答也涵盖了一些相同的领域:写在 ESP 下面是否有效?(但比 Raymond 更多的猜测和更少有趣的 Windows 细节。)

于 2019-08-12T18:36:52.463 回答