1 介绍
1.1 分类
ELF全称是Executable and Linking Format。它是对象文件格式(object file format)。对象文件分为以下三类:
- 可重定位文件(relocatable file):包含与其他对象文件链接生成可执行文件或共享的对象文件的代码和数据。
- 可执行文件(executable file):是一个可执行程序。
- 共享对象文件(shared object file):共享对象文件包含适合在两个上下文中链接的代码和数据。首先,链接编辑器(link editor)可以将其与其他可重定位和共享的对象文件一起处理,以创建另一个对象文件。其次,动态链接器将其与可执行文件和其他共享对象结合起来,以创建进程映像。
1.2 视图
我们可以从链接视图和执行视图这两个视图来看ELF。
从上图可以看出,大致可分为四部分,分别是ELF Header、Program Header Table、Section/Segment、Section Header Table。其中链接视图以Section为单位,执行视图以Segment为单位。
- ELF Header位于文件的开头,它描述文件组织的“路线图”
- Program Header Table 描述了系统如何创建进程映像
- Section Header Table 包含描述文件section的信息
- Section 或 Program :segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件
注:Program Header Table 与 Section Header Table 在文件中并无固定顺序。
1.3 数据表示
对象文件格式支持8位字节和32位字节的处理器体系结构。下面是32位的数据类型。
2 ELF Header
ELF Header的结构体如下所示:
#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;
参数 | 解析 |
---|---|
e_ident | ELF的标识信息。将文件标记为对象文件,并提供独立于机器的数据,用于解码和解释文件内容。 |
e_type | 标识对象文件类型,0表示可重定位文件,1表示可执行文件,2表示共享对象文件 |
e_machine | 文件所需的体系结构 |
e_version | 对象文件的版本,0表示不合法版本,1表示当前版本 |
e_entry | 程序入口的虚拟地址,若无则置0 |
e_phoff | 以字节为单位保存Program Header Table的文件偏移量 |
e_shoff | 以字节为单位保存Section Header Table的文件偏移量 |
e_flags | 与文件相关但不同于处理器的标志 |
e_ehsize | 以字节为单位保存ELF Header的大小 |
e_phentsize | 以字节为单位保存每个Program Header Table的大小 |
e_phnum | 以字节为单位保存Program Header Table的数量 |
e_shentsize | 以字节为单位保存Section Header Table的大小 |
e_shnum | 以字节为单位保存Section Header Table的数量 |
e_shstrndx | Section Header Table的位置 |
(1)e_ident
- EI_MAG0 到 EI_MAG3表示魔数(magic number):用来标记文件是一个ELF对象文件。
- EI_CLASS:标识文件类。取值0、1、2分别表示Invalid class、32-bit objects、64-bit objects.
- EI_DATA:处理器特定数据的数据编码方式。ELFDATANONE(0)指非法数据编码;ELFDATA2LSB(1)指高位在前;ELFDATA2MSB(2)指低位在前。
- EI_VERSION:ELF的版本号。
- EI_PAD:e_ident 中未使用字节的起始。
(2)e_type
(3)e_machine
3 Section Header Table
Section Header Table 的结构体如下所示。
typedef struct{
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
}Elf32_Shdr;
参数 | 解析 |
---|---|
sh_name | Section名 |
sh_type | Section类型 |
sh_flags | Section标志 |
sh_addr | Section的第一个字节应处的位置。否则,此字段为0。 |
sh_offset | Section 第一个字节与文件头之间的偏移 |
sh_size | 以字节为单位表示Section的长度 |
sh_link | Section Header Table的索引链接。 |
sh_info | 附加信息,其解释依赖于节区类型 |
sh_addralign | 地址对齐约束 |
sh_entsize | 某些Section 中包含固定大小的项目,如符号表。对于这类节区,此成员给出每个表项的长度字节数 |
(1)sh_type
- SHT_NULL:Section头部是不活跃的,缺乏相关Section,该Section的其他成员限值无意义。
- SHT_PROGBITS:该Section的形式和含义仅由程序决定。
- SHT_SYMTAB 和SHT_DYNSYM:含有符号表
- SHT_STRTAB:含有字符串表
- SHT_RELA:含有重定位表项,含补齐
- SHT_HASH:含有符号哈希表
- SHT_DYNAMIC:含有动态链接信息
- SHT_NOTE:含有标记文件信息
- SHT_NOBITS:不占空间但类似于SHT_PROGBITS
- SHT_REL:含有重定位表项,不含补齐
- SHT_SHLIB:语义未规定
- SHT_LOPROC 到SHT_HIPROC:此范围中的值是为处理器专用语义保留的。
- SHT_LOUSER:应用程序的索引下界
- SHT_HIUSER:应用程序的索引上界
(2)sh_flags
Program Header Table
Program Header Table结构体如下所示。
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_phdr;
参数 | 解析 |
---|---|
p_type | Segment类型 |
p_offset | 从文件头到该Segment第一个字节的偏移 |
p_vaddr | Segment第一个字节将被放到内存中的虚拟地址 |
p_paddr | Segment的物理地址 |
p_filesz | Segment中文件映像的字节数 |
p_memsz | Segment中内存映像的字节数 |
p_flags | Segment标记 |
p_align | 与内存和文件中Segment对齐的值 |
(1)p_type
- PT_NULL:此数组元整未使用
- PT_LOAD:此数组元素给出一个可加载的段,段的大小由 p_filesz 和 p_memsz描述。
- PT_DYNAMIC:数组元素给出动态链接信息
- PT_INTERP:数组元素给出一个 NULL 结尾的字符串的位置和长度,该字符串将被当作解释器调用
- PT_NOTE:此数组元素给出附加信息的位置和大小
- PT_SHLIB:Segment类型被保留,不过语义未指定
- PT_PHDR:此类型的数组元素如果存在,则给出了程序头部表自身的大小和位置,既包括在文件中也包括在内存中的信息
- PT_LOPROC 到PT_HIPROC:此范围的类型保留给处理器专用语义