http://blog.csdn.net/lingfong_cool/article/details/7832896
(一) ELF 文件的格式
ELF 文件類型 (1) 可重定位文件( .o 目標文件) : 用於鏈接創建可執行文件或 so 文件
(2) 可執行文件 : 用於執行
(3)so( 共享對象 ) 文件 : 用於鏈接
注 : 一個 Program Header 對應一個 Segment
一個 Section Header 對應一個 Section
Segment 由 Section 構成
Segment 類型 :#define PT_NULL 0 unused
#define PT_LOAD 1 可加載段 ( 代碼節和數據節 )
#define PT_DYNAMIC 2 動態鏈接段 ( 動態鏈接信息 )
#define PT_INTERP 3 解釋器段 ( 動態鏈接器路徑 )
#define PT_NOTE 4 auxiliary information
#define PT_SHLIB 5 reserved - purpose undefined
#define PT_PHDR 6 program header
#define PT_NUM 7 Number of segment types
#define PT_LOOS 0x60000000 reserved range for OS
#define PT_HIOS 0x6fffffff specific segment types
#define PT_LOPROC 0x70000000 reserved range for processor
#define PT_HIPROC 0x7fffffff specific segment types
Section 類型 : #define ELF_BSS ".bss" uninitialized data
#define ELF_DATA ".data " 數據節 initialized data
#define ELF_DEBUG ".debug" debug
#define ELF_DYNAMIC ".dynamic " 動態鏈接節 dynamic linking information
#define ELF_DYNSTR ".dynstr" dynamic string table
#define ELF_DYNSYM ".dynsym" dynamic symbol table
#define ELF_FINI ".fini" termination code
#define ELF_GOT ".got" global offset table
#define ELF_HASH ".hash" symbol hash table
#define ELF_INIT ".init" initialization code
#define ELF_REL_DATA ".rel.data" relocation data
#define ELF_REL_FINI ".rel.fini" relocation termination code
#define ELF_REL_INIT ".rel.init" relocation initialization code
#define ELF_REL_DYN ".rel.dyn" relocaltion dynamic link info
#define ELF_REL_RODATA ".rel.rodata" relocation read-only data
#define ELF_REL_TEXT ".rel.text" relocation code
#define ELF_RODATA ".rodata" read-only data
#define ELF_SHSTRTAB ".shstrtab" section header string table
#define ELF_STRTAB ".strtab" string table
#define ELF_SYMTAB ".symtab" symbol table
#define ELF_TEXT ".text " 代碼節 code
(二) ELF 文件的加載過程
源文件 Trunk/System/ElfLoader/dll/elfloader.c
LoadElfExec() 函數
加載的具體過程
1. 打開文件 open_library(char* filename)
系統調用 open(): 創建 File 結構體 , 放入進程打開文件表 , 返回 ( 打開文件表 ) 下標
2. 讀出文件頭和程序頭表 IsElfFormat(FILE)
讀出 ELF 文件頭 ( 同時讀出了程序頭表 Program Header Table), 判斷 ELF 格式根據文件頭中的e_ident 來比較判斷 .
3. 加載文件 load_library(char * filename,int fd)
(1) 計算所有 segment 占用內存大小 get_lib_extents()
通過遍歷程序頭表 (Program Header Table), 算出所有 segment 將占用的內存大小extents_size
(2) 分配內存 alloc_mem_region(extents_size)
匿名映射一塊非共享的私有內存 ( 不涉及文件 )
(3) 分配 soinfo 結構體 alloc_info(char *filename)
從全局靜態 soinfo 結構體數組中分配 soinfo 結構體 ( 描述整個 ELF 文件 )
(4) 加載 segment
load_segment(int fd,void* header,soinfo*si)
(1) 可加載段 (PT_LOAD): 映射到內存
mmap(void * start,size_t len, int prot,int flags,int fd,off_t offsize)
把 ELF 文件 offsize 處的 segment 映射到已分配內存的 start 處
(2) 動態鏈接段
由動態鏈接節設置 soinfo 中的動態鏈接信息
(5) 設置 soinfo 結構體
4. 加載依賴的動態鏈接庫
5.重定位(自身符號)
重定位表項: Elf32_Addr r_offset (重定位)內存地址(offset of relocation)
Elf32_Word r_info 符號表下標和類型(symbol table index and type)
符號表項: Elf32_Word st_name 符號名(name - index into string table)
Elf32_Addr st_value 符號值(symbol value)
Elf32_Word st_size symbol size
unsigned char st_info type and binding
unsigned char st_other 0 - no defined meaning
Elf32_Half st_shndx; section header index
根據重定位表(表項)查符號表,得到符號內存地址,修改(重定位)內存值
最后得到soinfo結構體數組描述了所有加載的文件
6.如果入口地址不為零,調用入口函數