ELF文件头表示
文件头中含有整个文件的结构信息,包括一些控制单元的大小。可以用以下这个数据结构体来描述文件头:
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
数据类型大小:
名字 字节数 对齐字节数 目的
Elf32_Addr 4 4 无符号地址
Elf32_Half 2 2 无符号半整型
Elf32_Off 4 4 无符号文件偏移量
Elf32_Sword 4 4 有符号整型
Elf32_Word 4 4 无符号整型
unsigned char 1 1 无符号短整型
其中各个成员的意义如下:
e_ident
开头这16个字节含有 ELF 文件的识别标志,并且提供了一些用于解码和解析文件内容的数据,是不依赖于操作系统的。
e_ident[]数组各个索引位置的含义 | |||||||||
名字 | EI_MAG0 | EI_MAG1 | EI_MAG2 | EI_MAG3 | EI_CLASS | EI_DATA | EI_VERSION | EI_PAD | EI_NIDENT |
---|---|---|---|---|---|---|---|---|---|
值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 |
用途 | 文件标志 | 文件标志 | 文件标志 | 文件标志 | 文件类别 | 编码格式 | 文件版本 | 补齐字节开始位置 | e_ident[]数组的大小 |
下面对这几个字段名字解释一下
名字 | 值 | 意义 | 解释说明 | |
---|---|---|---|---|
EI_MAG0 ~ EI_MAG3 | ELFMAG0 | 0x7F | e_ident[EI_MAG0] | 文件的最前面 4 字节 e_ident[EI_MAG0] ~ e_ident[EI_MAG3]的内容被称为“魔数”,用于标识这是一个 ELF 文件。这四个字节存放的内容是固定的: |
ELFMAG1 | ‘E’ | e_ident[EI_MAG1] | ||
ELFMAG2 | ‘L’ | e_ident[EI_MAG2] | ||
ELFMAG3 | ‘F’ | e_ident[EI_MAG3] | ||
EI_CLASS | ELFCLASSNONE | 0 | 非法目标文件 | 接下来的一个字节 e_ident[EI_CLASS]指明目标文件的类型,目前支持两种字长,32 位和 64 位。32 位字长的文件(ELFCLASS32)所支持的系统,其进程地址空间为 4G 字节,文件的最大容量也是 4G。64 位字长的文件(ELFCLASS64)格式定义目前还没有完成 |
ELFCLASS32 | 1 | 32位目标文件 | ||
ELFCLASS64 | 2 | 64位目标文件 | ||
EI_DATA | ELFDATANONE | 0 | 非法编码格式 | 指明了目标文件中的数据编码格式 |
ELFDATA2LSB | 1 | LSB编码(小端编码) | ||
ELFDATA2MSB | 2 | MSB编码(大端编码) | ||
EI_VERSION | EV_CURRENT | 1 | ELF 文件头的版本 | 目前这个版本号是 EV_CURRENT,即“1” |
EI_PAD~EI_NIDENT-1 | 从 e_ident[EI_PAD]到 e_ident[EI_NIDENT-1]之间的 9 个字节目前暂时不使用,留作以后扩展,在实际的文件中应被填 0 补充,其它程序在读取 ELF 文件头时应该忽略这些字节。 | |||
举个栗子 |
e_type
此字段表明本目标文件属于哪种类型,以下文件类型中,core 文件类型目前还不支持,但仍然为它保留了这一关键字。
名字 | ET_NONE | ET_REL | ET_EXEC | ET_DYN | ET_CORE | ET_LOPROC | ET_HIPROC |
---|---|---|---|---|---|---|---|
值 | 0 | 1 | 2 | 3 | 4 | 0xff00 | 0xffff |
意义 | 未知文件类型 | 可重定位文件 | 可执行文件 | 动态链接库文件 | Core文件 | 特定处理器文件扩展上/下边界 |
e_machine
此字段用于指定该文件适用的处理器体系结构,下表列出了几个主要的,其它的没列。
名字 | EM_NONE | EM_386 | RESERVED | EM_ARM |
值 | 0 | 3 | 11 ~ 16 | 40 |
意义 | 未知体系结构 | Intel Architecture | 保留未用 | ARM/Thumb Architecture |
在 ELF 文件中,处理器厂商可以定义一些自有的常量,还可以定义一些自有的段名字,这类命名必须要遵守一定的规则。
e_version
此字段指明目标文件的版本。EV_NONE表示非法版本号;EV_CURRENT表示当前版本号。EV_CURRENT 是一个动态的数字,表示最新的版本。
其他
e_entry
此字段指明程序入口的虚拟地址。即当文件被加载到进程空间里后,入口程序在进程地址空间里的地址。对于可执行程序文件来说,当 ELF 文件完成加载之后,程序将从这里开始运行;而对于其它文件来说,这个值应该是 0。
e_phoff:此字段指明程序头表(program header table)开始处在文件中的偏移量。如果没
有程序头表,该值应设为 0。
e_shoff:此字段指明节头表(section header table)开始处在文件中的偏移量。如果没有节头表,该值应设为 0。
e_flags:此字段含有处理器特定的标志位。标志的名字符合”EF_machine_flag”的格式。对于 Intel 架构的处理器来说,它没有定义任何标志位,所以 e_flags 应该为0。
e_ehsize:此字段表明 ELF 文件头的大小,以字节为单位。
e_phentsize:此字段表明在程序头表中每一个表项的大小,以字节为单位。
e_phnum:
此字段表明程序头表中总共有多少个表项。如果一个目标文件中没有程序头
表,该值应设为 0。
e_phnum:此字段表明程序头表中总共有多少个表项。如果一个目标文件中没有程序头表,该值应设为 0。
e_shentsize:此字段表明在节头表中每一个表项的大小,以字节为单位。
e_shnum:此字段表明节头表中总共有多少个表项。如果一个目标文件中没有节头表,该值应设为 0。
e_shstrndx:节头表中与节名字表相对应的表项的索引。如果文件没有节名字表,此值应设置为 SHN_UNDEF。