【问题标题】:How system V ABI's red zone is implementedSystem V ABI的红区是如何实现的
【发布时间】:2019-12-19 06:23:01
【问题描述】:

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

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

【问题讨论】:

  • 没有何时被破坏?如果一个固定大小的空间,你认为在什么意义上可能会在上下文中过度分配?

标签: linux gcc x86-64 abi red-zone


【解决方案1】:

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

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

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

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

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

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

像[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 字节影子空间。

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

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


进一步阅读

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

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

我的 SO 回答也涵盖了一些相同的领域:Is it valid to write below ESP?(但与 Raymond 相比,猜测更多,Windows 细节更不有趣。)

【讨论】:

    猜你喜欢
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多