关于ELF
可执行与可链接格式(Executable and Linkable Format,ELF),常被称为 ELF格式,是一种用于可执行文件、目标代码、共享库和核心转储(core dump)的标准文件格式。
ELF文件格式在链接和程序的运行阶段的格式不同。链接阶段每个.o文件都是一个独立的ELF文件,为了效率和便利性将他们的节合并为段才能生成对应的可执行文件。
一个ELF文件包含的内容有:ELF文件头,程序头表,节头表和节。
数据类型和大小
32bit的ELF文件
类型 |
大小 |
unsigned char |
1 |
Elf32_Addr |
4 |
Elf32_Half |
2 |
Elf32_Off |
4 |
Elf32_SWord |
4 |
Elf32_Word |
4 |
64位的ELF文件
类型 |
大小 |
unsigned char |
1 |
Elf32_Addr |
8 |
Elf32_Half |
2 |
Elf32_Off |
8 |
Elf32_Xword |
8 |
Elf32_Word |
4 |
ELF 文件头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #define EI_NIDENT 16
typedef struct { unsigned char e_ident[EI_NIDENT]; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;
|
需要注意的几个字段:
- e_entry: 可执行程序入口点地址
- e_phoff: 程序头表偏移地址
- e_shoff: 节头表偏移地址
- e_ehsize: ELF头部的大小
- e_phentsize: 程序头表中每个条目的大小
- e_phnum: 程序头表中的条目数量。
- e_shentsize: 节头表中每个条目的大小
- e_shnum: 节头表中的条目数量
- e_shstrndx: 节头字符串表索引
程序头表
1 2 3 4 5 6 7 8 9 10 11
| typedef struct { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_Xword p_align; } Elf64_Phdr;
|
- p_offset: 段相对于文件的偏移地址
- p_vaddr: 段在内存中的虚拟地址
- p_paddr: 段的物理地址
- p_filesz: 段在文件中所占的大小
- p_memsz: 段在内存中所占的大小
- p_align: 对齐长度
节头表
1 2 3 4 5 6 7 8 9 10 11 12
| typedef struct { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; } Elf64_Shdr;
|
- sh_name: 节名称,是节区头字符串表节区中(Section Header String Table Section)的索引,因此该字段实际是一个数值。在字符串表中的具体内容是以 NULL 结尾的字符串。
- sh_type: 节类型
- sh_addr: 节在内存中的地址
- sh_offset: 节在文件中的偏移
- sh_size: 节的大小
- sh_addralign: 节的地址对齐长度