La signification de la sortie de pmap

12

J'ai écrit main.csous Linux:

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

Quand je le compile et le démarre, je le peux 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) divisé par K est égal à la VIRTcolonne dans la sortie de top. Maintenant, où est le segment de texte? À 400000, 600000 et 601000, non? Où puis-je lire une explication, où est-il? man pmapn'a pas aidé.

Thorsten Staerk
la source
les segments de texte sont en fait en lecture seule, il s'agit donc de 0000000000600000.
Danila Ladner
Merci! Le segment de texte ne devrait-il pas également être exécutable?
Thorsten Staerk
1
Oui, tu as raison. r et rx. 0000000000400000 également.
Danila Ladner

Réponses:

14

Le segment de texte est le mappage à 0x400000 - il est marqué «rx» pour lisible et exécutable. Le mappage à 0x600000 est en lecture seule, c'est donc presque certainement la section ".rodata" du fichier exécutable. GCC place les littéraux de chaîne C dans une section en lecture seule. Le mappage à 0x601000 est 'rw-', donc c'est probablement le fameux tas. Vous pourriez avoir votre malloc()1024 octets exécutable et imprimer l'adresse pour voir avec certitude.

Vous pourriez obtenir un peu plus d'informations en trouvant le PID de votre processus et en faisant: cat /proc/$PID/maps- sur mon ordinateur portable Arch, cela donne des informations supplémentaires. Il exécute un noyau 3.12, donc il en a aussi /proc/$PID/numa_maps, et un catting qui pourrait aussi donner un petit aperçu.

Autres choses à exécuter sur le fichier exécutable: nmet objdump -x. Le premier peut vous donner une idée de l'emplacement de diverses choses dans la carte mémoire, vous pouvez donc voir ce qui se trouve dans la section 0x4000000 par rapport aux autres sections. objdump -xvous montre les en-têtes de fichiers ELF parmi beaucoup d'autres choses, afin que vous puissiez voir toutes les sections, complètes avec les noms de section et si elles sont mappées lors de l'exécution ou non.

Pour ce qui est de trouver une explication écrite de "où est-il", vous devrez faire des choses comme google pour "la disposition de la mémoire du fichier ELF". Sachez que le format de fichier ELF peut prendre en charge des dispositions de mémoire plus exotiques que celles couramment utilisées. GCC et Gnu ld et glibc font tous des hypothèses simplificatrices sur la façon dont un fichier exécutable est disposé puis mappé en mémoire au moment de l'exécution. Il existe de nombreuses pages Web qui prétendent documenter cela, mais ne s'appliquent qu'aux anciennes versions de Linux, aux anciennes versions de GCC ou de la glibc, ou ne s'appliquent qu'aux exécutables x86. Si vous ne l'avez pas, obtenez la readelfcommande. Si vous pouvez écrire des programmes C, créez votre propre version de objdump -xou readelfpour vous familiariser avec le fonctionnement des fichiers exécutables et leur contenu.

Bruce Ediger
la source
2
Très bonne réponse. Maintenant, où est le tas du programme? Et qu'est-ce que cela [anon] signifie? Que dois-je sur Google pour le savoir?
Thorsten Staerk
1
Vous savez quoi? J'avais tort sur le mappage d'adresse 0x601000 - c'est probablement le tas. Vous devrez utiliser readelfou objdumppour le comprendre, et quel que soit l'exécutable que vous avez créé. Ma boîte Linux Arch utilise /usr/lib/libc-2.18.so, donc c'est assez différent de votre boîte.
Bruce Ediger
2
0x601000est le segment de données. Il contient .data, .bsset peut être étendue via brk(). [anon]indique la mémoire non sauvegardée par les fichiers (donc sauvegardée par swap), obtenue via mmap(). dlmalloc utilise brk()pour des allocations inférieures à ~ 64 Ko IIRC et mmap()pour des allocations plus importantes. Le tas est tout ce qui est alloué par malloc, à la fois la partie étendue du segment de données et les mmap()allocations basées sur.
ninjalj