Pliki fs/binfmt_kodformatu.c
load_format_binary( struct linux_binprm *bprm,
struct pt_regs *regs)
Funkcje ładujące program konkretnego formatu
Algorytm
Choć różne formaty w różny sposób odwzorowują w pamięci wykonywany
program oraz udostępniają (lub nie) różne możliwości, to schemat
algorytmu jest ten sam. Szkic został sporządzony na podstawie formatu
ELF.
- Sprawdza pewne numery "magiczne" z pierwszych 128 bajtów pliku
(bprm->buf) w celu rozpoznania, czy jest to plik tego
formatu. Jeśli nie, zwraca -ENOEXEC.
- Czyta nagłówek pliku w celu ustalenia rozmieszczenia segmentów
programu i potrzebnych bibliotek współdzielonych.
- Znajduje w pliku ścieżkę do interpretera i pobiera strukturę
file dla niego, sprawdzając prawa wykonania (znów
open_exec()).
- Ustawia pole personality procesu.
- Wykonuje pewne sprawdznia spójności interpretera i jego typu.
- Kopiuje do pamięci jądra argumenty programu i wywołuje
flush_old_exec(), która to funkcja zwalnia zasoby starego
programu:
- Zapewnia otrzymanie nowej struktury obsługi sygnałów, jeśli
była współdzielona - make_private_signals(). Ustawia
tablicę obsługi sygnałów na działanie domyślne -
release_old_signals() oraz później wywołana flush_old_signals().
- Zwalnia wszystkie bloki stron i regiony pamięci należące do
procesu - funkcja exec_mmap(). Pamięć procesu jest
"wyczyszczona".
- flush_thread() i do_thread odpowiadają
za wyczyszczenie wszelkich rejestrów.
- Zamyka wszelkie pliki z flagą close_on_exec - funkcja
flush_old_files()
To jest "punkt bez powrotu" - zmian nie da się już odwrócić.
- Odwzorowuje w pamięci "nowego" programu bloki stronicowe
zawierające argumenty wywołania / zmienne środowiskowe i tworzy
region stosu użytkownika - setup_arg_pages().
- Odwzorowuje kod i dane programu w pamięci procesu. Zostaną one
sprowadzone z dysku do pamięci przy pierwszej próbie odwołania.
- Ładuje interpreter programu
-load_format_interpreter(). Podzczas ładowania w
pamięci procesu odwzorowuje się kod i dane programu interpretera.
- Ustala nowe uprawnienia procesu.
- Czyści flagę PF_FORKNOEXEC.
- Tworzy tablice z parametrami dla interpretera i zachowuje ją na
stosie trybu użytkownika.
- Ustala adresy początków (i ew. końców) kodu, danych i stosu
procesu - start_code, end_code, start_brk, end_brk,
start_stack.
- Mapuje w pamięci procesu strony segmentu bss - set_brk()
- Makro start_thread ustawia rejestry wskaźników kodu i
stosu na początek interpretera programu i wierzchołek stosu trybu
użytkownika.
- Jeśli proces jest śledzony, wysyła do niego SIGTRAP.
- Zwraca 0 - sukces!.
Po powrocie do trybu użytkownika, proces zaczyna wykonywać kod interpretera.
Pobiera on ze stosu dane przekazane w funkcji load_binary().
Odwzorowuje w pamięci procesu potrzebne biblioteki współdzielone.
Po uaktualnieniu wszelkich informacji o
odniesieniach i zapewnieniu spójności wykonuje skok do początku
świeżo załadowanego programu i rozpoczyna jego wykonanie.