21

Why is the orig_eax member included in sys/user.h's struct user_regs_struct?

bdonlan
  • 224,562
  • 31
  • 268
  • 324
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

1 Answers1

48

Because it was in struct pt_regs, which is .... 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)

So, a lot of user-space utilities expect an orig_eax field here, so it is included in user_regs_struct too (to be compatible with older debuggers and ptracers)

Next question is "Why is the orig_eax member included in struct pt_regs?".

It was added in linux 0.95 http://lxr.linux.no/#linux-old+v0.95/include/sys/ptrace.h#L44. I suggest this was done after some other unix with pt_regs struct. Comment in 0.95 says

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

So, the place of orig_eax is defined by syscall interface. Here it is 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

Why do we need to save old eax twice? Because eax will be used for the return value of syscall (same file, a bit below):

  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 needs to be able to read both all registers state before syscall and the return value of syscall; but the return value is written to %eax. Then original eax, used before syscall will be lost. To save it, there is a orig_eax field.

UPDATE: Thanks to R.. and great LXR, I did a full search of orig_eax in linux 0.95.

It is used not only in ptrace, but also in do_signal when restarting a syscall (if there is a syscall, ended with ERESTARTSYS)

 158                        *(&eax) = orig_eax;

UPDATE2: Linus said something interesting about it:

It's important that ORIG_EAX be set to some value that is not a valid system call number, so that the system call restart logic (see the signal handling code) doesn't trigger.

UPDATE3: ptracer app (debugger) can change orig_eax to change system call number to be called: http://lkml.org/lkml/1999/10/30/82 (in some versions of kernel, is was EIO to change in ptrace an ORIG_EAX)

ctuffli
  • 3,559
  • 4
  • 31
  • 43
osgx
  • 90,338
  • 53
  • 357
  • 513
  • 4
    cracking answer to a (seemingly) flimsy question! – sehe Jun 24 '11 at 14:50
  • 2
    I figured it was related to syscalls (and possibly syscall restarting). +1 for tracking down the details! – R.. GitHub STOP HELPING ICE Jun 24 '11 at 16:18
  • note, that recent kernels renamed field to orig_ax - if you want to do a LXR search, do both orig_eax and orig_ax. – osgx Jun 24 '11 at 16:38
  • Why would it need orig_eax anyway? Why would it matter what system call it is after the appropriate one was invoked? As I understand, the return value of system call is written to the stack, where late we pop it and save it in eax. And orig_eax is there just to make sure we do not loose the sys call invoked. My other question, why is the return value written on stack and not immediately to eax? – Tony Tannous Apr 14 '18 at 22:05