Section Header上节说了section header table是一个数组结构 , 这个数组的位置在 e_shoff 处 , 共有 e_shnum 个元素(即section) , 每个元素的大小为 e_shentsize 字节 。每个元素的结构如下:
typedef struct{Elf32_Word sh_name;/* Section name (string tbl index) */Elf32_Word sh_type;/* Section type */Elf32_Word sh_flags;/* Section flags */Elf32_Addr sh_addr;/* Section virtual addr at execution */Elf32_Off sh_offset;/* Section file offset */Elf32_Word sh_size;/* Section size in bytes */Elf32_Word sh_link;/* Link to another section */Elf32_Word sh_info;/* Additional section information */Elf32_Word sh_addralign;/* Section alignment */Elf32_Word sh_entsize;/* Entry size if section holds table */} Elf32_Shdr;其中 sh_name 是该section的名称 , 用一个word表示其在字符表中的偏移 , 字符串表(.shstrtab)就是上面说到的第 e_shstrndx 个元素 。ELF文件中经常使用这种偏移表示方式 , 可以方便组织不同区段之间的引用 。
sh_type 表示本section的类型 , SPEC中定义了几十个类型 , 列举其中一些如下:
SHT_NULL: 表示该section无效 , 通常第0个section为该类型SHT_PROGBITS: 表示该section包含由程序决定的内容 , 如 .text 、 .data 、 .plt 、 .gotSHT_SYMTAB/SHT_DYNSYM: 表示该section中包含符号表 , 如 .symtab 、 .dynsymSHT_DYNAMIC: 表示该section中包含动态链接阶段所需要的信息SHT_STRTAB: 表示该section中包含字符串信息 , 如 .strtab 、 .shstrtabSHT_REL/SHT_RELA: 包含重定向项信息虽然每个section header的大小一样(e_shentsize字节) , 但不同类型的section有不同的内容 , 内容部分由这几个字段表示:
sh_offset: 内容起始地址相对于文件开头的偏移sh_size: 内容的大小sh_entsize: 有的内容是也是一个数组 , 这个字段就表示数组的元素大小与运行时信息相关的字段为:
sh_addr: 如果该section需要在运行时加载到虚拟内存中 , 该字段就是对应section内容(之一个字节)的虚拟地址sh_addralign: 内容地址的对齐 , 如果有的话需要满足 sh_addr % sh_addralign = 0sh_flags: 表示所映射内容的权限 , 可根据 SHF_WRITE/ALLOC/EXECINSTR 进行组合另外两个字段 sh_link 和 sh_info 的含义根据section类型的不同而不同 , 如下表所示:

文章插图
至于不同类型的section , 有的是保存符号表 , 有的是保存字符串 , 这也是ELF表现出拓展性和复杂性的地方 , 因此需要在遇到具体问题的时候查看文档去进行具体分析 。
Program Headerprogram header table用来保存程序加载到内存中所需要的信息 , 使用段(segment)来表示 。与section header table类似 , 同样是数组结构 。数组的位置在偏移 e_phoff 处 , 每个元素(segment header)的大小为 e_phentsize , 共有 e_phnum 个元素 。单个segment header的结构如下:
typedef struct{Elf32_Word p_type;/* Segment type */Elf32_Off p_offset;/* Segment file offset */Elf32_Addr p_vaddr;/* Segment virtual address */Elf32_Addr p_paddr;/* Segment physical address */Elf32_Word p_filesz;/* Segment size in file */Elf32_Word p_memsz;/* Segment size in memory */Elf32_Word p_flags;/* Segment flags */Elf32_Word p_align;/* Segment alignment */} Elf32_Phdr;既然program header的作用是提供用于初始化程序进程的段信息 , 那么下面这些字段就是很直观的:
p_offset: 该segment的数据在文件中的偏移地址(相对文件头)p_vaddr: segment数据应该加载到进程的虚拟地址p_paddr: segment数据应该加载到进程的物理地址(如果对应系统使用的是物理地址)p_filesz: 该segment数据在文件中的大小p_memsz: 该segment数据在进程内存中的大小 。注意需要满足 p_memsz>=p_filesz , 多出的部分初始化为0 , 通常作为 .bss 段内容p_flags: 进程中该segment的权限(R/W/X)p_align: 该segment数据的对齐 , 2的整数次幂 。即要求 p_offset % p_align = p_vaddr。剩下的 p_type 字段 , 表示该program segment的类型 , 主要有以下几种:
PT_NULL: 表示该段未使用PT_LOAD: Loadable Segment , 将文件中的segment内容映射到进程内存中对应的地址上 。值得一提的是SPEC中说在program header中的多个PT_LOAD地址是按照虚拟地址递增排序的 。PT_DYNAMIC: 动态链接中用到的段 , 通常是RW映射 , 因为需要由 interpreter (ld.so)修复对应的的入口PT_INTERP: 包含interpreter的路径 , 见下文PT_HDR: 表示program header table本身 。如果有这个segment的话 , 必须要在所有可加载的segment之前 , 并且在文件中不能出现超过 一次。在不同的操作系统中还可能有一些拓展的类型 , 比如 PT_GNU_STACK 、 PT_GNU_RELRO 等 , 不一而足 。
推荐阅读
- 做梦梦见被一群狗追咬,到底什么意思
- 腔棘鱼是什么时代的 腔棘鱼是什么?
- 野生黄鱼和养殖黄鱼的区别图片 野生黄鱼和养殖黄鱼的区别是什么
- 梦见别人的房屋着火啥意思啊
- 母亲梦见儿子死亡啥意思
- 法院仲裁是什么意思 仲裁是什么意思通俗点?
- 岁月不饶人意思是什么 岁月不饶人的意思是什么20字?
- 论据是什么意思举例 事实论据是什么?
- 退货上门取件什么意思 快递退款上门取件什么意思?
- 怀孕梦见吃葡萄预示什么意思