动态链接的实现

来源:互联网 发布:广东问政网络平台 编辑:程序博客网 时间:2024/05/21 03:19

动态链接和静态链接不同,为了节省空间,在链接的时候,动态库只是将自己的符号表与可执行文件绑定在了一起生成了一个.o的可执行文件,真正的链接,实际上发生在程序运行实施装载的时候。
装载的时候,操作系统将动态链接器加载完后(动态链接器也是一个共享对象),就将控制权交给动态链接库器的入口地址。当动态链接器得到控制权后,它就开始将自身进行初始化,然后根据当前的环境参数,对可执行文件进行动态链接工作。当所有的动态链接工作结束了之后,动态链接器会将控制权交给可执行文件的入口地址,程序真正开始执行。

动态链接的实际链接步骤主要分下面三步:
1. 启动动态链接器本身
2. 装载所有需要的共享对象
3. 重定位和初始化

一、启动动态链接器本身

由于动态链接器本身就是一个共享对象,那么它的重定位的工作由谁来完成呢?所以,动态链接器必须有它的特殊性
1. 动态链接器本身不可以依赖于其他任何共享对象
2. 动态链接器本身所需要的全局和静态变量的重定位工作由自身完成

了达到这些要求,动态链接器首先应不使用任何系统库、运行库;对于第二个条件,动态链接器必须在启动时有一段代码可以完成这项任务同时又不用到任何的全局和静态变量。这种具有一定限制条件的启动代码被称为自举。
自举代码先找到动态链接器本身的“.dynamic”段,通过段中的信息,自举代码便可以获得动态链接器本身的重定位表和符号表,从而得到动态链接器本身的重定位入口,然后进行重定位。
这一步结束后,动态链接器才开始可以使用自己的全局变量和静态变量。

二、装载所有需要的共享对象

完成基本的自举之后,动态链接器可执行文件和链接器本身的符号表都合并到一个符号表当中,称为 全局符号表 ,然后链接器开始寻找可执行文件所依赖的共享对象。并将所有共享对象的符号表合并到全局符号表中。若共享对象还依赖于其他的共享对象,就将其他的共享对象添加进符号表,直到全部完成,(如果将依赖关系看成一个图的话,那么这个装载过程就是一个图的遍历过程,一般使用广度优先)

三、重定位和初始化

当上面的步骤结束之后,链接器开始重新编遍历可执行文件和每个共享对象的重定位表,将他们的GOT(全局偏移表)/PLT(延迟绑定)中的每个需要重定位的位置进行修正(根据全局符号表)。
重定位完成之后,如果某个共享对象有“.init”段,那么动态链接器执行“.init”段的代码,用以实现共享对象特有的初始化过程。
可执行文件中的“.init”段链接器不会去执行,因为这些由程序初始化部分代码负责执行。

当完成了重定位和初始化后,所有的准备工作就完成了,所有的共享对象都装载完成并且链接好了。这时候链接器就会将控制权转交给程序的入口开始执行。

       2017/04/21 20:27 
1 0
原创粉丝点击