O significado da saída do pmap

12

Eu escrevi main.cno Linux:

int main()
{
  while (1){}
}

Quando eu compilo e inicio, posso 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

total (3876) dividido por K é igual à VIRTcoluna na saída de top. Agora, onde está o segmento de texto? Em 400000, 600000 e 601000, certo? Onde posso ler uma explicação, o que é onde? man pmapnão ajudou.

Thorsten Staerk
fonte
os segmentos de texto são realmente somente leitura, portanto, é 0000000000600000.
Danila Ladner
Obrigado! O segmento de texto não deve ser executável também?
Thorsten Staerk
1
Sim você está certo. rex. 0000000000400000 também.
Danila Ladner

Respostas:

14

O segmento de texto é o mapeamento em 0x400000 - está marcado como 'rx' para legível e executável. O mapeamento em 0x600000 é somente leitura, portanto é quase certamente a seção ".rodata" do arquivo executável. O GCC coloca literais da cadeia C em uma seção somente leitura. O mapeamento em 0x601000 é 'rw-', então essa é provavelmente a famosa pilha. Você pode ter seus malloc()1024 bytes executáveis e imprimir o endereço para ter certeza.

Você pode obter um pouco mais de informações encontrando o PID do seu processo e fazendo: cat /proc/$PID/maps- no meu laptop Arch, isso fornece algumas informações extras. Ele está rodando um kernel 3.12, por isso também tem /proc/$PID/numa_maps, e o catting também pode fornecer uma pequena visão.

Outras coisas para executar no arquivo executável: nme objdump -x. O primeiro pode dar uma idéia de onde estão várias coisas no mapa de memória, para que você possa ver o que está na seção 0x4000000 em comparação às outras seções. objdump -xmostra os cabeçalhos de arquivo ELF entre muitas outras coisas, para que você possa ver todas as seções, completas com os nomes das seções e se elas estão mapeadas em tempo de execução ou não.

Quanto a encontrar uma explicação por escrito de "o que é onde", você precisará fazer coisas como o google para "layout de memória ELF FILE". Esteja ciente de que o formato de arquivo ELF pode suportar layouts de memória mais exóticos do que normalmente são usados. GCC, Gnu ld e glibc fazem suposições simplificadoras sobre como um arquivo executável é organizado e, em seguida, mapeado para a memória em tempo de execução. Existem muitas páginas da Web que pretendem documentar isso, mas se aplicam apenas a versões mais antigas do Linux, versões mais antigas do GCC ou glibc, ou apenas a executáveis ​​x86. Se você não tiver, obtenha o readelfcomando. Se você puder escrever programas em C, crie sua própria versão objdump -xou readelfse familiarize com o funcionamento dos arquivos executáveis ​​e o que há neles.

Bruce Ediger
fonte
2
Ótima resposta. Agora, onde está a pilha do programa? E o que isso significa? O que tenho no google para descobrir isso?
Thorsten Staerk
1
Você sabe o que? Eu estava errado sobre o mapeamento de endereço 0x601000 - esse é o monte, provavelmente. Você terá que usar readelfou objdumpdescobrir, e qualquer que seja o executável que você criou. Minha caixa do Linux linux usa /usr/lib/libc-2.18.so, então é bem diferente da sua caixa.
precisa
2
0x601000é o segmento de dados. Ele contém .data, .bsse pode ser estendido via brk(). [anon]indica memória não suportada por arquivo (suportada por troca), obtida via mmap(). O dlmalloc usa brk()para alocações menores que ~ 64Kb IIRC e mmap()para alocações maiores. O heap é tudo alocado pelo malloc, tanto a parte estendida do segmento de dados quanto as mmap()alocações baseadas em.
Ninjalj