为什么除了eax还提供了orig_eax?

为什么在sys/user.hstruct user_regs_struct包含orig_eax成员?

因为它在struct pt_regs ,这是… http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/arch/x86/include/asm/user_32.h#L77

  73 * is still the layout used by user mode (the new 74 * pt_regs doesn't have all registers as the kernel 75 * doesn't use the extra segment registers) 

因此,许多用户空间实用程序期望在此处有一个orig_eax字段,因此它也包含在user_regs_struct (为了与较早的调试器和ptrace rs兼容)

下一个问题是“为什么orig_eax包含orig_eax成员?”。

它被添加到Linux 0.95 http://lxr.linux.no/#linux-old+v0.95/include/sys/ptrace.h#L44 。 我建议这是在pt_regs结构的其他一些unix之后完成的。 在0.95评论说

  29 * this struct defines the way the registers are stored on the 30 * stack during a system call. 

所以, orig_eax的位置是由系统调用接口定义的。 这是http://lxr.linux.no/#linux-old+v0.95/kernel/sys_call.s

  17 * Stack layout in 'ret_from_system_call': 18 * ptrace needs to have all regs on the stack. 19 * if the order here is changed, it needs to be 20 * updated in fork.c:copy_process, signal.c:do_signal, 21 * ptrace.c ptrace.h 22 * 23 * 0(%esp) - %ebx ... 29 * 18(%esp) - %eax ... 34 * 2C(%esp) - orig_eax 

为什么我们需要保存旧的eax两次? 因为eax将被用于syscall的返回值(同一个文件,稍低于):

  96_system_call: 97 cld 98 pushl %eax # save orig_eax 99 push %gs ... 102 push %ds 103 pushl %eax # save eax. The return value will be put here. 104 pushl %ebp ... 117 call _sys_call_table(,%eax,4) 

Ptrace需要能够读取系统调用之前的所有寄存器状态和系统调用的返回值; 但返回值写入%eax 。 那么系统调用之前使用的原始eax将会丢失。 为了保存它,有一个orig_eax字段。

更新:感谢R ..和伟大的LXR,我在Linux 0.95做了一个完整的搜索orig_eax

它不仅在ptrace中使用,而且在重新启动系统调用(如果有系统调用,以ERESTARTSYS结束)

  158 *(&eax) = orig_eax; 

更新2:莱纳斯说了一些有趣的事情:

将ORIG_EAX设置为某个不是有效系统调用号的值是很重要的,这样系统调用重启逻辑(请参阅信号处理代码)不会触发。

UPDATE3: ptrace r app(调试器)可以改变orig_eax来改变被调用的系统调用号: http : orig_eax (在某些版本的内核中,是EIO改变的跟踪一个ORIG_EAX)