ELF 文件 动态链接 - 地址无关代码(GOT)
Linux 系统中,ELF动态链接文件被称为 动态共享对象(DSO,Dynamic Shared Object),简称共享对象
文件拓展名为“.so”
动态链接下 一个程序可以被分成若干个文件:程序的主要部分 - 可执行文件 和 程序所依赖的共享对象(一个或多个.so文件),它们都可称作为程序的模块。
动态链接文件(共享对象)的装载地址为0x00000000;这并非工作时的实际地址,实际地址由装载器根据当前进程地址空间的空闲情况来动态分配一块足够大的虚拟地址空间给共享对象。
装载时重定位
基本思路:在链接时对所有的绝对地址的引用不作重定位,而把这一步放在装载时完成。一旦模块装载完成,既目标地址确定,那么系统将对程序中的所有绝对地址的引用进行重定位。
静态链接时的重定位称为 链接时重定位(Link Time Relocation)
动态链接时的重定位称为 装载时重定位(Load Time Relocation) gcc -shared
然而光有装载时重定位也不能解决所有问题,因为对于动态链接文件来讲,它时可以分为可修改数据部分和不可修改数据部分,如果只有装载重定位,那每个程序必须都有一个共享对象的副本,这样会很浪费内存
这样就引入来下一个话题
地址无关代码 (gcc -shared -fPIC)
基本思想: 把指令中需要被修改的部分分离出来,跟数据部分放在一起,这样指令部分就保持不变了,而数据部分为每个进程都有一个副本,
这就是地址无关代码(PIC, Position-independent Code)技术
共享对象模块内的地址引用分为四种情况:
1. 模块内部调用或跳转:
它们之间位置固定,使用相对地址调用。
2. 模块内部数据访问
同样使用相对寻址(使用当前(指令地址)PC + 偏移量)
3. 模块与模块之间的数据访问(重点)
模块之间的数据访问,其目标地址需要等到装载后才能确定。
这里的基本思想时将这部分与地址相关的指令的当前地址放入到数据段里面。
ELF 的做法是在数据段中建立了一个 指向这些变量的指针数组 ,也被称为 全局偏移表(GOT, Global Offset Table),当代码需要引用该全局变量时,通过GOT间接引用,
即GOT中记录着该外部函数真正的地址,装载器在做动态链接时,会查找每个外部符号的地址,然后填充到GOT的对应的项中。
GOT 如何做到与指令无关的呢?(在.so 文件中对应 .got 段)
1. 模块在编译期可以确定模块内部变量相对与当前指令的偏移,同样在编译期也可以确定GOT相对于当前指令的偏移。确定GOT的位置和确定内部变量的位置方法上时一样的,通过
得到PC值然后加上一个偏移量即可得到GOT的位置。当然GOT中的每个地址对应于哪个符号(变量,函数都是符号)由编译期决定。
4. 模块间跳用和跳转
此时与3.中方法类似,只是对应的GOT的位置保存的时目标函数的地址,通过GOT实现间接跳转
地址无关小结:
| 各种引用方式 | ||
| 指令跳转和调用 | 数据访问 | |
| 模块内部 | 相对跳转调用 | 相对访问 |
| 模块外部 | GOT间接跳转访问 | GOT间接跳转访问 |
ELF 文件 动态链接 - 地址无关代码(GOT)的更多相关文章
- 实例分析ELF文件动态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第6章 可执行文件的装载与进程 第7章 动态链接 <Linux GOT与PLT> 开发平台 ...
- Cortex-M3 动态加载一(地址无关代码实现)
这篇文章是自己疑惑究竟地址无关性是如何实现,然后查看汇编和CPU指令手册,最后分析解除自己疑惑的,高手不要鄙视,哈哈. 编译C代码时候需要制定--acps/ropi选项,如下例子: void Syst ...
- 实例分析ELF文件静态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第4章 静态链接 开发平台: [thm@tanghuimin static_link]$ uname ...
- (九)ELF和动态链接
前言: 我们都知道我们所写的程序是被编译为一条条的CPU指令去执行的,但是在linux系统下能够运行的程序在windows环境下却运行不起来,但是我们使用的CPU明明是一样的,这又是为什么呢? 一.程 ...
- ELF 文件 动态连接 - 延迟绑定(PLT)
PLT 全称:Procedure Linkage Table ,直译:过程连接表 由于在动态连接中,程序的模块之间包含了大量的函数引用,所以在程序开始执行前,动态链接会耗费较多的时间用于模块之间函数引 ...
- Delphi通过Map文件查找内存地址出错代码所在行
一 什么是MAP文件 什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持.而且,这是唯 ...
- 问题-[Delphi]通过Map文件查找内存地址出错代码所在行
一 什么是MAP文件 什么是 MAP 文件?简单地讲, MAP 文件是程序的全局符号.源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方.任何时候使用,不需要有额外的程序进行支持 ...
- ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)
加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: ...
- ELF 动态链接 - so 的 重定位表
动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用.而在编译时期这些导入符号的确切地址时未知的.只有在运行期才能确定真 ...
随机推荐
- Python图片处理库之PIL
这个模块对于Python2.7 的windows64位电脑而言,还真的是不好找啊.这里分享一个下载链接吧,需要的朋友可以下载下来.PIL For Windows64 Python2.7下面分享一下这个 ...
- 1079. Total Sales of Supply Chain (25) -记录层的BFS改进
题目如下: A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyon ...
- [ExtJS5学习笔记]第二十二节 Extjs5中使用beforeLabelTpl配置给标签增加必填选项星号标志
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39395753 官方例子:http://docs.sencha.com/extjs/5. ...
- 【并发编程】AIDL关键字
oneway Oneway interfaces In early betas, the Android IPC was strictly synchronous. This means that s ...
- 当图片验证码遇上JSP
今天看到了一个关于使用JSP方式生成图片验证码 的小例子,感觉真的是很不错,拿来分享一下. 原理 对于图片验证码,我们在审查元素的时候会方便的看出是<img src="#" ...
- 编译GDAL使用最新的HDF库配置文件
HDF库最新版本中的动态库以及目录结构都发生了变化,导致按照之前的博客进行编译GDAL时,会出问题.使用HDF4版本为HDF4-4.2.10,HDF5的版本为HDF5-1.8.12.两个库的目录结构如 ...
- J2EE进阶(九)org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session 前言 在<many-to-o ...
- Servlet读取文件的最好的方式
在java web 开发的时候不可避免的会读取文本信息,但是方式不同,所付出的代价也是不一样的,今天学到了一个比较好的实用性的技巧,拿来与大家分享一下. 读取属性配置文件 之所以说成是读取属性(pro ...
- (七十)Xcode5及以上对于状态栏和导航栏样式的设定方法
[状态栏] 在Xcode5以前,状态栏是通过UIApplication单例来管理的,而在此后,默认情况下状态栏通过控制器来管理,而且如果控制器有NavigationController,那么设置状态栏 ...
- 小老虎的微信公众号:iITObserve
小老虎的微信公众号:iITObserve 现在,都流行玩微信. 现在,都流行玩微信公众号. 所以,博客已经Out啦! 原来是微博,现在是微信.真的,时代发展太快了. 偶赶紧也弄了一个,尝尝鲜. 偶的微 ...