繁体   English   中英

Linux x86-64 系统调用破坏 %r8、%r9 和 %r10 什么时候?

[英]When does Linux x86-64 syscall clobber %r8, %r9 and %r10?

我刚刚浏览了 Linux 内核源代码树并阅读了文件tools/include/nolibc/nolibc.h

我看到这个文件中的syscall在 clobber 列表中使用了%r8%r9%r10
还有一条评论说:

rcx 和 r8..r11 可能会被破坏,其他的会被保留。

据我所知, syscall只破坏%rax%rcx%r11 (和内存)。

是否有一个真实的syscall示例来破坏%r8%r9%r10

只有 64 位模式下的 32 位系统调用(例如通过int 0x80 )和 R11 一起在这些寄存器上执行。 如果您在 64 位代码中使用 32 位 int 0x80 Linux ABI,会发生什么? )。

syscall正确保存/恢复所有 regs,包括 R8、R9 和 R10,因此使用它的用户空间可以假设它们保留它们的值,除了 RAX 返回值。 (内核的系统调用入口点甚至保存了 RCX 和 R11,但此时它们已经被syscall指令本身用原始 RIP 和屏蔽前的 RFLAGS 值覆盖了。)


那些带有 R11 的寄存器是在函数调用约定中被调用破坏的非遗留寄存器,因此内核中 C 函数的编译器生成的代码自然会保留 R12-R15,即使 asm 入口点没有保存他们。

目前,64 位int 0x80入口点只是为进程状态结构中的调用破坏的 R8-R11 寄存器推送0 ,它将在返回用户空间之前从中恢复,而不是原始寄存器值。 也许早些时候有信息泄漏,在内核代码返回后它们没有受到影响?

根据 x86-64 ABI 关于系统调用部分 A.2 AMD64 Linux 内核约定,A.2.1 调用约定 [1]:

  1. 用户级应用程序使用整数寄存器来传递序列%rdi%rsi%rdx%rcx%r8%r9 内核接口使用%rdi%rsi%rdx%r10%r8%r9

  2. 系统调用是通过syscall指令完成的。 内核销毁寄存器%rcx%r11

  3. syscall的编号必须在寄存器%rax传递。

  4. 系统调用仅限于六个参数,没有参数直接在堆栈上传递。

  5. syscall返回,寄存器%rax包含系统调用的结果。 -4095 和 -1 之间范围内的值表示错误,它是 -errno。

  6. 只有类 INTEGER 或类 MEMORY 的值被传递给内核。

从 (2)、(5) 和 (6),我们可以得出结论,Linux x86-64 系统调用 clobbers %rax%rcx%r11 (以及"memory" )。

链接: https : //gitlab.com/x86-psABI/x86-64-ABI/-/wikis/x86-64-psABI [1]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM