为什么orig_eax
成员包含在sys/user.h
的{{1}}中?
答案 0 :(得分:35)
因为它位于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
成员包含在struct pt_regs
中?”。
它是在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
的位置由syscall接口定义。这是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需要能够读取syscall之前的所有寄存器状态和syscall的返回值;但返回值写入%eax
。然后在系统调用之前使用的原始eax
将丢失。要保存它,会有一个orig_eax
字段。
更新:感谢R ..和伟大的LXR,我在linux 0.95中对orig_eax
进行了全面搜索。
不仅在ptrace中使用,而且在重新启动系统调用时也在do_signal中使用(如果有系统调用,以ERESTARTSYS
结束)
158 *(&eax) = orig_eax;
UPDATE2:Linus said有趣的事情:
将ORIG_EAX设置为 not a的某个值非常重要 有效的系统调用号,以便系统调用重启逻辑(参见 信号处理代码)不会触发。
UPDATE3:ptrace
r app(调试器)可以更改orig_eax
以更改要调用的系统调用号:http://lkml.org/lkml/1999/10/30/82(在某些版本的内核中,是要在ptrace中更改的EIO一个ORIG_EAX)