目标文件
全局变量和局部静态变量在数据段即.data
未初始化的全局变量和局部静态变量在.bss段
elf文件
- 可重定位文件 被ld成可执行和共享目标文件 静态链接库是这一类 .a(目标文件集合用于静态链接) .o(目标文件)
- exe
- 共享目标文件 .so
段
readelf -s 查看段表
段的类型:
- 程序,代码,数据段 SHT_PROGBITS
- 符号表段 SHT_SYMTAB **
- 字符串表段 SHT_STRTAB .strtab/.shstrtab 字符串表和段表字符串表
- 重定位表 SHT_RELA ** 该段所使用的符号表在段表中的下标 该重定位表所作用的段在段表中的下标
- 动态链接信息 SHT_DYNAMIC **
- 动态链接的符号表 SHT_DNYSTM ** 该段所使用的字符串表在段表中的下标
- 重定位信息 SHT_REL ** 该段所使用的符号表在段表中的下标 该重定位表所作用的段在段表中的下标
.rel.text 链接器在处理目标文件时要重定位,记录重定位信息 针对.text段的重定位表
标**都代表与链接有关。
分别代表sh_link,sh_info
strip去除调试信息
ld
ld时会生成shstrtab symtab strtab
可以ld -s
禁止产生符号表
out格式
静态链接
目标文件被链接成最终可执行文件时,
- 输入的各个段合并
- ld分配在输出文件中的空间和地址
- 输入端的最终地址确定后 进行符号的解析和重定位
segment
相同权限的段被合并到一个段映射变成Segment
,Segment
是执行视图,Section
是链接视图
动态链接
静态链接将整个文件作为一个整体映射到虚存。而动态链接其实还是分模块, 尤其是动态链接器也作为一个模块映射到虚存,程序开始后先完成所有的动态链接工作。用/proc/maps查看可以看到主程序和共享模块分布在不同的地址中。
重定位
静态链接的重定位叫链接重定位,动态链接的重定位叫装载重定位。对于动态链接的共享库而言,它假定自己装载时在0x1000,如果正式装载时在0x3000那么所有绝对引用集体加0x2000即可。当然动态链接也可以用静态链接的方式,但这样就做不到共享了,因为要改指令部分,不同进程因为虚存的存在不可能同时改一份代码的指令。(数据拷贝共享)
--shared
是否用装载重定位方式。
-fPIC
动态链接作为多个进程共享模块,所以需要解决前面提到的不同进程因为虚存的存在不可能同时改一份代码的指令的问题。
首先模块内的数据指令不用考虑,用相对访问即可。问题在于模块间的数据访问,需要把跟地址相关的部分放到数据段里面,在数据段里建立一个指向这些变量的指针数组got(全局偏离表),got
在数据段中,互不影响(因为每个进程独立副本啊)
所以很简单访问got写入读取最终需要访问的绝对地址即可。
ps: 分析上层累了, 纯记录自己的学习。
网友评论