Смысл вывода pmap

12

Я написал main.cв Linux:

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

Когда я компилирую и запускаю, я могу 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

Итого (3876), деленное на K, равно VIRTстолбцу в выходных данных top. Теперь, где текстовый сегмент? На 400000, 600000 и 601000, верно? Где я могу прочитать объяснение, что где? man pmapне помогло.

Торстен Стэрк
источник
текстовые сегменты на самом деле только для чтения, так что это в 0000000000600000.
Данила Ладнер
Благодарность! Разве текстовый сегмент не должен быть исполняемым?
Торстен Стэрк
1
Да ты прав. r и rx. 0000000000400000 также.
Данила Ладнер

Ответы:

14

Текстовый сегмент - это отображение в 0x400000 - он помечен как rx для удобочитаемого и исполняемого. Отображение в 0x600000 доступно только для чтения, так что это почти наверняка раздел «.rodata» исполняемого файла. GCC помещает строковые литералы C в раздел только для чтения. Отображение в 0x601000 'rw-', так что это, вероятно, знаменитая куча. Вы можете иметь исполняемый файл malloc()размером 1024 байта и распечатать адрес, чтобы убедиться в этом.

Вы можете получить немного больше информации, найдя PID вашего процесса и выполнив: cat /proc/$PID/maps- на моем ноутбуке Arch, что дает дополнительную информацию. На нем запущено ядро ​​3.12, так что у него также есть /proc/$PID/numa_mapsи catting, что также может дать небольшую информацию.

Другие вещи для запуска исполняемого файла: nmи objdump -x. Первый может дать вам представление о том, где находятся различные объекты на карте памяти, поэтому вы можете увидеть, что находится в разделе 0x4000000 по сравнению с другими разделами. objdump -xПоказывает заголовки файлов ELF среди множества других вещей, так что вы можете увидеть все разделы, заполненные именами разделов, и их отображением во время выполнения или нет.

Чтобы найти письменное объяснение «что это где», вам придется сделать что-то вроде google для «ELF FILE memory layout». Помните, что формат файла ELF может поддерживать более экзотические макеты памяти, чем обычно используются. GCC и Gnu ld и glibc делают упрощенные предположения о том, как исполняемый файл размещается и затем отображается в памяти во время выполнения. Существует множество веб-страниц, предназначенных для документирования этого, но они применяются только к более старым версиям Linux, более старым версиям GCC или glibc или только к исполняемым файлам x86. Если у вас его нет, получите readelfкоманду. Если вы можете писать программы на C, создайте свою собственную версию objdump -xили readelfознакомьтесь с тем, как работают исполняемые файлы и что в них.

Брюс Эдигер
источник
2
Отличный ответ. Теперь, где куча программы? И что это [анон] означает? Что мне нужно гуглить, чтобы это выяснить?
Торстен Стэрк
1
Знаешь что? Я ошибся насчет отображения адресов 0x601000 - наверное, это куча. Вы должны будете использовать readelfили objdumpвыяснить это, и любой исполняемый файл, который вы сделали. Мой пакет Linux для Linux использует /usr/lib/libc-2.18.so, поэтому он сильно отличается от вашего.
Брюс Эдигер
2
0x601000это сегмент данных. Она содержит .data, .bssи может быть расширена с помощью brk(). [anon]указывает на не файловую резервную копию памяти (поэтому поддерживается swap), полученную через mmap(). dlmalloc использует brk()для распределений, меньших чем ~ 64Kb IIRC, и mmap()для больших распределений. Куча - это все, что выделяет malloc, как расширенная часть сегмента данных, так и mmap()распределения на основе.
ниндзя