2012-05-02 9 views
15

Plik ELF dla plików wykonywalnych ma program (segment) nagłówek i nagłówek sekcji, które mogą być postrzegane przez readelf -a, oto przykład:jaka część pliku ELF musi być załadowana do pamięci?

enter image description here

enter image description here

Dwa zdjęcia powyżej są odpowiednio nagłówek sekcji i nagłówek programu (segmentu). Widać, że nagłówek segmentu składa się z kilku nagłówków sekcji, które służą do wczytywania programu do pamięci.

Czy konieczne jest tylko ładowanie do pamięci części .text, .rodata, .data, .bss?

Czy wszystkie inne sekcje w segmencie (np. .ektory, .dtors .jcr w trzecim segmencie) są używane do wyrównywania?

+1

Dla _równomierności_? –

+0

@ Adriano, tak wyrównanie do rozmiaru strony, więc różne ochrony mogą być używane dla różnych części programu, na przykład .text (rx), dane (rw-) –

Odpowiedz

18

Sekcje i segmenty to całkowicie różne koncepcje. Sekcje odnoszą się do semantyki przechowywanych tam danych (tj. Do czego będzie ona używana) i są faktycznie nieistotne, gdy program lub biblioteka współdzielona jest połączona z wyjątkiem celów debugowania. Możesz nawet całkowicie usunąć nagłówki sekcji (lub zastąpić je losowymi śmieciami), a program nadal będzie działał.

Segmenty (tj. Dyrektywy ładowania nagłówka programu) są tym, na co właściwie wygląda jądro i/lub dynamiczny łącznik podczas ładowania programu. Na przykład w twoim przypadku masz dwie dyrektywy obciążenia. Pierwsza powoduje, że pierwsza 4k (1 strona) pliku jest mapowana pod adresem 0x08048000 i wskazuje, że tylko pierwsze 0x4b8 bajtów tego odwzorowania są faktycznie używane (reszta to wyrównanie). Drugi powoduje, że pierwsze 8k (2 strony) pliku ma być odwzorowane pod adresem 0x08049000. Ogromna większość to dostosowanie. Pierwsze bajty 0xf14 nie są częścią dyrektywy ładującej (tylko wyrównanie) i zostaną zmarnowane. Począwszy od 0x08049f14, faktycznie używane są bajty 0x108 zmapowane z pliku, a kolejne 0x10 bajtów (aby osiągnąć rozmiar Memsize 0x118) są wypełnione zerowo przez moduł ładujący (jądro lub dynamiczny linker). Rozciąga się to na 0x0804a02c (na drugiej zmapowanej stronie). Reszta drugiej zmapowanej strony jest nieużywana/zmarnowana (ale malloc może być w stanie odzyskać ją do użycia jako część sterty).

Wreszcie, podczas gdy nagłówki sekcji nie będą w ogóle używane, zawartość wielu różnych sekcji może być używana przez program podczas jego działania. Zauważ, że zakresy adresów .ctors i .dtors leżą na początku drugiego mapowania obciążenia, więc są mapowane i dostępne dla programu w czasie wykonywania (kod startowy/wyjściowy środowiska wykonawczego użyje ich do uruchomienia globalnych konstruktorów i destruktorów, jeśli C++ lub Zastosowano kod "GNU C" z atrybutem ctor/dtor). Zauważ też, że .data rozpoczyna się pod adresem 0x0804a00c, na drugiej zmapowanej stronie. Dzięki temu pierwsza strona może być chroniona tylko do odczytu po zastosowaniu relokacji (dyrektywa RELRO w nagłówku programu).

+0

+1 za wskazanie GNU_RELRO – SquareRootOfTwentyThree

+0

Czy C ma konstruktorów lub destruktory jako C++? –

+0

Nie, ale GCC to nie C, to "GNU C". Możesz wykonywać różnego rodzaju niestandardowe czynności, takie jak wyjątki i konstruktory. –

Powiązane problemy