引用动态链接库的原理

位置无关代码

可以架在你而无需重定位的代码成为位置无关代码(Position-Independent Code,PIC)。用户对GCC使用-fpic选项指示GNU编译系统生成PIC代码。动态链接库的编译必须总是使用该选项。

在x86-64系统中,对同一个目标模块中符号的引用是不需要特殊处理使之成为PIC。可以用PC相对寻址来编译这些引用,构造目标文件时由静态链接器重定位。然而,对动态链接库定义的外部过程和对全局变量的引用需要一些技巧。

PIC数据引用

无论我们在内存中何处加载一个目标模块,数据段与代码段的距离总是保持不变。因此,代码段中任何指令和数据段中任何变量之间的距离都是一个运行时常量,与代码段和数据段的绝对内存位置是无关的。

所以想要生成对全局变量PIC引用,可以在数据段开始的地方构造一张全局偏移量(Global Offset Table,GOT)。在GOT中,每个被这个目标模块引用的全局数据都有一个由编译器生成的重定位记录。在加载时,动态链接库会重定位GOT中的每个条目,使它包含目标的正确的绝对地址。运行的时候,根据数据段和代码段之间距离保持不变的特点,使用PC相对引用得到GOT表中的绝对地址即可。

PIC函数调用

假设程序调用有一个动态链接库定义的函数。编译器无法预测这个函数的运行时地址,因为定义它的共享模块再运行时可以加载到任意位置。GNU编译系统使用一种称为延迟绑定的技术将过程地址的绑定推迟到第一次调用该过程时。

使用延迟绑定的动机是对于一个像libc.so这样的动态链接库中包含很多函数,而一个应用程序往往只会使用到其中的小部分。把函数地址的解析推迟到它实际被调用的地方,能避免动态链接库在加载时对没有使用的函数进行不必要的重定位。第一次调用过程运行时开销很大,但是其后的每次调用只会花费一条指令和一个间接的内存引用。

延迟绑定技术使用到两个数据结构:

  1. 过程链接表(PLT)。PLT是一个数组,其中每个条目是16字节代码。PLT[0]是一个特殊条目,它跳转到动态链接库中。每个被可执行程序调用的库函数都有它自己的PLT条目。每个条目都负责调用一个具体的函数。
  2. 全局偏移量表(GOT)。GOT是一个数组,其中每个条目是8字节地址。和PLT联合使用时,GOT[0]和GOT[1]包含动态链接器在解析函数地址时会使用的信息,GTO[2]是动态链接器在ld-linux.so模块中的入口地址。其余的每个条目对应一个被调用的函数,其地址需要在运行时被解析,每个条目都有一个相匹配的PLT条目。

上图展示了,延迟绑定的具体步骤:

  1. 代码段中调用addvec函数,指令跳转到PLT[2],这是addvec函数的PLT条目。
  2. 接着,指令跳转到GOT[4]指向的地址,GOT[4]中应该包含addvec函数的地址。但是第一次进入时,GOT表中没有addvec的地址信息,只是简单地控制传送回PLT[2]中的下一条指令。
  3. 在把addvec的ID压入栈中只有,PLT[2]跳转到PLT[0]。
  4. PLT[0]通过GOT[1]把动态链接库的一个参数压入栈中,然后通过GOT[2]间接跳转进动态链接器中。动态链接库使用两个参数来确定addvec的运行时位置,并将addvec的地址写入GOT[4]中,再把控制传递给addvec。

参考书籍:《深入理解计算机系统(第三版)》

引用动态链接库的原理相关推荐

  1. 毕业论文中引用方法、原理、定义等 如何降重才更有效果?

    论文重复率过高是一件很痛苦的事,我当年的本科论文,一共查了四遍才过. 我的查重方法其实比较简单,初稿出来以后我就开始查重了,然后按照标注把标红的部分全部修改掉,而后以此类推,每次改外,或者觉得没问题了 ...

  2. python引用计数的原理_深入Python中引用计数

    在python中的垃圾回收机制主要是以引用计数为主要手段以标记清除和隔代回收机制为辅的手段 .可以对内存中无效数据的自动管理!在这篇文章,带着这个问题来一直往下看:怎么知道一个对象能不能被调用了呢? ...

  3. 智能指针shared_ptr引用计数工作原理

    引用计数原理 shared_ptr的实现是这样的:  shared_ptr模板类有一个__shared_count类型的成员_M_refcount来处理引用计数的问题.__shared_count也是 ...

  4. C++引用动态链接库

    因为要使用到C++的动态链接库,所以就特意网上找了一下资料实现了一下. 文章目录 一.lib与dll文件 二.创建dll文件 三.dll隐式链接 四.显式链接 五.小结 一.lib与dll文件 之前我 ...

  5. block引用外部变量原理

    block在赋值时才会生成对应的block结构体实例(结构体数据结构在编译时已经生成),赋值时会扫一遍里面引用的外部变量(嵌套block中的外部变量也算,只不过嵌套block中的外部变量会被内外两个b ...

  6. java 引用队列_Java中管理资源的引用队列相关原理解析

    当对象改变其可达性状态时,对该对象的引用就可能会被置于引用队列(reference queue)中.这些队列被垃圾回收器用来与我们的代码沟通有关对象可达性变化的情况.这些队列是探测可达性变化的最佳方式 ...

  7. axios 注册拦截器 cdn引用_CDN加速原理

    什么是 CDN CDN 全称是(Content Delivery NetWork,即内容分发网络.其目的是通过现有的 Internet 中增加一层新的缓存层,将网站的内容发布到最接近用户的网络 边缘 ...

  8. python像数常用函数_引用 象数疗法原理

    我们人体的阴阳,里面1个心外面一个舌,里面两叶肝外面两个眼,里面两叶肺外面两个鼻孔,里面两个肾外面两个耳,里面是阴外面是阳,八卦象数疗法配方中用0来平衡阴阳,偶数0是阴,奇数0是阳,00是阴,000是 ...

  9. DLL动态链接库的工作原理

    DLL动态链接库的工作原理 分类: VC++神奇理论2012-08-29 11:12 2635人阅读 评论(0) 收藏 举报 dll工作windowsexedelphimicrosoft " ...

  10. Dubbo原理和源码解析之服务引用

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

最新文章

  1. java学mybatis还用学jdbc吗,mybatis系统学习(二)——使用基础mybatis代替原始jdbc
  2. Android检查网络状态步骤
  3. python批量读取dbf_Python 读取DBF/FPT 文件
  4. Serverless Live | 9 大场景带你从零实践 Serverless
  5. python 设置横坐标刻度_python 双误差棒(上下误差棒)主刻度 副刻度
  6. AngularJS----服务,表单,模块
  7. Learning XNA 3.0翻译连载--序言
  8. Android系统各版本号及代号
  9. Oracle中使用SQL语句修改字段类型
  10. 计算机资源,来自verycd,排行榜
  11. 苹果手机录屏软件_一款“短小精悍的”手机录屏软件
  12. 俄罗斯方块,消消乐源码下载
  13. 什么?TTL信号也能高速稳定传输100m+?是的,你没有听错,量产电路推荐!
  14. 如何查看电脑CPU温度,笔记本温度显示怎么开启
  15. 设置图片在Unity中的默认打开方式
  16. Flash 实验 飞机爆炸
  17. Numpy、Pandas、SciPy、Scikit-Learn、Matplotlib的关系以及学习资料
  18. TPLinker实体关系抽取新范式TPLinker:单阶段联合抽取,并解决暴漏偏差~
  19. ip 地址在线解析, api
  20. 同名同姓查询,姓名查重,名字查重小程序,看看与你同名同姓的人有多少。

热门文章

  1. IAP之boot实现
  2. 一个程序员自媒体人的2017年终总结
  3. 解决笔记本更换固态硬盘,将机械盘放置光驱位后,机械盘休眠导致卡顿问题
  4. 【c++NOIP2015 普及组】 推销员
  5. 天翼云铸牢国云安全,护航千行百业
  6. CocCocoa Touch框架和Cocoa
  7. 2021 苟且活着,2022 向上生长
  8. WIN10桌面文件夹图标变黑解决方法~
  9. 北京大学网络教育学院计算机,北京大学继续教育部
  10. Windows远程提示“终端服务器超出了最大允许连接”