【问题标题】:/ptregs in syscall table/ptregs 在系统调用表中
【发布时间】:2017-03-05 14:02:19
【问题描述】:

为什么系统调用表中的某些系统调用有/ptregs?

来自arch/x86/entry/syscalls/syscall_64.tbl的示例:

54      64      setsockopt              sys_setsockopt
55      64      getsockopt              sys_getsockopt
56      common  clone                   sys_clone/ptregs
57      common  fork                    sys_fork/ptregs
58      common  vfork                   sys_vfork/ptregs
59      64      execve                  sys_execve/ptregs
60      common  exit                    sys_exit
61      common  wait4                   sys_wait4

【问题讨论】:

    标签: linux-kernel system-calls


    【解决方案1】:

    这些是特殊的系统调用,需要在堆栈上布置完整的寄存器转储(作为struct pt_regs)。这仅适用于 64 位 x86 架构,因为它有更多的寄存器(与 32 位相比)。

    系统调用处理程序 (arch/x86/entry/entry_64.S:entry_SYSCALL_64) 将大部分寄存器保存在系统调用入口的堆栈中。这样做部分是为了支持 ptrace(),部分是为了将参数传递给用 C 编写的实际系统调用处理程序(这就是为什么他们有 asmlinkage 规范,它使函数从堆栈中获取参数)。系统调用最多有 6 个参数(rdi、rsi、rdx、r10、r8、r9),并且一些寄存器用于 SYSCALL 簿记(rax、rcx、r11)。您不需要保存 rbp、rbx、r12、r13、r14、r15(因为它们是被调用者保存的),因此出于性能原因,它们不会在输入时保存。系统调用处理完成后,寄存器会从此备份中恢复,然后再返回用户空间。

    但是,一些系统调用(如 execve()、fork()、sigreturn() 等)需要在堆栈上有所有寄存器(包括 rbp、rbx、r12–r15) ,在struct pt_regs。这是因为这些系统调用会导致用户空间从不同的地方重新开始执行,因此它们需要保存准确的寄存器值。它们在 syscall_64.tbl 中用/ptregs 标记,以便发生以下魔术。

    通常系统调用处理程序表 (sys_call_table) 包含指向 C 函数的指针。但是对于那些特殊的系统调用,处理程序是small assembly thunks,它首先保存额外的寄存器,然后跳转到 C 代码(这就是慢路径所做的)。表中的 /ptregs 后缀指示脚本将这些存根而不是 C 函数插入到处理程序表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-25
      • 2011-06-13
      • 1970-01-01
      • 2016-02-09
      • 2011-06-23
      • 1970-01-01
      • 2021-09-16
      • 2021-09-19
      相关资源
      最近更新 更多