Различные адреса в заголовке ELF и виртуальной памяти процесса - PullRequest
4 голосов
/ 18 марта 2012

Я вижу изображение процесса через pmap в linux:

08048000       0       4       0 r-x--  [my program]

08049000       0       4       4 rw---  [my program]

Три сегмента выше - это сегменты кода, родаты и данных, которые все выровнены по PAGESIZE (4K), но когда я ставлюкоманда objdump -h, заголовки ELF отображаются следующим образом:

read-only code segment
Load off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
     filesz 0x00000448 memsz 0x00000448 flags r-x

read/write data segment
Load off 0x00000448 vaddr 0x08049448 paddr 0x08049448 align 2**12
     filesz 0x000000e8 memsz 0x00000104 flag rw-

В заголовке ELF говорится, что сегмент кода и сегмент данных адресуются из 0x08048000,0x049448 в виртуальном адресе отдельно, что отличается отобраз процесса в памяти.Я знаю, что сегмент кода / данных должен быть назначен разной PAGESIZE, что может дать им разные права защиты.Однако, как программа может выполняться, если реальный виртуал отличается от двоичного файла эльфа?

1 Ответ

4 голосов
/ 18 марта 2012

Способ загрузки ELF-программ (и отображение памяти в целом из файлов) осуществляется на основе страниц. Таким образом, используемые адреса, смещения в файлах и размер должны быть кратны размеру страницы.

Однако загрузчик программы достаточно умен, чтобы иметь дело с разделами, которые не начинаются или не заканчиваются точно на границе страницы, округляя их до границы страницы, отображая больше, чем требуется. Поэтому некоторые дополнительные данные будут загружены из файла для заполнения страницы, но к ним не следует обращаться, чтобы это не имело значения.

В вашем примере сегмент кода загружается по адресу 0x08048000 со смещением 0x0 с размером 0x448. Адрес и смещение выровнены, поэтому нужно просто округлить размер до полной страницы. Сегмент данных загружается в 0x08049448 со смещением 0x448. Они не выровнены, но совместимы - загрузчик округляет до кратной страницы (0x08049000 и 0x000) и отображает на этой странице. Обратите внимание, что в результате получается та же страница в файле, что и в сегменте кода, поэтому страница загружается по двум разным адресам: один только для чтения, а другой для чтения-записи-без общего доступа. Таким образом, код и данные в конечном итоге становятся видимыми в двух местах в образе процесса, но это неважно - код заканчивается rx на 0x8048000..0x8048447, а данные заканчиваются на rw- на 0x8049448..0x804954b, что все это вопросы.

...