Format wykonywalny i możliwy do połączenia

Format wykonywalny i możliwy do połączenia
Rozszerzenie nazwy pliku
brak, .axf , .bin , .elf , .o , .out , .prx , .puff , .ko , .mod i .so
magiczny numer 0x7F 'E' 'L' 'F'
Opracowany przez Laboratoria systemów Unix
Typ formatu Binarny , wykonywalny , obiektowy , współdzielona biblioteka , zrzut pamięci
Pojemnik na Wiele wykonywalnych formatów binarnych
Plik ELF ma dwa widoki: nagłówek programu pokazuje segmenty używane w czasie wykonywania, podczas gdy nagłówek sekcji zawiera zestaw sekcji .

W informatyce Executable and Linkable Format ( ELF , wcześniej nazywany Extensible Linking Format ) jest powszechnym standardowym formatem plików wykonywalnych , kodu wynikowego , bibliotek współdzielonych i zrzutów pamięci . Po raz pierwszy opublikowany w specyfikacji interfejsu binarnego aplikacji (ABI) systemu operacyjnego Unix w wersji o nazwie System V Release 4 (SVR4), a później w Tool Interface Standard, szybko został zaakceptowany przez różnych dostawców systemów uniksowych . W 1999 roku został wybrany jako standardowy format plików binarnych dla systemów uniksowych i uniksopodobnych na procesorach x86 przez projekt 86open .

Z założenia format ELF jest elastyczny, rozszerzalny i wieloplatformowy . Na przykład obsługuje różne endiany i rozmiary adresów, więc nie wyklucza żadnej konkretnej jednostki centralnej (CPU) ani architektury zestawu instrukcji . Umożliwiło to przyjęcie go przez wiele różnych systemów operacyjnych na wielu różnych platformach sprzętowych .

Układ plików

Każdy plik ELF składa się z jednego nagłówka ELF, po którym następują dane pliku. Dane mogą obejmować:

  • Tablica nagłówków programu, opisująca zero lub więcej segmentów pamięci
  • Tabela nagłówków sekcji, opisująca zero lub więcej sekcji
  • Dane, do których odnoszą się wpisy w tablicy nagłówków programu lub tablicy nagłówków sekcji
Struktura pliku ELF z podświetlonymi kluczowymi wpisami

Segmenty zawierają informacje potrzebne do wykonania pliku w czasie wykonywania , podczas gdy sekcje zawierają ważne dane do łączenia i relokacji. Dowolny bajt w całym pliku może należeć maksymalnie do jednej sekcji, a mogą wystąpić bajty osierocone, które nie należą do żadnej sekcji.

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 c5 48 40 00 00 00 00 00 | ..>......H@..... |

Przykładowy zrzut heksowy nagłówka pliku ELF

Nagłówek pliku

Nagłówek ELF określa, czy używać adresów 32-bitowych , czy 64-bitowych . Nagłówek zawiera trzy pola, na które ma wpływ to ustawienie, oraz inne pola, które za nimi następują. Nagłówek ELF ma długość 52 lub 64 bajty odpowiednio dla 32-bitowych i 64-bitowych plików binarnych.

Nagłówek ELF
Zrównoważyć Rozmiar (bajty) Pole Zamiar
32-bitowy 64-bitowy 32-bitowy 64-bitowy
0x00 4 e_ident[EI_MAG0] do e_ident[EI_MAG3] 0x7F , po którym następuje ELF ( 45 4c 46 ) w ASCII ; te cztery bajty stanowią magiczną liczbę .
0x04 1 e_identyfikator[EI_CLASS] Ten bajt jest ustawiony na 1 lub 2 , aby oznaczyć odpowiednio format 32- lub 64-bitowy.
0x05 1 e_identyfikator[EI_DATA] Ten bajt jest ustawiony na 1 lub 2 , aby odpowiednio oznaczać małą lub dużą endianność . Wpływa to na interpretację pól wielobajtowych zaczynających się od offsetu 0x10 .
0x06 1 e_identyfikator[EI_VERSION] Ustaw na 1 dla oryginalnej i aktualnej wersji ELF.
0x07 1 e_identyfikator[EI_OSABI] Identyfikuje docelowy system operacyjny ABI .
Wartość ABI
0x00 System V
0x01 HP-UX
0x02 NetBSD
0x03 Linuks
0x04 GNU Hurda
0x06 Solaris
0x07 AIX (Monterey)
0x08 IRIX
0x09 FreeBSD
0x0A Tru64
0x0B Novell Modesto
0x0C OpenBSD
0x0D OpenVMS
0x0E Jądro NonStop
0x0F AROS
0x10 FenixOS
0x11 Nuxi CloudABI
0x12 Stratus Technologies OpenVOS
0x08 1 e_identyfikator[EI_ABIVERSION] Dalej określa wersję ABI. Jego interpretacja zależy od docelowego ABI. Jądro Linuksa (po co najmniej 2.6) nie ma jego definicji, więc jest ignorowane w przypadku plików wykonywalnych połączonych statycznie. W takim przypadku przesunięcie i rozmiar EI_PAD wynoszą 8 .

glibc 2.12+ w przypadku, gdy e_ident[EI_OSABI] == 3 traktuje to pole jako wersję ABI dynamicznego linkera : definiuje listę funkcji dynamicznego linkera, traktuje e_ident[EI_ABIVERSION] jako poziom funkcji wymagany przez współdzielony obiekt (wykonywalny lub dynamiczny biblioteka) i odmawia załadowania, jeśli wymagana jest nieznana cecha, np. e_ident[EI_ABIVERSION] jest większa niż największa znana cecha.

0x09 7 e_identyfikator[EI_PAD] Zarezerwowane bajty dopełnienia. Obecnie nieużywany. Powinien być wypełniony zerami i ignorowany podczas odczytu.
0x10 2 e_typ Identyfikuje typ pliku obiektowego.
Wartość Typ Oznaczający
0x00 ET_NONE Nieznany.
0x01 ET_REL Przenośny plik.
0x02 ET_EXEC Plik wykonywalny.
0x03 ET_DYN Obiekt udostępniony.
0x04 ET_CORE Plik podstawowy.
0xFE00 ET_LOOS Zarezerwowany zakres włącznie. Specyficzny dla systemu operacyjnego.
0xFEFF ET_HIOS
0xFF00 ET_LOPROC Zarezerwowany zakres włącznie. Specyficzny dla procesora.
0xFFFF ET_HIPROC
0x12 2 e_maszyna Określa docelową architekturę zestawu instrukcji . Niektóre przykłady to:
Wartość JEST
0x00 Brak określonego zestawu instrukcji
0x01 AT&T WE 32100
0x02 SPARC
0x03 x86
0x04 Motorola 68000 (M68k)
0x05 Motorola 88000 (M88k)
0x06 Mikrokontroler Intela
0x07 Intel 80860
0x08 MIPS
0x09 System IBM/370
0x0A MIPS RS3000 Little-endian
0x0B - 0x0D Zarezerwowane do wykorzystania w przyszłości
0x0E Hewlett-Packard PA-RISC
0x0F Zarezerwowane do wykorzystania w przyszłości
0x13 Intel 80960
0x14 PowerPC
0x15 PowerPC (64-bitowy)
0x16 S390 , w tym S390x
0x17 IBM SPU/SPC
0x18 - 0x23 Zarezerwowane do wykorzystania w przyszłości
0x24 NEC V800
0x25 Fujitsu FR20
0x26 TRW RH-32
0x27 Motorola RCE
0x28 Uzbrojenie (do Armv7/AArch32)
0x29 Cyfrowa alfa
0x2A SuperH
0x2B SPARC wersja 9
0x2C Wbudowany procesor Siemens TriCore
0x2D Rdzeń Argonauta RISC
0x2E Hitachi H8/300
0x2F Hitachi H8/300H
0x30 Hitachi H8S
0x31 Hitachi H8/500
0x32 IA-64
0x33 Stanford MIPS-X
0x34 Motorola ColdFire
0x35 Motorolę M68HC12
0x36 Akcelerator multimedialny Fujitsu MMA
0x37 PCP Siemensa
0x38 Wbudowany procesor Sony nCPU RISC
0x39 Mikroprocesor Denso NDR1
0x3A Procesor Motorola Star*Core
0x3B Procesor Toyoty ME16
0x3C Procesor STMicroelectronics ST100
0x3D Rodzina wbudowanych procesorów TinyJ firmy Advanced Logic Corp
0x3E AMD x86-64
0x3F Procesor Sony DSP
0x40 Firma Digital Equipment Corp. PDP-10
0x41 Firma Digital Equipment Corp. PDP-11
0x42 Mikrokontroler Siemens FX66
0x43 STMicroelectronics ST9+ 8/16-bitowy mikrokontroler
0x44 STMicroelectronics ST7 8-bitowy mikrokontroler
0x45 Mikrokontroler Motorola MC68HC16
0x46 Mikrokontroler Motorola MC68HC11
0x47 Mikrokontroler Motorola MC68HC08
0x48 Mikrokontroler Motorola MC68HC05
0x49 Silikonowa grafika SVx
0x4A 8-bitowy mikrokontroler STMicroelectronics ST19
0x4B Cyfrowy VAX
0x4C 32-bitowy wbudowany procesor Axis Communications
0x4D 32-bitowy wbudowany procesor Infineon Technologies
0x4E 64-bitowy procesor DSP Element 14
0x4F 16-bitowy procesor DSP LSI Logic
0x8C Rodzina TMS320C6000
0xAF MCST Elbrus e2k
0xB7 Uzbrojenie 64-bitowe (Armv8/AArch64)
0xDC Zilog Z80
0xF3 RISC-V
0xF7 Filtr pakietów Berkeley
0x101 WDC65C816
0x14 4 e_wersja Ustaw na 1 dla oryginalnej wersji ELF.
0x18 4 8 e_wpis Jest to adres pamięci punktu wejścia, od którego rozpoczyna się wykonywanie procesu. To pole ma długość 32 lub 64 bitów, w zależności od wcześniej zdefiniowanego formatu (bajt 0x04). Jeśli plik nie ma powiązanego punktu wejścia, oznacza to zero.
0x1C 0x20 4 8 e_phoff Wskazuje początek tabeli nagłówków programu. Zwykle następuje po nagłówku pliku bezpośrednio po tym, tworząc przesunięcie 0x34 lub 0x40 odpowiednio dla 32- i 64-bitowych plików wykonywalnych ELF.
0x20 0x28 4 8 e_shoff Wskazuje początek tabeli nagłówków sekcji.
0x24 0x30 4 e_flagi Interpretacja tego pola zależy od architektury docelowej.
0x28 0x34 2 e_ehrozmiar Zawiera rozmiar tego nagłówka, zwykle 64 bajty dla formatu 64-bitowego i 52 bajty dla formatu 32-bitowego.
0x2A 0x36 2 e_fentsize Zawiera rozmiar pozycji tabeli nagłówka programu.
0x2C 0x38 2 e_phnum Zawiera liczbę wpisów w tablicy nagłówka programu.
0x2E 0x3A 2 e_szentrozmiar Zawiera rozmiar pozycji tabeli nagłówków sekcji.
0x30 0x3C 2 e_sznum Zawiera liczbę wpisów w tabeli nagłówków sekcji.
0x32 0x3E 2 e_shstrndx Zawiera indeks wpisu tabeli nagłówków sekcji, który zawiera nazwy sekcji.
0x34 0x40 Koniec nagłówka ELF (rozmiar).

Nagłówek programu

Tablica nagłówka programu informuje system, jak utworzyć obraz procesu. Znajduje się w pliku offset e_phoff i składa się z wpisów e_phnum , z których każdy ma rozmiar e_phentsize . Układ jest nieco inny w 32-bitowym ELF i 64-bitowym ELF, ponieważ p_flags znajdują się w innej lokalizacji struktury ze względu na wyrównanie. Każdy wpis ma strukturę:

Nagłówek programu
Zrównoważyć Rozmiar (bajty) Pole Zamiar
32-bitowy 64-bitowy 32-bitowy 64-bitowy
0x00 4 p_typ Identyfikuje typ segmentu.
Wartość Nazwa Oznaczający
0x00000000 PT_NULL Wpis tabeli nagłówka programu nieużywany.
0x00000001 PT_LOAD Ładowalny segment.
0x00000002 PT_DYNAMICZNA Informacje o łączeniu dynamicznym.
0x00000003 PT_INTERP Informacje o tłumaczu.
0x00000004 PT_NOTE Informacje pomocnicze.
0x00000005 PT_SHLIB Skryty.
0x00000006 PT_PHDR Segment zawierający samą tablicę nagłówków programu.
0x00000007 PT_TLS Szablon magazynu lokalnego wątków.
0x60000000 PT_LOOS Zarezerwowany zakres włącznie. Specyficzny dla systemu operacyjnego.
0x6FFFFFFFF PT_HIOS
0x70000000 PT_LOPROC Zarezerwowany zakres włącznie. Specyficzny dla procesora.
0x7FFFFFFFF PT_HIPROC
0x04 4 p_flagi Flagi zależne od segmentu (pozycja dla struktury 64-bitowej).
0x04 0x08 4 8 p_przesunięcie Przesunięcie segmentu w obrazie pliku.
0x08 0x10 4 8 p_vaddr Adres wirtualny segmentu w pamięci.
0x0C 0x18 4 8 p_paddr W systemach, w których istotny jest adres fizyczny, zarezerwowane dla adresu fizycznego segmentu.
0x10 0x20 4 8 p_filesz Rozmiar w bajtach segmentu w obrazie pliku. Może być 0.
0x14 0x28 4 8 p_memsz Rozmiar w bajtach segmentu w pamięci. Może być 0.
0x18 4 p_flagi Flagi zależne od segmentu (pozycja dla struktury 32-bitowej).
0x1C 0x30 4 8 p_wyrównaj 0 i 1 nie określaj wyrównania. W przeciwnym razie powinna być dodatnią, całkowitą potęgą 2, przy czym p_vaddr równa się p_offset modulus p_align .
0x20 0x38 Koniec nagłówka programu (rozmiar).

Nagłówek sekcji

Zrównoważyć Rozmiar (bajty) Pole Zamiar
32-bitowy 64-bitowy 32-bitowy 64-bitowy
0x00 4 sh_name Przesunięcie do ciągu w sekcji .shstrtab , który reprezentuje nazwę tej sekcji.
0x04 4 sh_type Identyfikuje typ tego nagłówka.
Wartość Nazwa Oznaczający
0x0 SHT_NULL Wpis tabeli nagłówka sekcji nieużywany
0x1 SHT_PROGBITS Dane programu
0x2 SHT_SYMTAB Tabela symboli
0x3 SHT_STRTAB Stół strunowy
0x4 SHT_RELA Wpisy relokacyjne z dodatkami
0x5 SHT_HASH Tablica skrótów symboli
0x6 SHT_DYNAMICZNY Informacje o łączeniu dynamicznym
0x7 SHT_NOTE Notatki
0x8 SHT_NOBITS Przestrzeń programu bez danych (bss)
0x9 SHT_REL Wpisy dotyczące relokacji, bez dodatków
0x0A SHT_SHLIB Skryty
0x0B SHT_DYNSym Tablica symboli dynamicznego linkera
0x0E SHT_INIT_ARRAY Tablica konstruktorów
0x0F SHT_FINI_TABLICA Tablica destruktorów
0x10 SHT_PREINIT_ARRAY Tablica prekonstruktorów
0x11 SHT_GRUPA Grupa sekcji
0x12 SHT_SYMTAB_SHNDX Rozszerzone indeksy sekcji
0x13 SHT_NUM Liczba zdefiniowanych typów.
0x60000000 SHT_LOOS Uruchom w zależności od systemu operacyjnego.
... ... ...
0x08 4 8 sh_flags Identyfikuje atrybuty sekcji.
Wartość Nazwa Oznaczający
0x1 SHF_WRITE Możliwość zapisu
0x2 SHF_ALLOC Zajmuje pamięć podczas wykonywania
0x4 SHF_EXECINSTR wykonywalny
0x10 SHF_MERGE Może być połączone
0x20 SHF_STRINGS Zawiera ciągi zakończone znakiem null
0x40 SHF_INFO_LINK „sh_info” zawiera indeks SHT
0x80 SHF_LINK_ORDER Zachowaj porządek po połączeniu
0x100 SHF_OS_NONCONFORMING Wymagana niestandardowa obsługa specyficzna dla systemu operacyjnego
0x200 SHF_GRUPA Sekcja jest członkiem grupy
0x400 SHF_TLS Sekcja przechowuje dane lokalne wątku
0x0FF00000 SHF_MASKOS Specyficzne dla systemu operacyjnego
0xF0000000 SHF_MASKPROC Specyficzne dla procesora
0x4000000 SHF_ORDERED Specjalne wymagania dotyczące zamówienia (Solaris)
0x8000000 SHF_WYKLUCZ Sekcja jest wykluczona, chyba że istnieje odniesienie lub alokacja (Solaris)
0x0C 0x10 4 8 sh_addr Wirtualny adres sekcji w pamięci dla załadowanych sekcji.
0x10 0x18 4 8 sh_offset Przesunięcie sekcji w obrazie pliku.
0x14 0x20 4 8 sh_rozmiar Rozmiar w bajtach sekcji obrazu pliku. Może być 0.
0x18 0x28 4 sh_link Zawiera indeks sekcji powiązanej sekcji. To pole jest używane do kilku celów, w zależności od typu sekcji.
0x1C 0x2C 4 sh_info Zawiera dodatkowe informacje o sekcji. To pole jest używane do kilku celów, w zależności od typu sekcji.
0x20 0x30 4 8 sh_addralign Zawiera wymagane wyrównanie przekroju. To pole musi być potęgą dwójki.
0x24 0x38 4 8 sh_entsize Zawiera rozmiar (w bajtach) każdego wpisu dla sekcji zawierających wpisy o stałym rozmiarze. W przeciwnym razie to pole zawiera zero.
0x28 0x40 Koniec nagłówka sekcji (rozmiar).

Narzędzia

Aplikacje

Systemy typu Unix

Format ELF zastąpił starsze formaty plików wykonywalnych w różnych środowiskach. Zastąpił formaty a.out i COFF w systemach operacyjnych typu Unix :

Adopcja inna niż Unix

ELF został również przyjęty w systemach operacyjnych innych niż Unix, takich jak:

Microsoft Windows również używa formatu ELF, ale tylko dla swojego podsystemu Windows dla systemu zgodności z systemem Linux.

Konsole gier

Niektóre konsole do gier również używają ELF:

PowerPC

Inne (operacyjne) systemy działające na PowerPC , które używają ELF:

Telefony komórkowe

Niektóre systemy operacyjne dla telefonów komórkowych i urządzeń mobilnych używają ELF:

Niektóre telefony mogą uruchamiać pliki ELF za pomocą łatki , która dodaje kod asemblera do głównego oprogramowania układowego , co jest funkcją znaną jako ELFPack w podziemnej kulturze modowania . Format pliku ELF jest również używany z architekturami mikrokontrolerów Atmel AVR (8-bit), AVR32 i Texas Instruments MSP430 . Niektóre implementacje Open Firmware mogą również ładować pliki ELF, w szczególności implementacja Apple używana w prawie wszystkich maszynach PowerPC wyprodukowanych przez firmę.

Specyfikacje

Linux Standard Base (LSB) uzupełnia niektóre z powyższych specyfikacji dla architektur, w których jest określony. Tak jest na przykład w przypadku Systemu V ABI, suplementu AMD64.

86otwarte

86open był projektem mającym na celu osiągnięcie konsensusu w sprawie wspólnego formatu plików binarnych dla systemów operacyjnych Unix i Unix-podobnych na wspólnej architekturze x86 kompatybilnej z komputerami PC , aby zachęcić twórców oprogramowania do portowania na architekturę. Początkowy pomysł polegał na standaryzacji małego podzbioru specyfikacji Spec 1170, poprzednika specyfikacji Single UNIX , oraz biblioteki GNU C (glibc), aby umożliwić uruchamianie niezmodyfikowanych plików binarnych w systemach operacyjnych typu x86 typu Unix. Projekt został pierwotnie oznaczony jako „Spec 150”.

Ostatecznie wybrano format ELF, a konkretnie implementację ELF w Linuksie, po tym, jak okazało się, że jest to de facto standard obsługiwany przez wszystkich zaangażowanych dostawców i systemy operacyjne.

Grupa rozpoczęła dyskusje e-mailowe w 1997 roku i po raz pierwszy spotkała się razem w biurach Santa Cruz Operation 22 sierpnia 1997 roku.

Komitet sterujący był Marc Ewing , Dion Johnson, Evan Leibovitch, Bruce Perens , Andrew Roach, Bryan Wayne Sparks i Linus Torvalds . Inne osoby biorące udział w projekcie to Keith Bostic , Chuck Cranor, Michael Davidson, Chris G. Demetriou, Ulrich Drepper, Don Dugger, Steve Ginzburg, Jon „maddog” Hall , Ron Holt, Jordan Hubbard , Dave Jensen, Kean Johnston, Andrew Josey, Robert Lipe, Bela Lubkin, Tim Marsland, Greg Page, Ronald Joe Record, Tim Ruckle, Joel Silverstein, Chia-pi Tien i Erik Troan. Reprezentowane systemy operacyjne i firmy to BeOS , BSDI , FreeBSD , Intel , Linux , NetBSD , SCO i SunSoft .

Projekt rozwijał się iw połowie 1998 roku SCO rozpoczęło opracowywanie lxrun , warstwy kompatybilności typu open source, zdolnej do uruchamiania plików binarnych Linuksa na OpenServer , UnixWare i Solaris . SCO ogłosiło oficjalne wsparcie lxrun na LinuxWorld w marcu 1999 r. Sun Microsystems zaczął oficjalnie wspierać lxrun dla Solaris na początku 1999 r., A później przeniósł się do zintegrowanej obsługi formatu binarnego Linuksa za pośrednictwem Solaris Containers for Linux Applications .

Ponieważ BSD od dawna wspierały pliki binarne Linuksa (poprzez warstwę kompatybilności ), a główni dostawcy x86 Unix dodali obsługę tego formatu, w ramach projektu zdecydowano, że Linux ELF jest formatem wybranym przez branżę i „zadeklarował [d] samo rozwiązanie” w dniu 25 lipca 1999.

FatELF: uniwersalne pliki binarne dla systemu Linux

FatELF to rozszerzenie formatu binarnego ELF, które dodaje możliwości grubych plików binarnych . Jest przeznaczony dla systemu Linux i innych systemów operacyjnych typu Unix . Oprócz abstrakcji architektury procesora ( kolejność bajtów , rozmiar słowa , zestaw instrukcji procesora itp.) istnieje potencjalna zaleta abstrakcji platformy programowej, np. plików binarnych obsługujących wiele wersji ABI jądra . Od 2021 roku FatELF nie został zintegrowany z głównym jądrem Linuksa.

Zobacz też

Dalsza lektura

Linki zewnętrzne