为什么要动态链接
动态链接可以节省内存和磁盘空间,便于程序的开发和发布。
动态链接是把链接这个过程从本来的程序装载前被推迟到了装载的时候。
动态链接文件的最终装载地址在编译时是不确定的。
地址无关代码
固定装载地址产生干扰
装载时重定位:
进行基址重置(Rebasing)
但是由于装载时重定位的方法需要修改指令,没有办法做到同一份指令被多个进程共享,因为指令被重定位后对于每个进程来说是不同的。
当然,动态链接库中的可修改数据部分 对于不同的进程来说有多个副本,所以它们可以采用装载时重定位的方法。
代码中的四种类型的地址引用方式有:
一,模块内部的函数调用,跳转等。
采用相对跳转和调用
二,模块内部的数据访问,比如模块中定义的全局变量,静态变量。
采用相对地址访问
三,模块外部的函数调用,跳转等。
采用间接跳转和调用(GOT)
GOT(Global Offset Table): 全局偏移表。
链接器在装载模块的时候会查找每个变量所在的地址,然后填充GOT中的各个项,以确保每个指针所指向的地址正确。由于GOT本身是放在数据段的,所以他可以在模块装载时被修改,并且每个进程都可以有独立的副本,相互不受影响。
四,模块外部的数据访问,比如其他模块中定义的全局变量。
采用间接访问(GOT)
动态链接的步骤
一,启动动态链接器本身;
二,装载所有需要的共享对象;
完成基本自举后,动态链接器将可执行文件和连接器本身的符号表都合并到一个符号表当中,称为“全局符号表(Global Symbol Table)”.
三,重定位和初始化。