对elf文件连接的理解(一)-重定位概述
来源:互联网 发布:java 时间控件 编辑:程序博客网 时间:2024/05/24 20:06
一.首先分析一下为什么需要重定位(暂时不考虑fpic代码,动态链接库等复杂情况)
这里举一个简单的例子,如下a.c中代码如下
int a ;int test(){ a = 1; return 0;}编译生成目标文件a.o,再经过与带有main函数的模块连接之后生成可执行文件,则可运行了;但是在这里要考虑一个问题,当编译a=1这一赋值语句时要知道a的地址,才能编译出相应的代码.但是在链接之前,明显a的地址是不能确定的.所以编译器在编译该段代码时会针对a=1这一对a发生引用的地方记录一个重定位信息(包括其在当前section中的offset,关联的符号,重定位类型).这样在链接时,首先算出确定所有符号的地址,然后根据重定位信息找到要修改相应的位置,再根据已经确定的符号地址算出实际要填入的值,然后修改对应位置.
如果没有重定位过程,则再编译a.c到a.o的过程中,a变量的地址可能是随机指定的,如0.可是当a.o与其他模块链接后,最终a的地址可能被定义到0x100.则在生成的可执行文件中,若不对对应位置进行修改,则明显会出错.
二.哪些地方会发生重定位,各有什么特点
在代码中,甚至在数据中(例如a=&b),都有可能需要重定位.下面分析一下各种情况.
1.在代码段中,例如上面的test函数引用变量a,这里需要生成重定位记录,以便链接器链接后来修改.具体还有几种情况
1.1 对函数,变量的引用(注意这里是对函数符号的引用,如a = (int)printf)
1.1.1 对静态函数或变量的引用
1.1.2 对全局函数或变量的引用
1.2对函数的调用(体会与引用的区别,若是引用,则要重定为函数的绝对地址,若是调用则不一定,与平台有关,在x86下是e8+偏移值,所以改成的不是绝对地址)
1.2.1 对全局函数的调用
1.2.2 对静态函数的调用
2.在数据段中,分为两种情况
2.1 对静态函数或变量的引用
2.2 对全局函数或变量的引用
三.重定位的时机
其实重定位的实际不止在ld链接时,还发生在加载器(ld-linux.so加载相应模块时.所以一个是链接时,一个是加载时.
四.为什么要区别不同的重定位类型
1.为什么要区分区域,分成代码区和数据区重定位
首先,代码区重定位可以转化为数据区重定位,通过在数据区添加一个变量和函数的地址存储区域.将每个代码区重定位转移为数据区重定位(后面再具体分析),这样有什么好处呢.这里得提到动态库,大家知道动态库的好处是可以在物理内存中只有一份拷贝,然后映射到不同的进程的地址空间,可是.so文件如果存在重定位项,则加载器在加载.so文件到每个进程空间时会发生重定位(这里的重定位时机在加载时),这时便要修改.so文件的很多地方,包括代码段和数据段,这样麻烦就来了,因为存在写时复制,会为每个进程产生一个拷贝,这样.so库的优点就荡然无存了,所以这时候在数据区开出一个固定的区域,将重定位项集中到该区域,则问题便解决了.这有就是fpic代码的实现方法.
- 对elf文件连接的理解(一)-重定位概述
- 对elf文件连接的理解(二)-简单的重定位类型
- ELF文件重定位
- 可重定位的ELF文件(续)
- 典型的ELF可重定位目标文件
- 典型的ELF可重定位目标文件
- 典型的ELF可重定位目标文件
- linux下elf重定位理解
- Linux 可重定位文件 ELF结构
- ELF格式的重定位原理分析
- ELF重定位分析
- ELF重定位简介
- 重定位的理解
- ELF函数重定位问题
- 对定位的理解
- ELF(七)可重定位目标,部分摘自深入理解操作系统,深入理解linx内核
- Bfd对elf文件头的处理
- 可执行文件---prelink对ELF文件的影响
- Android 与 iOS 持久化 Http Cookie
- 深拷贝详解
- C++构造函数详解
- 源码,反码,补码,二进制 反码求和
- 利用pull方式进行xml文件查看天气
- 对elf文件连接的理解(一)-重定位概述
- OpenCV Machine Learning 之 K最近邻分类器 K-Nearest Neighbors
- MFC hook注入dll,远程线程注入dll
- 一种经典的网络游戏服务器架构
- WPF Control event 触发
- xml基础训练
- 歧路亡羊
- poj 3167 Cow Patterns(kmp)
- ecshop属性筛选时,同一属性名下,不同属性值的排序问题