代码可从 /usr/include/elf.h 中找到
Executable Header
以下是 ELF header 的结构体

接下来,我们详细解析下每个字段
e_ident
这是一个 16字节 的数组,主要包含的是 ELF header 的 标识信息,(ident = identity)
以下解释每一个索引处的内容
-
0-3:魔数,用于标识这是一个
ELF文件,内容为0x7fELF -
4:
EI_CLASS = 4,二进制文件是32还是64位架构-
ELFCLASS32 = 1 -
ELFCLASS64 = 2
-
-
5:
EI_DATA = 5,架构是 大端序 还是 小端序-
ELFDATA2LSB = 1,小端序 -
ELFDATA2MSB = 2,大端序
-
-
6:
EI_VERSION = 6,ELF文件格式的版本EV_CURRENT = 1
-
7:
EI_OSABI = 7,确定ABI类型,默认值是0,即UNIX System V ABI -
8:
EI_ABIVERSION = 8,确定ABI版本,默认值是0 -
9-15:
EI_PAD = 9,这段用作填充,设置为0,用于以后的扩展
e_type
确定该 ELF 文件的类型
-
ET_NONE = 0:无类型 -
ET_REL = 1:可重定位文件 -
ET_EXEC = 2:可执行文件 -
ET_DYN = 3:动态库,或者叫共享目标文件 -
ET_CORE = 4: 核心转储文件
e_machine
确定该文件可运行的目标架构
-
EM_X86_64 = 62:x86_64 平台 -
EM_386 = 3: x86 平台 -
EM_ARM = 40:arm 平台
...
e_version
确定 ELF 文件格式的版本
EV_CURRENT = 1
e_entry
确定该文件的 入口点,当 动态链接器 结束加载 动态库 之后,需要将控制权移交到此处
这个字段的值是 虚拟地址
e_phoff
program header table 的 文件偏移量,不是 虚拟地址
值为0,表示没有 segemnt
e_shoff
section header table 的 文件偏移量,不是 虚拟地址
值为0,表示没有 section
e_flag
在 ELF 文件中用于存储与架构相关的标志,一般设置为0
e_ehsize
Executable header 的大小
e_phentsize
program header table 中每个条目的大小,即一个 program header 的大小
e_phnum
program header table 中的条目数量
e_shentsize
section header table 中每个条目的大小,即一个 section header 的大小
e_shnum
section header table 中的条目数量
e_shstrndx
一个 section 在 section header table 中的索引,这个 section 是一个特殊的 string table,里面包含的字符串是 ELF 文件中的各个 section 的名字
Section Headers

sh_name
确定当前 section header 的名字
值表示在 .shstrtab 中的下标,如果为0,表示没有名字
sh_type
确定 section 的类型
-
SHT_PROGBITS = 1,包含程序数据(指令和常量) -
SHT_SYMTAB = 2,符号表(静态,用于链接器) -
SHT_STRTAB = 3, 字符串表 -
SHT_DYNSYM = 11,符号表(动态,用于动态链接器) -
SHT_REL = 9静态链接的重定位信息 -
SHT_RELA = 4静态链接的重定位信息(包含额外添加值addend) -
SHT_DYNAMIC = 6动态链接所需信息
...
sh_flags
描述了 section 的附加信息
-
SHF_WRITE = 1,运行时可写 -
SHF_ALLOC = 2,执行时被加载到虚拟内存中 -
SHF_EXECINSTR = 4,包含可执行的指令
...
sh_addr
section 的 虚拟地址,用于链接的重定位,如果为0,表示不需要加载到虚拟内存中
sh_offset
section 的 文件偏移量
sh_size
section 的 大小
sh_link
用于表示与当前 section 有关联的其他 section 的 索引,帮助链接器识别并处理 section 与 section 之间的 关联
sh_info
包含了当前 section 的 额外信息(具体内容取决于 section 的 类型)
sh_addralign
当前 section 的 内存对齐要求,0和1表示没有对齐要求
sh_entsize
有一些 section,比如符号表,会有对应的 结构体,这个字段就包含了每个条目(即使用的结构体)的大小,如果不使用,就设置为0
Sections
.init 和 .fini
section .init 包含 执行初始化任务 的代码,SHF_EXECINSTR,操作系统在将控制转移至 entry point 前,会先执行这里的代码,相当于 构造函数,.fini 和 .init 的作用相反,相当于 析构函数
.text
代码段
.bss, .data, .rodata
-
.rodata只读数据,存放常量 -
.data存放初始化的全局/静态变量 -
.bss存放未初始化的全局/静态变量,又被称为 零初始化段,不占用磁盘空间,当程序运行时才分配实际空间
延迟绑定和 .plt, .got, .got.plt
Program Headers

p_type
确定了 segment 的类型
-
PT_LOAD = 1, 存储程序的可执行部分和数据部分,程序在加载时会将这些内容加载到内存中 -
PT_DYNAMIC = 2,指定了用于加载该程序的解释器(通常是动态链接器) -
PT_INTERP = 3,包含动态链接相关信息,帮助解释器加载并解析程序 -
PT_PHDR = 6,包含program header table
p_flags
确定了运行时对 segment 的访问权限
-
PF_X = 1,可执行 -
PF_W = 2,可写 -
PF_R = 4,可读
p_offset
当前 segment 的 文件偏移量
p_vaddr
当前 segment 的 虚拟地址 (被加载到这个地址处)
p_paddr
当前 segment 的 物理地址,一般被设置为0,表示不使用
p_filesz
当前 segment 的 在磁盘文件中所占的大小(不包括 .bss 这种零初始化段,因为全都是0,所以不需要存储在磁盘中,节省空间**
p_memsz
当前 segment 在运行时,分配到的虚拟空间的大小(包括 .bss 这种零初始化段,所以有时候可能会比 p_filesz 大)
p_align
确定当前 segment 的 内存对齐数
0和1表示不需要进行对齐
Summary

posted on
浙公网安备 33010602011771号