程序员的自我修养(十一) -- 动态链接步骤和实现

动态链接的步骤
  1. 启动动态链接器本身
  2. 装载所有需要的共享对象
  3. 重定位和初始化
动态链接器自举

动态链接器本身也是一个共享对象,但是它有一些特殊性:

  1. 动态链接器本身不可以依赖其他任何共享对象
  2. 动态链接器本身所需要的全局和静态变量的重定位工作由它本身完成==》这一点就用到了自举

自举是什么?
它是一种具有一定限制条件的启动代码

动态链接器的入口地址即自举代码的入口,当操作系统将进程控制权交给动态链接库时,动态链接库的自举代码即开始执行。

自举步骤:

  1. 先找到自己的GOT【GOT第一个入口保存的是.dynamic段的偏移,从而得到动态链接器本身的重定位表和符号表等】
  2. 得到动态链接器的重定位入口,先根据重定位表和符号表进行重定位
  3. 动态链接器在这时候才可以使用它自己的全局变量和静态变量

在GOT/PLT没有被重定位之前,自举代码不可以使用任何全局变量,也不可以调用函数。

装载共享对象
  1. 完成基本的自举之后,动态链接器将可执行文件和链接器本身的符号表都合并到一个符号表中,称之为 全局符号表
  2. 链接器寻找可执行文件所依赖的共享对象【链接器可以列出可执行文件所需要的所有共享对象,并将这些共享对象的名字放到一个装载集合中】
  3. 链接器从装载集合里取一个所需要的共享对象的名字,找到相应地文件后打开该文件
  4. 读取相应ELF文件头和“.dynamic”段,然后将它相应地代码段和数据段映射到进程空间【如果这个ELF共享对象还依赖于其他对象,那么将所依赖的共享对象的名字放到装载集合中,循环3–4,直到所有的依赖的共享对象都被装载进来位置。==》这个过程可以比作图的遍历,装载顺序并不一定唯一】

当一个新的共享对象被装载进来的时候,它的符号表会被合并到全局符号表中。【所以,所有的共享对象被装载完之后,全局符号表里面将包含进程中所有的动态链接所需要的符号】

共享对象全局符号介入:一个共享对象里面的全局符号被另一个共享对象的同名符号覆盖的现象

Linux动态链接处理共享对象全局符号介入的问题:当一个符号需要被加入全局符号表时,如果相同的符号名已存在,则后加入的符号被忽略。

重定位和初始化
  1. 上面的两大部分完成后,链接器开始重新遍历可执行文件和每个共享对象的重定位表,将它们的GOT/PLT中的每个需要重定位的位置进行修正。【这个时候已经有全局符号表了,以此为据,修正起来会相对简单一点】
  2. 重定位完成后,如果某个共享对象有“.init”段,动态链接器会执行“.init”段中的代码,以实现共享对象特有的初始化过程
  3. 相应地,如果共享对象中有“.finit”段,进程退出的时候回执行“.final”段中的代码【可以用来实现类似C++全局对象析构之类的操作】
  4. 注意:可执行文件中的“.init”段和“.finit”段并不在这里执行【它们由程序初始化部分代码负责执行】

当完成重定位和初始化之后,所有的准备工作就宣告完成了,并且所需要的共享对象也都已经装载&&链接完成了,链接器就将进程的控制权限转交给程序的入口,并开始执行。

在这里插入图片描述

动态链接库使用

运行时加载,也叫显示运行时链接:让程序自己在运行时控制加载指定的模块,并且可以在不需要该模块的嘶吼将其卸载。

Linux下常用的几个动态链接库相关的函数:
  • dlopen()
  • dlsym()
  • dlerror()
  • dlclose()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值