Формат ELF
Формат ELF
Формат ELF имеет файлы нескольких типов, которые до сих пор мы называли по-разному, например, исполняемый файл или объектный файл. Тем не менее стандарт ELF различает следующие типы:
1. Перемещаемый файл (relocatable file), хранящий инструкции и данные, которые могут быть связаны с другими объектными файлами. Результатом такого связывания может быть исполняемый файл или разделяемый объектный файл.
2. Разделяемый объектный файл (shared object file) также содержит инструкции и данные, но может быть использован двумя способами. В первом случае, он может быть связан с другими перемещаемыми файлами и разделяемыми объектными файлами, в результате будет создан новый объектный файл. Во втором случае, при запуске программы на выполнение операционная система может динамически связать его с исполняемым файлом программы, в результате чего будет создан исполняемый образ программы. В последнем случае речь идет о разделяемых библиотеках.
3. Исполняемый файл хранит полное описание, позволяющее системе создать образ процесса. Он содержит инструкции, данные, описание необходимых разделяемых объектных файлов, а также необходимую символьную и отладочную информацию.
На рис. 2.4 приведена структура исполняемого файла, с помощью которого операционная система может создать образ программы и запустить программу на выполнение.
Рис. 2.4. Структура исполняемого файла в формате ELF
Заголовок имеет фиксированное расположение в файле. Остальные компоненты размещаются в соответствии с информацией, хранящейся в заголовке. Таким образом заголовок содержит общее описание структуры файла, расположение отдельных компонентов и их размеры.
Поскольку заголовок ELF-файла определяет его структуру, рассмотрим его более подробно (табл. 2.4).
Таблица 2.3. Поля заголовка ELF-файла
Поле Описание е_ident[] Массив байт, каждый из которых определяет некоторую общую характеристику файла: формат файла (ELF), номер версии, архитектуру системы (32-разрядная или 64-разрядная) и т.д. e_type Тип файла, поскольку формат ELF поддерживает несколько типов e_machine Архитектура аппаратной платформы, для которой создан данный файл. В табл. 2.4 приведены возможные значения этого поля e_version Номер версии ELF-формата. Обычно определяется как EV_CURRENC (текущая), что означает последнюю версию e_entry Виртуальный адрес, по которому системой будет передано управление после загрузки программы (точка входа) e_phoff Расположение (смещение от начала файла) таблицы заголовков программы е_shoff Расположение таблицы заголовков секций е_ehsize Размер заголовка e_phentsize Размер каждого заголовка программы e_phnum Число заголовков программы e_shentsize Размер каждого заголовка сегмента (секции) е_shnum Число заголовков сегментов (секций) e_shstrndx Расположение сегмента, содержащего таблицу строкТаблица 2.4. Значения поля e_machine заголовка ELF-файла
Значение Аппаратная платформа ЕМ_М32 AT&T WE 32100 ЕМ_SPARC Sun SPARC ЕМ_386 Intel 80386 ЕМ_68K Motorola 68000 EM_88K Motorola 88000 ЕМ_486 Intel 80486 ЕМ_860 Intel i860 ЕМ_MIPS MIPS RS3000 Big-Endian EM_MIPS_RS3_LE MIPS RS3000 Little-Endian EM_RS6000 RS6000 EM_PA_RISC PA-RISC EM_nCUBE nCUBE EM_VPP500 Fujitsu VPP500 EM_SPARC32PLUS Sun SPARC 32+Информация, содержащаяся в таблице заголовков программы, указывает ядру, как создать образ процесса из сегментов. Большинство сегментов копируются (отображаются) в память и представляют собой соответствующие сегменты процесса при его выполнении, например, сегменты кода или данных.
Каждый заголовок сегмента программы описывает один сегмент и содержит следующую информацию:
? Тип сегмента и действия операционной системы с данным сегментом
? Расположение сегмента в файле
? Стартовый адрес сегмента в виртуальной памяти процесса
? Размер сегмента в файле
? Размер сегмента в памяти
? Флаги доступа к сегменту (запись, чтение, выполнение)
Часть сегментов имеет тип LOAD, предписывающий ядру при запуске программы на выполнение создать соответствующие этим сегментам структуры данных, называемые областями, определяющие непрерывные участки виртуальной памяти процесса и связанные с ними атрибуты. Сегмент, расположение которого в ELF-файле указано в соответствующем заголовке программы, будет отображен в созданную область, виртуальный адрес начала которой также указан в заголовке программы. К сегментам такого типа относятся, например, сегменты, содержащие инструкции программы (код) и ее данные. Если размер сегмента меньше размера области, неиспользованное пространство может быть заполнено нулями. Такой механизм, в частности используется при создании неинициализированных данных процесса (BSS). Подробнее об областях мы поговорим в главе 3.
В сегменте типа INTERP хранится программный интерпретатор. Данный тип сегмента используется для программ, которым необходимо динамическое связывание. Суть динамического связывания заключается в том, что отдельные компоненты исполняемого файла (разделяемые объектные файлы) подключаются не на этапе компиляции, а на этапе запуска программы на выполнение. Имя файла, являющегося динамическим редактором связей, хранится в данном сегменте. В процессе запуска программы на выполнение ядро создает образ процесса, используя указанный редактор связей. Таким образом, первоначально в память загружается не исходная программа, а динамический редактор связей. На следующем этапе динамический редактор связей совместно с ядром UNIX создают полный образ исполняемого файла. Динамический редактор загружает необходимые разделяемые объектные файлы, имена которых хранятся в отдельных сегментах исходного исполняемого файла, и производит требуемое размещение и связывание. В заключение управление передается исходной программе.
Наконец, завершает файл таблица заголовков разделов или секций (section). Разделы (секций) определяют разделы файла, используемые для связывания с другими модулями в процессе компиляции или при динамическом связывании. Соответственно, заголовки содержат всю необходимую информацию для описания этих разделов. Как правило разделы содержат более детальную информацию о сегментах. Так, например, сегмент кода может состоять из нескольких разделов, таких как хэш-таблица для хранения индексов используемых в программе символов, раздел инициализационного кода программы, таблица связывания, используемая динамическим редактором, а также раздел, содержащий собственно инструкции программы.
Мы еще вернемся к формату ELF в главе 3 при обсуждении организации виртуальной памяти процесса, а пока перейдем к следующему распространенному формату — COFF.
Данный текст является ознакомительным фрагментом.