2011-06-24 10 views

Odpowiedz

29

Ponieważ było w struct pt_regs, czyli .... 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) 

Tak, wiele narzędzi przestrzeni użytkownika spodziewać pole orig_eax tutaj, więc to jest wliczone w user_regs_struct też (być zgodne ze starszymi debuggerami i ptrace rs)

Następne pytanie brzmi "Dlaczego członek orig_eax jest zawarty w struct pt_regs?".

Został dodany w linuksie 0.95 http://lxr.linux.no/#linux-old+v0.95/include/sys/ptrace.h#L44. Sugeruję, że zostało to zrobione po jakimś innym systemie UNIX o strukturze pt_regs. Komentarz w 0,95 mówi

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

Więc miejsce orig_eax jest definiowany przez interfejs syscall. Tu jest 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 

Dlaczego musimy oszczędzać stary eax dwukrotnie? Ponieważ eax będą wykorzystywane do wartości zwracanej syscall (ten sam plik, poniżej bitowy):

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 musi być w stanie odczytać zarówno wszystkich rejestrach stanu sprzed syscall i wartości zwracanej syscall; ale wartość zwracana jest zapisana na %eax. Wtedy oryginalny eax, używany przed syscall zostanie utracony. Aby go zapisać, pojawi się pole orig_eax.

AKTUALIZACJA: Dzięki R .. i świetnemu LXR, przeprowadziłem pełne wyszukiwanie orig_eax w linuksie 0.95.

Jest on używany nie tylko w ptrace, ale również w do_signal podczas ponownego uruchamiania wywołania systemowego (jeśli istnieje syscall, zakończony ERESTARTSYS)

158      *(&eax) = orig_eax; 

Update2: Linus said coś ciekawego o tym:

Ważne jest, aby ORIG_EAX był ustawiony na pewną wartość, która jest , a nie a ważny numer wywołania systemowego, tak aby wywołanie systemowe zostało ponownie uruchomione (patrz: kod obsługi sygnału) nie uruchamia się.

UPDATE3: ptrace r app (debugger) może zmienić orig_eax zmienić liczbę wywołań systemowych na miano: http://lkml.org/lkml/1999/10/30/82 (w niektórych wersjach jądra, jest to EIO zmienić w ptrace się ORIG_EAX)

+2

pękanie odpowiedź (pozornie) wątłe pytanie! – sehe

+2

Doszedłem do wniosku, że było to związane z systemami operacyjnymi (i prawdopodobnie ponownym uruchomieniem syscall). +1 do śledzenia szczegółów! –

+0

Zwróć uwagę, że ostatnio zmieniono nazwę pola na jądro na orig_ax - jeśli chcesz wykonać wyszukiwanie LXR, wykonaj oba polecenia orig_eax i orig_ax. – osgx

Powiązane problemy