2017-03-05 67 views
1

为什么syscall表中的某些系统调用有/ptregs?从arch/x86/entry/syscalls/syscall_64.tbl/系统调用表中的ptregs

例如:

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 

回答

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(),叉(),sigreturn()等)需要具有在堆栈上所有寄存器(包括RBP,RBX,R12-R15),在struct pt_regs 。这是因为这些系统调用会导致用户空间从一个不同的地方重新开始执行,所以他们需要保存准确的寄存器值。它们在syscall_64.tbl中用/ptregs标记,以便发生以下魔法。

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