ELF FORMAT
1 ELF 格式

ELF 是 EXECUTABLE AND LINKABLE FORMAT 的簡寫,意思是可執行與可連結格式。 ELF 格式是 LINUX 上的執行檔與目的檔的通用格式。 執行檔主要就是依據 ELF 可執行格式編寫,目的檔就是依據 ELF 的可連結格式編寫。 另外,模組檔就是目的檔的應用,通常一個 C 語言檔可編譯成一個 ELF 格式的目的檔(.o),多個目的檔可連結成一個模組檔(.module)。 作業系統執行可執行檔時,會依據程式檔頭表,將可執行檔的程式群轉換成二進位映像,並包裝成一個任務,放到記憶體中執行。 可連結檔通常是用來連結成執行檔之前的模組檔或目的檔。 了解 ELF 格式,進而撰寫作業系統核心,是作業系統開發的必經之路。


2 ELF 內容架構

ELF 檔案的內容大致上可分成五個部分,ELF 檔頭、程式檔頭表、程式群、區段檔頭表、區段群。 可執行檔一定會有 ELF 檔頭、程式檔頭表、程式群。可連結檔一定會有 ELF 檔頭、區段檔頭表、區段群。

GRUB2

2.1 ELF 檔頭格式

ELF 格式使用的資料型態:

SIGNED LARGE INTEGER
資料類型體積隊齊說明
Elf32_Addr44UNSIGNED PROGRAM ADDRESS
Elf32_Half22UNSIGNED MEDIUM INTERGER
Elf32_Off44UNSIGNED FILE OFFSET
Elf32_Sword44
Elf32_Word44SIGNED LARGE INTEGER
unsigned char11UNSIGNED SMALL INTEGER

ELF 檔頭結構:

   ELF_FORMAT.PDF
01 #define EINIDENT 16
02 typedefstruct{
03      unsigned char eident[EINIDENT];
04      Elf32_Half e_type;
05      Elf32_Half e_machine;
06      Elf32_Word e_version;
07      Elf32_Addr e_entry;
08      Elf32_Off  e_phoff;
09      Elf32_Off  e_shoff;
10      Elf32_Word e_flags;
11      Elf32_Half e_ehsize;
12      Elf32_Half e_phentsize;
13      Elf32_Half e_phnum;
14      Elf32_Half e_shentsize;
15      Elf32_Half e_shnum;
16      Elf32_Half e_shstrndx;
17 }Elf32Ehdr;

ELF 檔頭的 e_type 是檔案型態。
ELF 檔頭的 e_machine 是機器號碼。
ELF 檔頭的 e_version 是版本號碼。
ELF 檔頭的 e_entry 是可執行檔的入口點。
ELF 檔頭的 e_phoff 是程式檔頭表的位址。
ELF 檔頭的 e_shoff 是區段檔頭表的位址。
ELF 檔頭的 e_flags 是 ELF 檔的旗號。
ELF 檔頭的 e_ehsize 是 ELF 檔頭的體積。
ELF 檔頭的 e_phentsize 是程式檔頭表的程式檔頭體積。
ELF 檔頭的 e_phnum 是程式檔頭表的程式檔頭數目。
ELF 檔頭的 e_shentsize 每個區段檔頭的體積。
ELF 檔頭的 e_shnum 是區段檔頭表的區段檔頭數目。
ELF 檔頭的 e_shstrndx 是區段檔頭表專用的字串表的區段索引。


2.2 程式檔頭格式
   ELF_FORMAT.PDF
01 typedef struct{
02     Elf32_Word p_type;
03     Elf32_Off  p_offset;
04     Elf32_Addr p_vaddr;
05     Elf32_Addr p_paddr;
06     Elf32_Word p_filesz;
07     Elf32_Word p_memsz;
08     Elf32_Word p_flags;
09     Elf32_Word p_align;
10 }Elf32Phdr;

程式檔頭的 p_type 是程式型態。
程式檔頭的 p_offset 是程式內容在 ELF 檔的起始位址。
程式檔頭的 p_vaddr 是程式在虛擬記憶體中的起始位址,即載入到記憶體的位址。
程式檔頭的 p_paddr 是程式在物理實際記憶體的起始位址。
程式檔頭的 p_filesz 是程式在 ELF 檔體積。
程式檔頭的 p_memsz 是程式段在記憶體的體積。
程式檔頭的 p_flags 是程式的旗號群。
程式檔頭的 p_align 是程式在記憶體的對齊位元組數。


2.3 區段檔頭格式
   ELF_FORMAT.PDF
01 typedefstruct{
02 Elf32_Word sh_name;
03 Elf32_Word sh_type;
04 Elf32_Word sh_flags;
05 Elf32_Addr sh_addr;
06 Elf32_Off  sh_offset;
07 Elf32_Word sh_size;
08 Elf32_Word sh_link;
09 Elf32_Word sh_info;
10 Elf32_Word sh_addralign;
11 Elf32_Word sh_entsize;
12 }Elf32Shdr;

區段檔頭的 sh_name 是區段檔頭的名稱字串索引值,該字串位於區段檔頭表的字串表。
區段檔頭的 sh_type 是區段型態。
區段檔頭的 sh_flags 是區段旗號。
區段檔頭的 sh_addr 是區段內容要載入的記憶體位址。
區段檔頭的 sh_offset 是此區段在 ELF 檔的位址。
區段檔頭的 sh_size 是區段在 ELF 檔的體積。
區段檔頭的 sh_link 是區段的連結型態。
區段檔頭的 sh_info 是區段的資訊型態。
區段檔頭的 sh_addralign 是區段的記憶體對齊參數。
區段檔頭的 sh_entsize 是區段內每個單元資料的體積。