Elf32|Elf32 文件重定位研究(二)
【Elf32|Elf32 文件重定位研究(二)】前面已经说过,elf目标文件如果要链接成可执行文件,那么需要经过符号解析和重定位,才能变成一个可执行程序。那么对于一个elf目标文件,应用程序能否动态加载他,并调用里面的内部函数去执行,答案是可以的。具体应该如何做,下面来看一下。
应用程序动态加载elf目标文件,先把该文件读到内存中,获取目标文件elf头得信息,得到elf文件sections得起始地址,获取各个section信息。然后根据section中得信息,得到核心代码和核心数据得位置,重新分配一块内存,把核心代码和核心数据加载到该内存,这个时候就要根据加载地址,对该elf文件进行符号解析和重定位了。
elf文件中有许多section,对于符号解析,和重定位相关的比较重要的section是rel开头的可重定位section和符号表sym section。
重定位表,是一个由许多重定位表项组成的数组。
下面是ELF里面重定位项的结构:
struct elf32_rel {
Elf32_Addrr_offset;
Elf32_Wordr_info;
//SYMBOL<<8+TYPE&0xff.
} ;
r_offset是代码中需要进行重定位的地址;
r_info 是符号表中该符号的索引;
符号表,是由许多符号表项组成的数组。
下面是“符号表项”的结构:
struct elf32_sym{
Elf32_Word st_name;
//index into the symbol string table
Elf32_Addr st_value;
Elf32_Word st_size;
//size of the symbol. 0 for no size or unkown size
unsigned char st_info;
//BIND<<4+TYPE&0x0f
unsigned char st_other;
//0 for reserve
Elf32_Half st_shndx;
//relevant section table index, some indicates special meanings
};
St_name是符号的名称,该值在字符串表中得的index
St_value是该符号在内存中的地址
st_size是该符号的大小,以字节为单位
st_shndx是符号所在的section的index
符号的名称,是由st_name和符号名表决定。St_name是一个指向符号名表的索引值,通过“符号名表基地址”+st_name就可以得到符号名的地址。
之所以采用这种方法,是为了处理“变长”的符号名。
符号的值(也就是符号在内存中的地址,我们要计算的东西)是由st_value和st_shndx决定的。
在relocatable文件中,st_value是符号相对于某个section起始地址的偏移,这个section是由st_shndex指定的(COMMON类型的section除外,它很少会被用到)。
在executable和shared object文件中,st_value包含一个虚拟地址。这个地址是和ELF文件的预定装载地址联系在一起的。在进行动态链接时,我们需要计算“当前装载地址”与“预定装载地址”之间的差。
1 符号解析
把核心代码加载到内存中以后,该加载地址就是这段代码得运行地址,这时符号表中记录的符号的地址显然是不对的,而且符号表中还有未定义的符号,需要为这些未定义符号填写正确的外部函数地址。所以这边可以遍历符号表,对于全局符号,修改其符号表的值,更正为该符号在内存中的真实地址,未定义符号,为其填写真实的外部函数地址
2 重定位
根据上面的动作,符号表已经修正完毕,但是核心代码段里面的数据还是没有改变的,代码最终执行的时候不会依赖符号表,所以需要遍历重定位section,把需要进行重定位的符号,在核心代码中为其纠正过来。
根据重定位表中的r_info信息在sym section中找到该符号,根据st_value得到该符号在ram中的真实位置,然后根据重定位表中的r_offset 得到该重定位代码在内存中的真实地址,利用st_value修改该重定位代码的寻址地址,完成重定位
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 2.6|2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
- 我们重新了解付费。
- 人间词话的智慧
- 螃蟹和这些食物同吃,轻则腹泻、重则中毒!要小心哦~
- django-前后端交互
- 如何在Mac中的文件选择框中打开系统隐藏文件夹
- java中如何实现重建二叉树
- 使用composer自动加载类文件
- 2019-03-27健康减肥126天