ELF 格式詳解(一)
ELF 全稱 “Executable and Linkable Format”,即可執行可連結檔案格式,目前常見的Linux、 Android可執行檔案、共享庫(.so)、目標檔案( .o)以及Core 檔案(吐核)均為此格式。
檔案佈局
常見的ELF檔案大致結構如下:
常見的ELF格式如上圖所示,左邊為連結檢視,右邊為執行檢視。
連結檢視:
靜態連結器(即編譯後參與生成最終ELF過程的連結器,如ld )會以連結檢視解析ELF。編譯時生成的 。o(目標檔案)以及連結後的 。so (共享庫)均可透過連結檢視解析,連結檢視可以沒有段表(如目標檔案不會有段表)。
執行檢視:
動態連結器(即載入器,如x86架構 linux下的 /lib/ld-linux。so。2或者安卓系統下的 /system/linker均為動態連結器)會以執行檢視解析ELF並動態連結,執行檢視可以沒有節表。
檔案頭
ELF的結構宣告位於系統標頭檔案 elf。h 中,ELF格式分為32位與64位兩種,除了重定位型別稍有區別,其它大致相同,為了簡化描述,後續說明將省略32/64字樣。
ELF Header的宣告如下 :
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf_Half e_type; /* Object file type */
Elf_Half e_machine; /* Architecture */
Elf_Word e_version; /* Object file version */
Elf_Addr e_entry; /* Entry point virtual address */
Elf_Off e_phoff; /* Program header table file offset */
Elf_Off e_shoff; /* Section header table file offset */
Elf_Word e_flags; /* Processor-specific flags */
Elf_Half e_ehsize; /* ELF header size in bytes */
Elf_Half e_phentsize; /* Program header table entry size */
Elf_Half e_phnum; /* Program header table entry count */
Elf_Half e_shentsize; /* Section header table entry size */
Elf_Half e_shnum; /* Section header table entry count */
Elf_Half e_shstrndx; /* Section header string table index */
} Elf_Ehdr;
e_ident
包含了Maigc Number和其它資訊,共16位元組。
0~3:前4位元組為Magic Number,固定為ELFMAG。
4(EI_CLASS):ELFCLASS32代表是32位ELF,ELFCLASS64 代表64位ELF。
5(EI_DATA):ELFDATA2LSB代表小端,ELFDATA2MSB代表大端。
6(EI_VERSION):固定為EV_CURRENT(1)。
7(EI_OSABI):作業系統ABI標識(實際未使用)。
8(EI_ABIVERSION):ABI版本(實際 未使用)。
9~15:對齊填充,無實際意義。
e_type
ELF的檔案型別,定義如下:
ET_REL 可重定位文 件(如目標檔案)
ET_EXEC 可執行檔案(可直接執行的檔案)
DT_DYN 共享目標檔案(如SO庫)
DT_CORE Core檔案(吐核檔案)
注:GCC使用編譯選項 -pie 編譯的可執行檔案實際 也是DT_DYN型別。
e_machine
e_verison
檔案版本,目前常見的ELF 檔案版本均為EV_CURRENT(1)。
e_entry
入口虛擬地址。
e_phoff
段表文件偏移。
e_shoff
節表文件偏移。
e_flags
處理器特定的標誌,一般為0。
e_ehsize
Elf_Header的大小(位元組)
e_phentsize
段頭(Program Header)的大小(位元組)。
e_phnum
段的數量。
e_shentsize
節頭(Section Header)的大小(位元組)。
e_shnum
字的數量。
e_shstrndx
節字串表的節索引。
更多技術相關文章:Virbox技術部落格