Почему orig_eax предоставляется в дополнение к eax? - PullRequest
15 голосов
/ 24 июня 2011

Почему член orig_eax включен в sys/user.h struct user_regs_struct?

1 Ответ

37 голосов
/ 24 июня 2011

Поскольку оно было в 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. Я полагаю, это было сделано после некоторого другого Unix с pt_regs struct.Комментарий в 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 я выполнил полный поиск orig_eax в linux 0.95.

Этоиспользуется не только в ptrace, но и в do_signal при перезапуске системного вызова (если есть системный вызов, заканчивающийся ERESTARTSYS)

 158                        *(&eax) = orig_eax;

ОБНОВЛЕНИЕ2: Линус сказал что-то интересное:

Важно, чтобы ORIG_EAX было установлено на какое-то значение, которое не действительный номер системного вызова, чтобы системный вызов перезапускал логику (см.код обработки сигнала) не запускается.

UPDATE3: ptrace r приложение (отладчик) может изменить orig_eax, чтобы изменить номер вызываемого системного вызова: http://lkml.org/lkml/1999/10/30/82 (внекоторые версии ядра, это EIO, чтобы изменить в ptrace ORIG_EAX)

...