Die Bedeutung der Ausgabe von pmap

12

Ich schrieb main.cin Linux:

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

Wenn ich es kompiliere und starte, kann ich pmapes:

# 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) geteilt durch K entspricht der VIRTSpalte in der Ausgabe von top. Wo ist nun das Textsegment? Bei 400000, 600000 und 601000, richtig? Wo kann ich eine Erklärung lesen, was ist wo? man pmaphat nicht geholfen.

Thorsten Staerk
quelle
Textsegmente sind eigentlich schreibgeschützt, es liegt also bei 0000000000600000.
Danila Ladner
Vielen Dank! Sollte das Textsegment nicht auch ausführbar sein?
Thorsten Staerk
1
Ja, du hast recht. r und rx. 0000000000400000 auch.
Danila Ladner

Antworten:

14

Das Textsegment ist das Mapping bei 0x400000 - es ist als 'rx' für lesbar und ausführbar markiert. Die Zuordnung bei 0x600000 ist schreibgeschützt, das ist also mit ziemlicher Sicherheit der Abschnitt ".rodata" der ausführbaren Datei. GCC fügt C-String-Literale in einen schreibgeschützten Abschnitt ein. Die Zuordnung bei 0x601000 ist 'rw-', das ist also wahrscheinlich der berühmte Haufen. Sie könnten Ihre ausführbare Datei malloc()1024 Bytes haben und die Adresse ausdrucken, um sicher zu gehen.

Möglicherweise erhalten Sie ein wenig mehr Informationen, indem Sie die PID Ihres Prozesses ermitteln und Folgendes ausführen: cat /proc/$PID/maps- Auf meinem Arch-Laptop werden einige zusätzliche Informationen angezeigt. Es wird ein 3.12-Kernel ausgeführt, also auch ein /proc/$PID/numa_mapsCatting, das möglicherweise auch einen kleinen Einblick gibt.

Andere Dinge, die für die ausführbare Datei ausgeführt werden müssen: nmund objdump -x. Ersteres kann Ihnen eine Vorstellung davon geben, wo verschiedene Dinge in der Speicherzuordnung liegen, sodass Sie sehen können, was sich im Abschnitt 0x4000000 im Vergleich zu den anderen Abschnitten befindet. objdump -xZeigt Ihnen unter anderem ELF-Dateikopfzeilen an, sodass Sie alle Abschnitte einschließlich der Abschnittsnamen und der Zuordnung zu einer Laufzeit anzeigen können.

Um eine schriftliche Erklärung für "Was ist wo?" Zu finden, müssen Sie beispielsweise Google für "ELF-DATEI-Speicherlayout" ausführen. Beachten Sie, dass das ELF-Dateiformat mehr exotische Speicherlayouts unterstützt, als normalerweise verwendet werden. GCC, Gnu ld und glibc machen alle vereinfachende Annahmen darüber, wie eine ausführbare Datei angeordnet und dann zur Laufzeit in den Speicher abgebildet wird. Es gibt viele Webseiten, die dies dokumentieren sollen, aber nur für ältere Versionen von Linux, ältere Versionen von GCC oder glibc oder nur für x86-ausführbare Dateien gelten. Wenn Sie es nicht haben, rufen Sie den readelfBefehl ab. Wenn Sie C-Programme schreiben können, erstellen Sie eine eigene Version von objdump -xoder readelfmachen Sie sich mit der Funktionsweise und den darin enthaltenen ausführbaren Dateien vertraut.

Bruce Ediger
quelle
2
Gute Antwort. Wo ist der Haufen des Programms? Und was bedeutet das? Was muss ich googeln, um das herauszufinden?
Thorsten Staerk
1
Weißt du was? Ich habe mich bei der 0x601000-Adresszuordnung geirrt - das ist wahrscheinlich der Haufen. Sie müssen readelfoder verwenden, objdumpum es herauszufinden, und was auch immer die ausführbare Datei, die Sie gemacht haben. Meine Arch Linux Box verwendet /usr/lib/libc-2.18.so, es ist also ganz anders als deine Box.
Bruce Ediger
2
0x601000ist das Datensegment. Es enthält .data, .bssund kann über verlängert werden brk(). [anon]Gibt an, dass der Speicher nicht dateigesichert ist (also durch Auslagerung gesichert ist), der über abgerufen wurde mmap(). dlmalloc verwendet brk()für Zuordnungen, die kleiner als ~ 64 KB IIRC sind, und mmap()für größere Zuordnungen. Der Heap ist alles, was von malloc zugewiesen wird, sowohl der erweiterte Teil des Datensegments als auch die auf mmap()-basierten Zuweisungen.
Ninjalj