Какая часть файла ELF должна быть загружена в память?

В файле ELF для исполняемых файлов есть заголовок программы (сегмента) и заголовок раздела, который можно увидеть через readelf -a, вот пример:

enter image description here

enter image description here

Два изображения выше - заголовок заголовка раздела и заголовка программы (сегмента), соответственно. Можно видеть, что заголовок сегмента состоит из нескольких заголовков разделов, которые используются для загрузки программы в память.

Нужно ли только загружать в память разделы .text,.rodata,.data,.bss?

Используются ли все остальные разделы в сегменте (например .ctors,.dtors.jcr в третьем сегменте)?

Ответы

Ответ 1

Разделы и сегменты - это две разные концепции. Разделы относятся к семантике хранимых там данных (то есть к чему они будут использоваться) и фактически неактуальны, если программа или разделяемая библиотека связаны, за исключением целей отладки. Вы даже можете полностью удалить заголовки разделов (или перезаписать их случайным мусором), и программа все равно будет работать.

Сегменты (например, директивы загрузки заголовков программ) - это то, на что на самом деле смотрят ядро ​​и/или динамический компоновщик при загрузке программы. Например, в вашем случае у вас есть две директивы нагрузки. Первая приводит к отображению первой 4k (1 страницы) файла по адресу 0x08048000 и указывает, что на самом деле должны использоваться только первые 0x4b8 байтов этого сопоставления (остальное - выравнивание). Второе приводит к отображению первых 8k (2 страницы) файла по адресу 0x08049000. Подавляющее большинство из них - выравнивание. Первые байты 0xf14 не являются частью директивы load (просто выравнивание) и будут потрачены впустую. Начиная с 0x08049f14, фактически используются 0x108 байт, отображенные из файла, и еще 0x10 байт (для достижения MemSize 0x118) заполняются нулевым загрузчиком (ядром или динамическим компоновщиком). Это составляет до 0x0804a02c (на второй сопоставленной странице). Остальная часть второй отображаемой страницы не используется/потеряна (но malloc может восстановить ее для использования как часть кучи).

Наконец, в то время как заголовки разделов не будут использоваться вообще, содержимое многих разных разделов может использоваться вашей программой во время ее работы. Обратите внимание, что диапазоны адресов .ctors и .dtors лежат в начале второго сопоставления нагрузки, поэтому они отображаются и доступны программой во время выполнения (код запуска/выхода во время выполнения будет использовать их для запуска глобальных конструкторов и деструкторов, если использовался код С++ или "GNU C" с атрибутом ctor/dtor). Также обратите внимание, что .data начинается с адреса 0x0804a00c, на второй отображаемой странице. Это позволяет первой странице защищаться только для чтения после применения релокаций (директива RELRO в заголовке программы).