动态链接其实就是把链接的过程推迟到了运行时再进行。
特点
- 解决了共享的目标文件多个副本浪费磁盘和空间的问题
- 可以动态地选择加载各种程序模块【程序可扩展性和兼容性】
重定位
- 静态链接时的重定位–链接时重定位
- 装载程序时的重定位–装载时重定位,在Windows中又被称为基址重置
地址无关代码
目的:希望程序模块中共享的指令部分在装载时不需要因为装载地址的改变而改变。
-fPIC 与 -fPIE
模块中的几种地址引用:
- 模块内部的函数调用、跳转等【这种不需要重定位】
- 模块内部的数据访问,比如模块中定义的全局变量、静态变量【相对寻址】
- 模块外部的函数调用、跳转等【GOT,但是保存的是目标函数的地址】
- 模块外部的数据访问,比如其他模块中定义的全局变量【全局偏移表(Global Offset Table,GOT)–ELF在数据段里面建立了一个指向和本模块装载地址有关的其他模块的全局变量的指针数组】
共享模块的全局变量问题
动态链接比静态链接慢,原因?
- 动态链接下对于全局和静态的数据访问都要进行复杂的GOT定位,然后间接寻址;对于模块间的调用也要先定位GOT,然后进行间接跳转
- 动态链接的链接工作在运行时完成
延迟绑定(PLT)
基本思想:当函数第一次被用到的时候才进行绑定(符号查找、重定位等)
优点:加快程序的启动速度【针对上面原因的第二点】
这种方法使用了一些很精妙的指令序列来完成。
需要补充了解的知识
1、 指令寻址方式【汇编】