ELF

Разбиране на ELF файловия формат

Разбиране на ELF файловия формат

От изходен код към двоичен код

Програмирането започва с умна идея и писане на изходен код на избран от вас програмен език, например C, и запазване на изходния код във файл. С помощта на адекватен компилатор, например GCC, първоначално вашият изходен код се превежда в обектен код. В крайна сметка линкерът превежда обектния код в двоичен файл, който свързва обектния код с референтните библиотеки. Този файл съдържа единичните инструкции като машинен код, които се разбират от процесора и се изпълняват веднага след стартирането на компилираната програма.

Бинарният файл, споменат по-горе, следва специфична структура и един от най-често срещаните се нарича ELF, който съкращава изпълним и свързан формат. Той се използва широко за изпълними файлове, преместваеми обектни файлове, споделени библиотеки и сметища на ядрото.

Преди двадесет години - през 1999 г., проектът 86open избра ELF като стандартен двоичен файлов формат за Unix и Unix-подобни системи на x86 процесори. За щастие, форматът ELF вече е бил документиран както в двоичния интерфейс на приложението System V, така и в стандарта за интерфейса на инструмента [4]. Този факт значително опрости споразумението за стандартизация между различните доставчици и разработчици на Unix-базирани операционни системи.

Причината за това решение беше дизайнът на ELF - гъвкавост, разширяемост и поддръжка на различни платформи за различни ендиански формати и адреси. Дизайнът на ELF не се ограничава до конкретен процесор, набор от инструкции или хардуерна архитектура. За подробно сравнение на изпълними файлови формати, погледнете тук [3].

Оттогава форматът ELF се използва от няколко различни операционни системи. Наред с други, това включва Linux, Solaris / Illumos, Free-, Net- и OpenBSD, QNX, BeOS / Haiku и Fuchsia OS [2]. Освен това ще го намерите на мобилни устройства с Android, Maemo или Meego OS / Sailfish OS, както и на игрови конзоли като PlayStation Portable, Dreamcast и Wii.

Спецификацията не изяснява разширението на името на файла за ELF файлове. Използва се множество комбинации от букви, като .axf, .кошче, .елф, .o, .prx, .пуф, .ко, .така, и .мод, или нито един.

Структурата на ELF файл

На терминал на Linux командният човек elf ви дава удобно резюме за структурата на ELF файл:

Листинг 1: Страницата на структурата на ELF

$ man elf
ELF (5) Ръководство на програмиста за Linux ELF (5)
ИМЕ
elf - формат на изпълними и свързващи формати (ELF) файлове
СИНОПСИС
#include
ОПИСАНИЕ
Заглавният файл определя формата на изпълнимия двоичен файл ELF
файлове. Сред тези файлове са нормални изпълними файлове, преместваеми
обектни файлове, основни файлове и споделени библиотеки.
Изпълним файл, използващ файловия формат ELF, се състои от заглавка ELF,
последвано от таблица със заглавия на програма или таблица със заглавия на раздели или и двете.
Заглавката ELF винаги е с нулево отместване на файла. Програмата
заглавната таблица и изместването на заглавната таблица на раздела във файла са
дефинирани в заглавката ELF. Двете таблици описват останалата част от
особености на файла.
..

Както можете да видите от описанието по-горе, ELF файлът се състои от два раздела - заглавка на ELF и данни от файла. Разделът с файлови данни може да се състои от таблица със заглавия на програма, описваща нула или повече сегменти, таблица със заглавия на секция, описваща нула или повече секции, която е последвана от данни, посочени от записи от таблицата със заглавия на програмата, и таблица със заглавия на раздела. Всеки сегмент съдържа информация, необходима за изпълнение на файла по време на изпълнение, докато секциите съдържат важни данни за свързване и преместване. Фигура 1 илюстрира това схематично.

Заглавката на ELF

Заглавката ELF е с дължина 32 байта и идентифицира формата на файла. Започва с последователност от четири уникални байта, които са 0x7F, последвани от 0x45, 0x4c и 0x46, което се превежда в трите букви E, L и F. Наред с други стойности, заглавката също така показва дали е ELF файл за 32 или 64-битов формат, използва малко или голямо крайност, показва версията ELF, както и за коя операционна система е компилиран файлът, за да си взаимодейства с десен двоичен интерфейс на приложение (ABI) и набор от инструкции на процесора.

Шестнадесетичният бутон на докосването на двоичен файл изглежда както следва:

.Листинг 2: Hexdump на двоичния файл

$ hd / usr / bin / touch | глава -5
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF… |
00000010 02 00 3e 00 01 00 00 00 e3 25 40 00 00 00 00 00 | ...> ...% @ ... |
00000020 40 00 00 00 00 00 00 00 28 e4 00 00 00 00 00 00 | @… (… |
00000030 00 00 00 00 40 00 38 00 09 00 40 00 1b 00 1a 00 | [имейл защитен] @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 | [имейл защитен] |

Debian GNU / Linux предлага командата readelf, която се предоставя в пакета на GNU 'binutils'. Придружен от превключвателя -h (кратка версия за “-file-header”) той добре показва заглавката на ELF файл. Листинг 3 илюстрира това за командното докосване.

.Листинг 3: Показване на заглавката на ELF файл

$ readelf -h / usr / bin / touch
Заглавка на ELF:
Магия: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Клас: ELF64
Данни: допълнение 2, малко ендиан
Версия: 1 (текуща)
OS / ABI: UNIX - система V
Версия на ABI: 0
Тип: EXEC (изпълним файл)
Машина: Advanced Micro Devices X86-64
Версия: 0x1
Адрес на входната точка: 0x4025e3
Начало на заглавките на програмата: 64 (байта във файл)
Начало на заглавките на раздели: 58408 (байта във файл)
Флагове: 0x0
Размер на тази заглавка: 64 (байта)
Размер на заглавията на програмата: 56 (байта)
Брой заглавки на програмата: 9
Размер на заглавията на раздели: 64 (байта)
Брой заглавки на секции: 27
Индекс на таблицата със заглавки на секции: 26

Заглавката на програмата

Заглавката на програмата показва сегментите, използвани по време на изпълнение, и казва на системата как да създаде изображение на процес. Заглавката от Листинг 2 показва, че ELF файлът се състои от 9 програмни заглавки, които имат размер 56 байта всеки, а първият заглавие започва от байт 64.

Отново, командата readelf помага да се извлече информацията от ELF файла. Превключвателят -l (съкращение от -program-headers или -segments) разкрива повече подробности, както е показано в листинг 4.

.Листинг 4: Показване на информация за заглавките на програмата

$ readelf -l / usr / bin / touch
Типът на Elf е EXEC (изпълним файл)
Входна точка 0x4025e3
Има 9 заглавки на програмата, започвайки с отместване 64
Заглавия на програмата:
Въведете Offset VirtAddr PhysAddr
FileSiz MemSiz Знамена Подравнете
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Заявка за програмен интерпретатор: / lib64 / ld-linux-x86-64.така.2]
ТОВАР 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
ТОВАР 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DYNAMIC 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
ЗАБЕЛЕЖКА 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x000000000000bc40 0x000000000040bc40 0x000000000040bc40
0x00000000000003a4 0x00000000000003a4 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x00000000000001f0 0x00000000000001f0 R 1
Съставяне на сегменти към сегменти:
Сегментиране на раздели ..
00
01 .интерп
02 .интерп .Забележка.ABI-таг .Забележка.gnu.build-id .gnu.хеш .динсим .dynstr .gnu.версия .gnu.version_r .относително.дин .относително.plt .в него .plt .текст .фини .родата .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .динамичен .има .има.plt .данни .bss
04 .динамичен
05 .Забележка.ABI-таг .Забележка.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .динамичен .има

Заглавката на раздела

Третата част от структурата на ELF е заглавката на раздела. Предназначен е да изброи отделните раздели на двоичния файл. Ключът -S (съкратено от -section-headers или -sections) изброява различните хедъри. Що се отнася до командата за докосване, има 27 заглавки на раздели и в Листинг 5 са ​​показани само първите четири от тях плюс последния. Всеки ред обхваща размера на секцията, типа на секцията, както и нейния адрес и отместване на паметта.

.Листинг 5: Подробности за раздела, разкрити от readelf

$ readelf -S / usr / bin / touch
Има 27 заглавки на секции, започвайки с отместване 0xe428:
Заглавия на раздели:
[Nr] Име Тип Адрес Отместване
Размер EntSize Знамена Информация за връзката Подравняване
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .Забележка.ABI-таг ЗАБЕЛЕЖКА 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .Забележка.gnu.build-i ЗАБЕЛЕЖКА 0000000000400274 00000274
..
..
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Ключ към флаговете:
W (запис), A (разпределение), X (изпълнение), M (сливане), S (низове), l (голямо)
I (информация), L (ред на връзката), G (група), T (TLS), E (изключва), x (неизвестно)
O (изисква се допълнителна обработка на ОС) o (специфично за ОС), p (специфично за процесора)

Инструменти за анализ на ELF файл

Както може би сте забелязали от примерите по-горе, GNU / Linux се предлага с редица полезни инструменти, които ви помагат да анализирате ELF файл. Първият кандидат, който ще разгледаме, е помощната програма за файлове.

файлът показва основна информация за ELF файлове, включително архитектурата на набор от инструкции, за която е предназначен кодът в преместваем, изпълним или споделен обектен файл. В списък 6 той ви казва, че / bin / touch е 64-битов изпълним файл, следващ Linux Standard Base (LSB), динамично свързан и създаден за ядрото GNU / Linux версия 2.6.32.

.Листинг 6: Основна информация с помощта на файл

$ файл / кош / докосване
/ bin / touch: ELF 64-битов LSB изпълним файл, x86-64, версия 1 (SYSV), динамично свързан, интерпретатор / lib64 / l,
за GNU / Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, лишен
$

Вторият кандидат е прочетен. Той показва подробна информация за ELF файл. Списъкът с ключове е сравнително дълъг и обхваща всички аспекти на формата ELF. Използване на превключвателя -n (съкратено от -notes) Листинг 7 показва само разделите на бележките, които съществуват в докосването на файла - етикетът на версията ABI и битстрингът на идентификатора на компилация.

.Листинг 7: Показване на избрани секции от ELF файл

$ readelf -n / usr / bin / touch
Показване на бележки, намерени при отместване на файла 0x00000254 с дължина 0x00000020:
Размер на данните на собственика Описание
GNU 0x00000010 NT_GNU_ABI_TAG (маркер на версията на ABI)
ОС: Linux, ABI: 2.6.32
Показване на бележки, намерени при отместване на файла 0x00000274 с дължина 0x00000024:
Размер на данните на собственика Описание
GNU 0x00000014 NT_GNU_BUILD_ID (уникален битстринг с идентификатор на компилация)
Идентификатор на компилация: ec08d609e9e8e73d4be6134541a472ad0ea34502

Имайте предвид, че при Solaris и FreeBSD помощната програма elfdump [7] съответства на readelf. Към 2019 г. няма нова версия или актуализация от 2003 г. насам.

Номер три е пакетът с име elfutils [6], който е изцяло достъпен за Linux. Той предоставя алтернативни инструменти на GNU Binutils и също така позволява проверка на ELF файлове. Обърнете внимание, че всички имена на помощните програми, предоставени в пакета, започват с eu за „elf utils“.

Не на последно място ще споменем objdump. Този инструмент е подобен на readelf, но се фокусира върху обектни файлове. Той предоставя подобен набор от информация за ELF файлове и други обектни формати.

.Листинг 8: Файлова информация, извлечена от objdump

$ objdump -f / bin / touch
/ bin / touch: файлов формат elf64-x86-64
архитектура: i386: x86-64, флагове 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
начален адрес 0x00000000004025e3
$

Съществува и софтуерен пакет, наречен „elfkickers“ [9], който съдържа инструменти за четене на съдържанието на ELF файл, както и за манипулиране с него. За съжаление, броят на изданията е доста нисък и затова просто го споменаваме и не показваме допълнителни примери.

Вместо това като разработчик може да разгледате „pax-utils“ [10,11]. Този набор от помощни програми предоставя редица инструменти, които помагат за валидиране на ELF файлове. Като пример, dumpelf анализира ELF файла и връща C заглавен файл, съдържащ подробностите - вижте Фигура 2.

Заключение

Благодарение на комбинацията от интелигентен дизайн и отлична документация, форматът ELF работи много добре и все още се използва след 20 години. Помощните програми, показани по-горе, ви позволяват да получите поглед върху ELF файл и ви позволяват да разберете какво прави една програма. Това са първите стъпки за анализ на софтуера - щастливо хакване!

Връзки и справки
  • [1] Изпълним и свързващ се формат (ELF), Уикипедия
  • [2] Fuchsia OS
  • [3] Сравнение на изпълними файлови формати, Уикипедия
  • [4] Linux Foundation, посочени спецификации
  • [5] Ciro Santilli: Урок за ELF Hello World
  • [6] elfutils пакет Debian
  • [7] elfdump
  • [8] Майкъл Болен: 101-те от ELF файловете в Linux: Разбиране и анализ
  • [9] elfkickers
  • [10] Закалени / PaX помощни програми
  • [11] pax-utils, пакет Debian
Благодарности

Писателят би искал да благодари на Аксел Бекерт за подкрепата му по отношение на подготовката на тази статия.

OpenTTD срещу Simutrans
Създаването на собствена транспортна симулация може да бъде забавно, релаксиращо и изключително примамливо. Ето защо трябва да сте сигурни, че изпробв...
Урок за OpenTTD
OpenTTD е една от най-популярните бизнес симулационни игри там. В тази игра трябва да създадете прекрасен транспортен бизнес. Въпреки това, ще започне...
SuperTuxKart за Linux
SuperTuxKart е страхотно заглавие, създадено да ви предостави безплатно изживяването на Mario Kart във вашата Linux система. Играта е доста предизвика...