静态程序编译链接与装载(三)segment分析以及链接视图与执行视图
程序通过编译,链接生成ELF可执行之后,如果要被执行,是需要装载到内存当中,然后去执行的。
那么装载的过程,应该是如何装载的?是按照链接时候的section为单位进行装载吗?下面,就要基于这个问题,进行分析。
链接的时候,是通过section进行组合,得到最终的ELF,但是对section进行分类的话,section无非就下面几种权限:
-
RX:可读可执行,对应于代码段
-
RW: 可读可写,对应于数据段
-
R: 只读,对应于只读段
因为,就可以考虑,将相同权限,并且地址连续的的section,合并成一个大的段,这样的话,就方便装载。此时,这个段,就称为segment。
一、程序头表
对于可执行程序,是看的program headers表
对于可执行程序,program header table,程序头表,表征了 程序的 加载信息。
程序装载到内存,也是按段进行装载,不过此时,用的是segment
对于ELF可执行程序,关于program域的成员变量,都不为0
start of program headers |
程序头表在elf文件中的偏移 |
size of program headers |
程序头表,一个表项所占大小 |
number of program headers |
程序头表的表项个数 |
程序头表数据结构如下图所示:
p_type |
segment的类型,关注LOAD,表示要加载到内存 |
p_offset |
segment在文件中的偏移 |
p_vaddr |
segment的va,也就是VMA |
p_paddr |
segment加载到内存中的pa,一般pa和va一样,除非链接脚本单独指定,也就是LMA |
p_files |
segment在elf文件中所占空间的大小 |
p_memsz |
segment加载到内存中,所占的大小 |
p_flags |
segment的权限,RWX |
p_align |
segment的对齐要求。实际对齐字节等于2的p_align次方 |
通过readelf -l 可以查看程序头表信息
有2个segment
第一个segment: va是0x40_0000 pa是0x40_0000, 权限可读可执行, 包含了 .text 段
第二个segment: va是0x41_007c, pa是0x41_007c, 权限可读可写, 包含了.data和.bss 段
所以segment就是 section的集合,将相同权限,并且地址是连续的section,合并成一个segment,方便加载。
这样,就引出了链接视图与执行视图。
链接视图: 通过section来描述,也就是elf中section header table
执行视图: 通过segment来描述,也就是elf中的program header table
那么对于section,是如何映射到segment的呢?
以下是链接视图,可以看到各个section。
以下是执行视图,可以看到各个segment,以及segment集合的section。
每个section有VMA,每个segment也有VMA
如果一个section的VMA,属于一个segment的VMA范围内,那么该section会被合并到该segment
.text的VMA处于segment0的VMA范围内,因此划分到segment0
.data和.bss的VMA处于segment1的VMA范围内,因此划分到segment1
转载地址 http://www.lujun.org.cn/?p=4190
也欢迎访问我的个人网站 http://www.lujun.org.cn