一、ELF文件头(elf_header)
可以用以下这个数据结构体来描述文件头。
struct Elf64_Ehdr { unsigned char e_ident[16]; 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; };
其中各个成员的意义如下:
1. e_ident
从头开始的16个字节含有 ELF 文件的识别标志,并且提供了一些用于解码 和解析文件内容的数据,是不依赖于具体操作系统的。
0000 7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00
1.1 File identification
是ELF文件开头的4个字节也就是文件标识EI_MAG[0] ~ EI_MAG[3],这4个字节的内容是固定的。
EI_MAG[0] | 0x7F | |
EI_MAG[1] | 0x45 | E |
EI_MAG[2] | 0x4C | L |
EI_MAG[3] | 0x46 | F |
1.2 EI_CLASS
是上面块中第五个字节,代表的是目标文件的类型
ELFCLASSNONE | 0 | 无效的种类 |
ELFCLASS32 | 1 | 32位对象 |
ELFCLASS64 | 2 | 64位对象 |
1.3 EL_DATA
第六个字节代表着文件中数据采用的编码格式
0x1表示采用小端序,0x2为大端序
1.4 EI_VERSION
第7个字节EI_VERSION指明 ELF 文件头的版本,目前这个版本号是 EV_CURRENT,即“1”
1.5 EI_OSABI
第8个字节EI_OSABI表示操作系统/ABI标识
1.6 EI_ABIVERSION
第9个字节 ABI版本。
1.7 EI_PAD
第10个字节到第15个字节暂时不使用,留作以后扩展,在实际的文件中应被填 0 补充,其它程序在读取 ELF 文件头时应该忽略这些字节。
1.8 EI_NIDENT
第16个字节是e_ident[]的大小。
2. e_type
0010 03 00 B7 00 01 00 00 00 20 13 00 00 00 00 00 00
ET_NONE | 0 | 没有文件类型 |
ET_REL | 1 | 可重定位文件 |
ET_EXEC | 2 | 可执行文件 |
ET_DYN | 3 | 动态链接库文件 |
ET_CORE | 4 | Core 文件 |
ET_LOPROC | 0xFF00 | 处理器指定下限 |
ET_HIPROC | 0xFFFF | 处理器指定上限 |
3. e_machine
这一项指定了当前文件可以运行的机器架构
0010 03 00 B7 00 01 00 00 00 20 13 00 00 00 00 00 00
enum MachineArchitecture { EM_NONE = 0, // No machine. EM_386 = 3, // Intel 架构. EM_ARM = 40, // ARM 架构. 0x28 EM_X86_64 = 62, // Intel x86-64 架构. 0x3E EM_AARCH64 = 183, // ARM 64位 架构. 0xB7 // 其他值略过 };
4. e_version
0010 03 00 B7 00 01 00 00 00 20 13 00 00 00 00 00 00
同上1.4
5. e_entry
0010 03 00 B7 00 01 00 00 00 20 13 00 00 00 00 00 00
程序入口点地址
6. e_phoff
0020 40 00 00 00 00 00 00 00 E0 41 00 00 00 00 00 00
是指明程序头表(program header table)开始处在文件中的偏移量。如果没有程序头表,该值应设为0。
即0x40也是elf_header的大小。
7. e_shoff
0020 40 00 00 00 00 00 00 00 E0 41 00 00 00 00 00 00
是指明节头表(section header table)开始处在文件中的偏移量。如果没有节头表,该值应设为 0。
8. e_flags
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
这一项给出文件中与特定处理器相关的标志。
#define EF_MIPS_NOREORDER 0x00000001 #define EF_MIPS_PIC 0x00000002 /* Contains PIC code */ #define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */ #define EF_MIPS_UCODE 0x00000010 #define EF_MIPS_ABI2 0x00000020 /* N32 */ #define EF_MIPS_OPTIONS_FIRST 0x00000080 #define EF_MIPS_ABI 0x0000F000 #define EF_MIPS_ABI_O32 0x00001000 #define EF_MIPS_ABI_O64 0x00002000 #define EF_MIPS_ABI_EABI32 0x00003000 #define EF_MIPS_ABI_EABI64 0x00004000 #define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */ #define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */ #define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */ #define EF_MIPS_ARCH 0xF0000000 /* Architecture field */ #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */ #define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */ #define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */ #define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */ #define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */ #define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */ #define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */ #define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */ #define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */
9. e_ehsize
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
此字段表明 ELF 文件头的大小,以字节为单位。
10. e_phentsize
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
此字段表明在程序头表(program header table)中每一个表项的大小,以字节为单位,每个表项的大小相同。
11. e_phnum
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
此字段表明程序头表中总共有多少个表项。
如上图所示
e_phentsize 乘以 e_phnum 就得到了整个program header table的大小。
12. e_shentsize
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
此字段表明在节头表(section header table)中每一个表项的大小,一个节头是节头表中的一项;节头表中所有项占据的空间大小相同。
13. e_shnum
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
此字段表明节头表中总共有多少个表项。
如上图所示
e_shentsize 乘以 e_shnum,就得到了整个section header table的大小。
14. e_shstrndx
0030 00 00 00 00 40 00 38 00 08 00 40 00 18 00 17 00
节头表中与节名字表相对应的表项的索引。如果文件没有节名字表,此值应设置为 SHN_UNDEF。
0x17转为十进制是23