为什么系统调用表中的某些系统调用具有/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
答案 0 :(得分:2)
这些是特殊的系统调用,需要在堆栈中布置完整的寄存器转储(作为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函数插入到处理程序表中。