(一) 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.如果入口地址不为零,调用入口函数 |
|
来自: astrotycoon > 《链接加载》