一、 ELF簡介
ELF(Executable and Linkable Format)即可執行連接文件格式,是一種比較複雜的文件格式,但其應用廣泛。與linux下的其他可執行文件(a.out,cof)相比,它對節的定義和gnu工具鏈對它的支持使它十分靈活,它保存的足夠了系統相關信息使它能支持不同平臺上的交叉編譯和交叉鏈接,可移植性很強.同時它在執行中支持動態鏈接共享庫。 ELF目前是Linux,SVR4和Solaris2.0默認的目標文件格式,目前標準接口委員會TIS已將ELF標準化爲一種可移植的目標文件格式,運行於32-bit Intel體系微機上,可與多種操作系統兼容。分析elf文件有助於理解一些重要的系統概念,例如程序的編譯和鏈接,程序的加載和運行等。
二、3種類型的ELF文件:
i. 可重定位文件:用戶和其他目標文件一起創建可執行文件或者共享目標文件,例如lib*.a文件。
ii. 可執行文件:用於生成進程映像,載入內存執行,例如編譯好的可執行文件a.out。
iii.共享目標文件:用於和其他共享目標文件或者可重定位文件一起生成elf目標文件或者和執行文件一起創建進程映像,例如lib*.so文件。
三、ELF文件作用:
ELF文件參與程序的連接(建立一個程序)和程序的執行(運行一個程序),所以可以從不同的角度來看待ELF格式的文件。
i. 如果用於編譯和鏈接(可重定位文件),則編譯器和鏈接器將把ELF文件看作是節頭表描述的節的集合,程序頭表可選。
ii. 如果用於加載執行(可執行文件),則加載器則將把ELF文件看作是程序頭表描述的段的集合,一個段可能包含多個節,節頭表可選。
iii. 如果是共享文件,則兩者都含有。
四、ELF文件總體組成:
從連接的角度和運行的角度,可以分別把目標文件的組成部分做以下劃分:
i. ELF頭文件:位於文件最開始處,包含整個文件的結構信息。
ii. 節(section):是專門用於連接過程而言的,在每個節中包含指令數據、符號數據、重定位數據等等。
iii. 程序頭表: 在運行過程中是必須的,在鏈接過程中是可選的,因爲它的作用是告訴系統如何創建進程的映像。
iv. 節頭表:包含文件中所用節的信息。
下面看一下Linux內核對ELF頭文件的定義,在linux+v2.6.36/include/linux/elf.h
/* 32-bit ELF base types. */
typedef __u32 Elf32_Addr;
typedef __u16 Elf32_Half;
typedef __u32 Elf32_Off;
typedef __s32 Elf32_Sword;
typedef __u32 Elf32_Word;
#define EI_NIDENT 16
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT]; //16字節的信息,下文詳細解釋
Elf32_Half e_type; //目標文件類型?
Elf32_Half e_machine; //體系結構類型
Elf32_Word e_version; //目標文件版本
Elf32_Addr e_entry; /* Entry point 程序入口的虛擬地址*/
Elf32_Off e_phoff; //程序頭部表的偏移量
Elf32_Off e_shoff; //節區頭部表的偏移量
Elf32_Word e_flags; //
Elf32_Half e_ehsize; //ELF頭部的大小
Elf32_Half e_phentsize; //程序頭部表的表項大小
Elf32_Half e_phnum; //程序頭部表的數目
Elf32_Half e_shentsize; //節區頭部表的表項大小
Elf32_Half e_shnum; //節區頭部表的數目
Elf32_Half e_shstrndx; //
}Elf32_Ehdr; //此結構體一共52個字節
我們使用notepad++打開一個ELF文件,可以看到前四個字節爲" ELF":
此外,在linux下我們可以使用objdump 和readelf 兩個命令 ,查看到ELF文件的各個節段的信息,運行時必要的動態鏈接庫,ELF中的彙編代碼等。