Napisałem main.c
w systemie Linux:
int main()
{
while (1){}
}
Kiedy kompiluję i uruchamiam, mogę pmap
:
# pmap 28578
28578: ./a.out
0000000000400000 4K r-x-- /root/a.out
0000000000600000 4K r---- /root/a.out
0000000000601000 4K rw--- /root/a.out
00007f87c16c2000 1524K r-x-- /lib/libc-2.11.1.so
00007f87c183f000 2044K ----- /lib/libc-2.11.1.so
00007f87c1a3e000 16K r---- /lib/libc-2.11.1.so
00007f87c1a42000 4K rw--- /lib/libc-2.11.1.so
00007f87c1a43000 20K rw--- [ anon ]
00007f87c1a48000 128K r-x-- /lib/ld-2.11.1.so
00007f87c1c55000 12K rw--- [ anon ]
00007f87c1c65000 8K rw--- [ anon ]
00007f87c1c67000 4K r---- /lib/ld-2.11.1.so
00007f87c1c68000 4K rw--- /lib/ld-2.11.1.so
00007f87c1c69000 4K rw--- [ anon ]
00007fff19b82000 84K rw--- [ stack ]
00007fff19bfe000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 3876K
suma (3876) podzielona przez K równa się VIRT
kolumnie na wyjściu top
. Gdzie jest teraz segment tekstu? Przy 400000, 600000 i 601000, prawda? Gdzie mogę przeczytać wyjaśnienie, gdzie jest? man pmap
nie pomogło.
linux
process
memory
virtual-memory
Thorsten Staerk
źródło
źródło
Odpowiedzi:
Segment tekstowy jest mapowany na 0x400000 - jest oznaczony jako „rx”, aby można go było odczytać i wykonać. Mapowanie w 0x600000 jest tylko do odczytu, więc prawie na pewno jest to sekcja „.rodata” pliku wykonywalnego. GCC umieszcza literały ciągów C w sekcji tylko do odczytu. Mapowanie w 0x601000 to „rw-”, więc prawdopodobnie jest to słynna sterta. Możesz mieć wykonywalne
malloc()
1024 bajty i wydrukować adres, aby się upewnić.Możesz uzyskać trochę więcej informacji, znajdując PID swojego procesu i wykonując:
cat /proc/$PID/maps
- na moim laptopie Arch, daje to dodatkowe informacje. Działa z jądrem 3.12, więc ma również/proc/$PID/numa_maps
i catting, który może dać trochę wglądu.Inne rzeczy do uruchomienia na pliku wykonywalnym:
nm
iobjdump -x
. Ten pierwszy może dać ci wyobrażenie o tym, gdzie różne rzeczy leżą na mapie pamięci, dzięki czemu możesz zobaczyć, co jest w sekcji 0x4000000 w porównaniu do innych sekcji.objdump -x
pokazuje nagłówki plików ELF wśród wielu innych rzeczy, dzięki czemu można zobaczyć wszystkie sekcje, wraz z nazwami sekcji i tym, czy są one mapowane w czasie wykonywania, czy nie.Jeśli chodzi o znalezienie pisemnego wyjaśnienia „co jest gdzie”, musisz zrobić takie rzeczy jak Google dla „Układu pamięci ELF FILE”. Należy pamiętać, że format pliku ELF może obsługiwać bardziej egzotyczne układy pamięci, niż się powszechnie stosuje. GCC i Gnu ld i glibc przyjmują uproszczone założenia, w jaki sposób plik wykonywalny jest układany, a następnie odwzorowywany w pamięci w czasie wykonywania. Istnieje wiele stron internetowych, które mają to udokumentować, ale dotyczą tylko starszych wersji Linuksa, starszych wersji GCC lub glibc lub dotyczą tylko plików wykonywalnych x86. Jeśli go nie masz, pobierz
readelf
polecenie. Jeśli potrafisz pisać programy w języku C, utwórz własną wersjęobjdump -x
lubreadelf
zapoznaj się ze sposobem działania plików wykonywalnych i ich zawartością.źródło
readelf
lubobjdump
rozgryźć, i niezależnie od tego, jaki plik wykonywalny stworzyłeś. My Arch Linux korzysta z /usr/lib/libc-2.18.so, więc jest zupełnie inny niż twój box.0x601000
to segment danych. Zawiera on.data
,.bss
i może zostać przedłużony przezbrk()
.[anon]
wskazuje pamięć nieopartą na plikach (tak zabezpieczoną przez swap), uzyskaną przezmmap()
. dlmalloc używabrk()
do przydziałów mniejszych niż ~ 64Kb IIRC orazmmap()
do większych przydziałów. Na stercie jest wszystko przydzielane przez malloc, zarówno rozszerzona część segmentu danych, jak immap()
przydziały oparte na bazie .