linux - 系统V ABI的红色区域是如何实现的

标签 linux gcc x86-64 abi red-zone

编译器如何确保红色区域不被破坏?是否存在空间过度分配的情况?

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

最佳答案

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

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

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

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

在 i386 System V 中,print foo(123) 将使用当前 ESP 正下方的空间,踩在 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 字节影子空间。

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

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


进一步阅读

了解为什么在 Windows 上使用 ESP 下面的空间安全,或者在没有红区的 Linux 上使用,是有启发性的。

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

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

关于linux - 系统V ABI的红色区域是如何实现的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57465132/

相关文章:

python - Pyserial 发送超过一个字节

macos - Qt5.1/Qt5.2 + Mac OS 10.9 (Mavericks) + XCode 5.0.2,架构 x86_64 的 undefined symbol

linux - 如何在 Linux 内核中递归读取目录的内容?

linux - 如何在 64 位 RHEL 5.4 上升级 glibc

linux - 如何使用命令 SIOCGIFFLAGS 和 SIOCSIFFLAGS 原子地调用 ioctl

c - 一次又一次初始化时,指针在循环内做了什么?

c - 防止 gcc 内联所有函数

c - 使用内联组件绘制像素 VGA

kernel - x86-64 架构中的分页

C# 应用程序 list 被忽略/不工作