为什么sys/user.h的struct user_regs_struct中包含orig_eax成员
发布于 2011-06-24 22:16:13
因为它是在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中(以便与较旧的调试器和ptracers兼容)。
下一个问题是“为什么struct pt_regs中包含orig_eax成员?”
它是在Linux0.95 http://lxr.linux.no/#linux-old+v0.95/include/sys/ptrace.h#L44中添加的。我建议这是在其他unix使用pt_regs结构之后完成的。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?因为syscall的返回值将使用eax (下面的文件相同):
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,我在Linux0.95中全面搜索了orig_eax。
它不仅在ptrace中使用,在重启syscall时也会在do_signal中使用(如果有syscall,以ERESTARTSYS结尾)
158 *(&eax) = orig_eax;UPDATE2: Linus said一些有趣的事情:
必须将ORIG_EAX设置为无效的系统调用编号,这样系统调用重启逻辑(请参阅信号处理代码)才不会触发。
UPDATE3:ptracer应用程序(调试器)可以更改orig_eax以更改要调用的系统调用号:http://lkml.org/lkml/1999/10/30/82 (在某些版本的内核中,在ptrace和ORIG_EAX中更改的是was EIO )
https://stackoverflow.com/questions/6468896
复制相似问题