根据定义,elf32的结构体定义,在Linux上可以在/usr/include/elf.h中找到
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
有了这些数据结构的信息,然后对应具体的数据细节如下:
- e_ident[EI_NIDENT]
文件的标识以及标识描述了elf如何编码等信息。
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
关于该结构体的索引可以看下面的表格:
名称 | 取值 | 目的 |
EI_MAG0 | 0 | 文件标识(0x7f) |
EI_MAG1 | 1 | 文件标识(E) |
EI_MAG2 | 2 | 文件标识(L) |
EI_MAG3 | 3 | 文件标识(F) |
EI_CLASS | 4 | 文件类 |
EI_DATA | 5 | 数据编码 |
EI_VERSION | 6 | 文件版本 |
EI_PAD | 7 | 补齐字节开始处 |
EI_NIDENT | 16 | e_ident[]大小 |
EI_CLASS的内容,当取值为0时,是非法类别,1是32位的目标,2是64位的目标。这里是1所以程序是32位的目标。
EI_DATA表示数据的编码,当为0时,表示非法数据编码,1表示高位在前,2表示低位在前。
EL_VERSION表示了elf的头部版本号码。
前面四个基本上确定的,内容第一个字符为7f,后面用ELF字符串表示该文件为ELF格式。
- e_type
该数据类型是uint16_t数据类型的,占两个字节。通过字段查看,可以看到这个值为00 02。表格定义如下:
名称 | 取值 | 含义 |
ET_NONE | 0x0000 | 未知目标文件格式 |
ET_ERL | 0x0001 | 可重定位文件 |
ET_EXEC | 0x0002 | 可执行文件 |
ET_DYN | 0x0003 | 共享目标文件 |
ET_Core | 0x0004 | Core文件(转储格式) |
ET_LOPROC | 0xff00 | 特定处理器文件 |
ET_HIPROC | 0xffff | 特定处理器文件 |
对应表格内容,可以看到类型为EXEC即可执行文件类型。
- e_machine
由字段可以看到为00 28,关于这个字段的解析,基本上就是表示该elf文件是针对哪个处理器架构的。
下面只列出几个常见的架构的序号
名称 | 取值 | 含义 |
EM_NONE | 0 | No machine |
EM_SPARC | 2 | SPARC |
EM_386 | 3 | Intel 80386 |
EM_MIPS | 8 | MIPS I Architecture |
EM_PPC | 0x14 | PowerPC |
EM_ARM | 0x28 | Advanced RISC Machines ARM |
通过上述的表格,可以看到该架构是ARM处理器上运行的程序。
- e_version
该字段占四个字节,表示当前文件版本的信息。现在取值为00 00 00 01。从取值上来看
名称 | 取值 | 含义 |
EV_NONE | 0 | 非法版本 |
EV_CURRENT | 1 | 当前版本 |
- e_entry
这里表示程序的入口地址,目前为四字节,所以通过字段解析到的内容为00 00 80 00。得到可执行程序的入口地址为0x8000。
- e_phoff
该字段表示程序表头偏移。占四个字节,根据字段解析,可以查看当前的偏移量为00 00 00 34。也就是实际的偏移量为52个字节。这52个字节其实就是头部的信息数据结构体的大小。
- e_shoff
该区域比较重要,记录了section的偏移地址。为四字节,解析出来的字段为0x00 04 24 5c。所以得到地址为0x4245c。
根据这个偏移得到section的内容:
通过readelf -t也可以得到类似的结果。
关于节区如何解析。后面再进行描述。
- e_flags
特定处理器格式的标志,这里的字段解析为05 00 02 00。与特定的处理器相关。
- e_ehsize
elf文件的头部大小。该取值与头文件结构体的大小相关,目前为52字节,即00 34。
- e_phentsize
程序头部表项大小,当前取值为00 20,为32个字节,这里表示