Расширение имени файла | none, .axf , .bin , .elf , .o , .out , .prx , .puff , .ko , .mod и .so |
---|---|
Магическое число | 0x7F 'E' 'L' 'F' |
Разработано | Лаборатории систем Unix [1] : 3 |
Тип формата | Двоичный , исполняемый , объект , разделяемая библиотека , дамп ядра |
Контейнер для | Множество исполняемых двоичных форматов |
В вычислительной технике Executable and Linkable Format [2] ( ELF , ранее назывался Extensible Linking Format ) — это общепринятый стандартный формат файлов для исполняемых файлов, объектного кода , разделяемых библиотек и дампов ядра . Впервые опубликованный в спецификации для двоичного интерфейса приложений (ABI) версии операционной системы Unix под названием System V Release 4 (SVR4) [3] , а затем в Tool Interface Standard [1] , он был быстро принят различными поставщиками систем Unix . В 1999 году он был выбран в качестве стандартного двоичного формата файлов для Unix и Unix-подобных систем на процессорах x86 проектом 86open.
По своей конструкции формат ELF является гибким, расширяемым и кроссплатформенным . Например, он поддерживает различные порядки байтов и размеры адресов, поэтому не исключает какую-либо конкретную архитектуру ЦП или набора инструкций . Это позволило принять его во многих различных операционных системах на многих различных аппаратных платформах .
Каждый файл ELF состоит из одного заголовка ELF, за которым следуют данные файла. Данные могут включать:
Сегменты содержат информацию, необходимую для выполнения файла во время выполнения , в то время как разделы содержат важные данные для связывания и перемещения. Любой байт во всем файле может принадлежать максимум одному разделу, и могут встречаться байты-сироты, которые не принадлежат ни одному разделу.
Заголовок ELF определяет, использовать ли 32-битные или 64-битные адреса. Заголовок содержит три поля, на которые влияет эта настройка, и смещает другие поля, которые следуют за ними. Заголовок ELF имеет длину 52 или 64 байта для 32-битных и 64-битных двоичных файлов соответственно.
Компенсировать | Размер (байты) | Поле | Цель | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
32-битный | 64-битный | 32-битный | 64-битный | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x00 | 4 | e_ident[EI_MAG0] через e_ident[EI_MAG3] | 0x7F за которыми следует ELF ( 45 4c 46 ) в ASCII ; эти четыре байта составляют магическое число . | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x04 | 1 | e_ident[EI_CLASS] | Этот байт устанавливается в значение 1 или 2 для обозначения 32- или 64-битного формата соответственно. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x05 | 1 | e_ident[EI_DATA] | Этот байт устанавливается либо в значение, 1 либо 2 в значение, указывающее на прямой или обратный порядок байтов , соответственно. Это влияет на интерпретацию многобайтовых полей, начинающихся со смещения 0x10 . | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x06 | 1 | e_ident[EI_VERSION] | Установите 1 для исходной и текущей версии ELF. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x07 | 1 | e_ident[EI_OSABI] | Определяет ABI целевой операционной системы .
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x08 | 1 | e_ident[EI_ABIVERSION] | Далее указывается версия ABI. Ее интерпретация зависит от целевого ABI. Ядро Linux (после версии 2.6) не имеет ее определения, [5] поэтому она игнорируется для статически скомпонованных исполняемых файлов. В этом случае смещение и размер EI_PAD равны 8 .glibc 2.12+ в случае e_ident[EI_OSABI] == 3 обрабатывает это поле как версию ABI динамического компоновщика : [6] он определяет список функций динамического компоновщика, [7] обрабатывает e_ident[EI_ABIVERSION] как уровень функции, запрошенный общим объектом (исполняемым файлом или динамической библиотекой), и отказывается загружать его, если запрошена неизвестная функция, т. е. e_ident[EI_ABIVERSION] больше наибольшей известной функции. [8] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x09 | 7 | e_ident[EI_PAD] | Зарезервированные байты заполнения. В настоящее время не используются. Следует заполнить нулями и игнорировать при чтении. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x10 | 2 | e_type | Определяет тип объектного файла.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x12 | 2 | электронная_машина | Указывает архитектуру набора целевых инструкций . Вот некоторые примеры:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x14 | 4 | электронная_версия | Установите 1 для оригинальной версии ELF. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x18 | 4 | 8 | e_entry | Это адрес памяти точки входа , с которой процесс начинает выполнение. Это поле имеет длину 32 или 64 бита в зависимости от формата, определенного ранее (байт 0x04). Если файл не имеет связанной точки входа, то это поле содержит ноль. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x1С | 0x20 | 4 | 8 | e_phoff | Указывает на начало таблицы заголовков программы. Обычно он следует за заголовком файла, следующим сразу за этим, создавая смещение 0x34 или 0x40 для 32- и 64-битных исполняемых файлов ELF соответственно. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x20 | 0x28 | 4 | 8 | e_shoff | Указывает на начало таблицы заголовков раздела. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x24 | 0x30 | 4 | e_flags | Интерпретация этого поля зависит от целевой архитектуры. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x28 | 0x34 | 2 | e_ehsize | Содержит размер этого заголовка, обычно 64 байта для 64-битного и 52 байта для 32-битного формата. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x2A | 0x36 | 2 | e_phentsize | Содержит размер записи таблицы заголовков программ. Как поясняется ниже, это обычно 0x20 (32 бита) или 0x38 (64 бита). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x2С | 0x38 | 2 | e_phnum | Содержит количество записей в таблице заголовков программы. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x2E | 0x3A | 2 | e_shentsize | Содержит размер записи таблицы заголовков разделов. Как поясняется ниже, это обычно 0x28 (32 бита) или 0x40 (64 бита). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x30 | 0x3C | 2 | e_shnum | Содержит количество записей в таблице заголовков разделов. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x32 | 0x3E | 2 | e_shstrndx | Содержит индекс записи таблицы заголовков разделов, содержащей названия разделов. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x34 | 0x40 | Конец заголовка ELF (размер). |
Таблица заголовков программы сообщает системе, как создать образ процесса. Она находится по смещению файла e_phoff и состоит из записей e_phnum , каждая размером e_phentsize . Макет немного отличается в 32-битном ELF по сравнению с 64-битным ELF, поскольку p_flags находятся в другом месте структуры для выравнивания. Каждая запись структурирована следующим образом:
Компенсировать | Размер (байты) | Поле | Цель | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
32-битный | 64-битный | 32-битный | 64-битный | |||||||||||||||||||||||||||||||||||||||
0x00 | 4 | p_тип | Определяет тип сегмента.
| |||||||||||||||||||||||||||||||||||||||
0x04 | 4 | p_flags | Флаги, зависящие от сегмента (позиция для 64-битной структуры).
| |||||||||||||||||||||||||||||||||||||||
0x04 | 0x08 | 4 | 8 | p_offset | Смещение сегмента в файле изображения. | |||||||||||||||||||||||||||||||||||||
0x08 | 0x10 | 4 | 8 | p_vaddr | Виртуальный адрес сегмента в памяти. | |||||||||||||||||||||||||||||||||||||
0x0C | 0x18 | 4 | 8 | p_paddr | В системах, где физический адрес имеет значение, зарезервировано для физического адреса сегмента. | |||||||||||||||||||||||||||||||||||||
0x10 | 0x20 | 4 | 8 | p_filesz | Размер сегмента в файле изображения в байтах. Может быть 0. | |||||||||||||||||||||||||||||||||||||
0x14 | 0x28 | 4 | 8 | p_memsz | Размер сегмента в памяти в байтах. Может быть 0. | |||||||||||||||||||||||||||||||||||||
0x18 | 4 | p_flags | Флаги, зависящие от сегмента (позиция для 32-битной структуры). См. вышеприведенное p_flags поле для определений флагов. | |||||||||||||||||||||||||||||||||||||||
0x1С | 0x30 | 4 | 8 | p_align | 0 и 1 не указывать выравнивание. В противном случае должно быть положительной целой степенью числа 2, с p_vaddr, равным p_offset модулю p_align . | |||||||||||||||||||||||||||||||||||||
0x20 | 0x38 | Конец заголовка программы (размер). |
Компенсировать | Размер (байты) | Поле | Цель | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
32-битный | 64-битный | 32-битный | 64-битный | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x00 | 4 | sh_name | Смещение строки в разделе .shstrtab , представляющее имя этого раздела. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x04 | 4 | sh_type | Определяет тип этого заголовка.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x08 | 4 | 8 | sh_flags | Определяет атрибуты раздела.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x0C | 0x10 | 4 | 8 | sh_addr | Виртуальный адрес раздела в памяти, для загруженных разделов. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x10 | 0x18 | 4 | 8 | sh_offset | Смещение раздела в файле изображения. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x14 | 0x20 | 4 | 8 | sh_size | Размер раздела в байтах. Может быть 0. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x18 | 0x28 | 4 | sh_link | Содержит индекс раздела связанного раздела. Это поле используется для нескольких целей, в зависимости от типа раздела. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x1С | 0x2С | 4 | sh_info | Содержит дополнительную информацию о разделе. Это поле используется для нескольких целей, в зависимости от типа раздела. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x20 | 0x30 | 4 | 8 | sh_addralign | Содержит требуемое выравнивание раздела. Это поле должно быть степенью двойки. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x24 | 0x38 | 4 | 8 | sh_entsize | Содержит размер в байтах каждой записи для разделов, содержащих записи фиксированного размера. В противном случае это поле содержит ноль. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0x28 | 0x40 | Конец заголовка раздела (размер). |
readelf
— это двоичная утилита Unix, которая отображает информацию об одном или нескольких файлах ELF. Свободная программная реализация предоставляется GNU Binutils .elfutils
предоставляет альтернативные инструменты GNU Binutils исключительно для Linux. [10]elfdump
— команда для просмотра ELF-информации в ELF-файле, доступная в Solaris и FreeBSD .objdump
предоставляет широкий спектр информации о файлах ELF и других форматах объектов. objdump
использует библиотеку Binary File Descriptor в качестве внутреннего инструмента для структурирования данных ELF.file
может отображать некоторую информацию о файлах ELF, включая архитектуру набора инструкций , для которой предназначен код в перемещаемом, исполняемом или общем объектном файле или на основе которого был создан дамп ядра ELF.Формат ELF заменил старые исполняемые форматы в различных средах. Он заменил форматы a.out и COFF в Unix-подобных операционных системах:
ELF также нашел некоторое применение в операционных системах, отличных от Unix, таких как:
Microsoft Windows также использует формат ELF, но только для своей системы совместимости с подсистемой Windows для Linux . [16]
Некоторые игровые консоли также используют ELF:
Другие (операционные) системы, работающие на PowerPC , которые используют ELF:
Некоторые операционные системы для мобильных телефонов и мобильных устройств используют ELF:
Некоторые телефоны могут запускать файлы ELF с помощью патча , который добавляет код сборки к основной прошивке , что является функцией, известной как ELFPack в культуре андеграундного моддинга . Формат файла ELF также используется с архитектурами микроконтроллеров Atmel AVR (8-бит), AVR32 [21] и Texas Instruments MSP430 . Некоторые реализации Open Firmware также могут загружать файлы ELF, в частности, реализация Apple , используемая почти во всех машинах PowerPC , производимых компанией.
Linux Standard Base (LSB) дополняет некоторые из вышеперечисленных спецификаций для архитектур, в которых она указана. [22] Например, это касается System V ABI, AMD64 Supplement. [23] [24]
86open был проектом по формированию консенсуса по общему двоичному формату файлов для Unix и Unix-подобных операционных систем на общей PC-совместимой архитектуре x86 , чтобы побудить разработчиков программного обеспечения портировать на эту архитектуру. [25] Первоначальная идея состояла в том, чтобы стандартизировать небольшое подмножество Spec 1170, предшественника Single UNIX Specification , и GNU C Library (glibc), чтобы позволить немодифицированным двоичным файлам работать на x86 Unix-подобных операционных системах. Первоначально проект назывался «Spec 150».
В конечном итоге был выбран формат ELF, а точнее реализация ELF для Linux, после того как он стал фактическим стандартом, поддерживаемым всеми вовлеченными поставщиками и операционными системами.
Группа начала проводить обсуждения по электронной почте в 1997 году и впервые встретилась в офисе Santa Cruz Operation 22 августа 1997 года.
Руководящий комитет состоял из Марка Юинга , Диона Джонсона, Эвана Лейбовича, Брюса Перенса , Эндрю Роуча, Брайана Уэйна Спаркса и Линуса Торвальдса . Другими людьми, принимавшими участие в проекте, были Кейт Бостик , Чак Крейнор, Майкл Дэвидсон, Крис Г. Деметриу, Ульрих Дреппер, Дон Даггер, Стив Гинзбург, Джон «maddog» Холл , Рон Холт, Джордан Хаббард , Дэйв Дженсен, Кин Джонстон, Эндрю Джози, Роберт Липе, Бела Лабкин, Тим Марсланд, Грег Пейдж, Рональд Джо Рекорд, Тим Ракл, Джоэл Сильверстайн, Чиа-пи Тиен и Эрик Троан. Были представлены следующие операционные системы и компании: BeOS , BSDI , FreeBSD , Intel , Linux , NetBSD , SCO и SunSoft .
Проект развивался, и в середине 1998 года SCO начала разрабатывать lxrun — слой совместимости с открытым исходным кодом, способный запускать двоичные файлы Linux на OpenServer , UnixWare и Solaris . SCO объявила об официальной поддержке lxrun на LinuxWorld в марте 1999 года. Sun Microsystems начала официально поддерживать lxrun для Solaris в начале 1999 года [26] , а затем перешла к интегрированной поддержке двоичного формата Linux через Solaris Containers for Linux Applications .
Поскольку BSD уже давно поддерживают двоичные файлы Linux (через уровень совместимости ), а основные поставщики x86 Unix добавили поддержку формата, проект решил, что Linux ELF — это формат, выбранный отраслью, и «объявил о своем роспуске» 25 июля 1999 года. [27]
FatELF — это расширение двоичного формата ELF, которое добавляет возможности двоичного формата fat . [28] Он предназначен для Linux и других Unix-подобных операционных систем. Помимо абстракции архитектуры ЦП ( порядок байтов , размер слова , набор инструкций ЦП и т. д.), существует потенциальное преимущество абстракции программной платформы, например, двоичные файлы, которые поддерживают несколько версий ABI ядра . По состоянию на 2021 год FatELF не был интегрирован в основное ядро Linux. [29] [30] [31][обновлять]
{{cite web}}
: CS1 maint: архивная копия как заголовок ( ссылка )Динамически подключаемые библиотеки также называются разделяемыми объектами (.so).