动态链接(2): 全局偏移表
1 相关符号表及结构
- 动态链接器(.interp)
- 链接所需要信息:.dynamic段
- 动态符号表(.dynsyms)
- 动态链接重定位表
- 过程链接表(PLT)
- 全局偏移表(GOT)
2 动态链接器
2.1 interp段
- 该段存放一个字符串,用于指明动态链接器的路径
- 查看.interp段内容:
arm-linux-gnueabi-objdump –s a.out
# 如 /lib/ld-linux.so.2
2.2 动态链接器
- 跟动态链接库一样,本质也是一个共享库
- 在运行之前,要首先给自己进行重定位:自举
- 在C标准库中实现,是Glibc的一部分
3 .dynamic段
保存了动态链接器所需要的基本信息:
- 依赖于哪些共享库
- 动态链接符号表位置
- 动态链接字符串表的位置
- 动态链接重定位表位置
- 共享库初始化代码位置
查看.dynamic段内容:
readelf –d xx.so
4. 动态链接符号表
4.1 dynsyms section
- 静态链接的符号表保存了该文件所有的符号定义及引用
- 动态链接的符号表只保存动态链接的符号
- 查看动态链接符号表:
readelf –s a.out
4.2 动态链接字符串表
- 动态链接符号表的辅助表,存储符号名
- 符号表.symtab对应.strtab
- 动态链接符号表.dynsym对应.dynstr
4.3 符号哈希表
- 动态链接文件,提高程序运行查找符号速度
- 静态链接无此段
- 查看字符串表:$ readelf –sD a.out/xx.so
5 动态链接重定位表
- 包括.rel.dyn和.rel.plt
- .rel.dyn用于描述数据段的重定位信息
- .rel.plt用于代码段的重定位信息
- 重定位表中的地址偏移为各个未定义符号在GOT表中的地址
查看重定位表:
readelf -r xx.so
6 过程链接表
- 使用.plt后缀,内容是一个跳转命令,跳到GOT对应的项
- 过程链接表无法单独工作,跟GOT是关联的
- 当引用某个符号时,会从PLT表跳转到GOT表
7 延迟绑定PLT
7.1 动态链接对性能的影响
寄存器间接寻址
程序运行之前的动态链接、重定位
7.2 延迟绑定
当函数第一次用到时才进行绑定
ELF就是采用PLT的方式来实现
7.3 最终形式
动态链接:节省内存
延迟绑定:提高运行速度
8 全局偏移表
8.1 got表
GOT: Global Offset Table
每一个引用外部模块定义的符号在GOT表中有相应的条目
.got:编译器将对外部引用(绝对地址)的符号全部分离出来放到该表中
9 重定位过程
9.1 修改全局偏移表GOT
- 第一次调用使用PLT表跳转,跳到GOT,再跳到动态链接器
- 动态链接器链接共享库、重定位、修改GOT表符号真实地址
- 第二次调用,直接从GOT表中跳转到符号真实地址,执行函数