System V ABI的红区是如何实现的

How system V ABI's red zone is implemented

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

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

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

事实上,在 Linux 上只有 信号处理程序 运行 在用户 space 代码中异步。 (内核堆栈获取中断:Why can't kernel code use a Red Zone

内核在向用户传递信号时实现了红区-space。我想就是这样;它真的很容易实现。

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

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

And what factors lead to choosing 128 byte as the size of red zone?

[rsp - 128]这样的寻址模式下的有符号字节位移可以达到那么远。 IIRC,我在回答 Why does Windows64 use a different calling convention from all other OSes on x86-64? 时查看的 amd64.org 邮件存档实际上包含一条消息,引用该消息作为该特定选择的原因。

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

您希望它足够小,以便跳过它来调用信号处理程序不需要像新页面那样触及更多 space。比 4kB 小得多。

需要超过 128 字节局部变量的叶函数可能足够大,以至于移动 RSP 只是九牛一毛。然后 +-disp8 寻址模式的好处开始发挥作用,可以访问整个 256 字节的 space 以及从 byte [rsp+127]byte [rsp-128] 或 dword/qword 块的紧凑寻址模式.


进一步阅读

阅读为什么在 Windows 或 Linux 上 space 下使用 space 不安全 是有启发性的.

陈峰的博客:Why do we even need to define a red zone? Can’t I just use my stack for anything?

我的 SO 回答也涵盖了一些相同的基础:(但与 Raymond 相比,更多的猜测和更不有趣的 Windows 细节。)