ARM Architecture C 语言寻址解析——
从U-Boot relocation所展开的探索(三)
by蔡于清
ARMArchitecture C语言PIC寻址方式解析(续)
继
续讨论上一篇文章的问题,GOT所记录的是C的对象地址,但一个工程中往往还存在汇编代码定义的变量(事实上汇编语言中并不存在“变量”这一说法,这些所
谓的“变量”更准确的讲是一个"Lable",C语言的指针变量名,比如main.c中定义的global_str,对汇编来说也是一个Lable,在接
下来的文章里我们统一用Lable称呼这两者),如何对汇编的Lable进行relocate呢?如何得到需要relocate的Lable信息呢?命令
行进入arm_pic目录,运行命令arm-none-eabi-readelf-r
arm_pic,得到以下输出:
“arm-none-
eabi-readelf”是一个分析elf文件的工具,使用“-r”选项可以列出所有需要relocate的Lable信息。观察上图“offset”
列的数据,配合arm_pic.dump,我想读者应该发现,0x40200020是Lable“_undefined_instruction”的
地址,0x40200024是Lable"_software_interrupt"的地址(这两个Lable是在汇编文件start.S中定义的),没
错,所有在汇编语言中定义的Lable,都可以在这个输出中查看到它们的地址,更甚者,C语言GOTentry的地址也都被列出。那么上面输出的这些数据
保存在elf文件中的哪个section呢?——它们被保存在.rel.dynsection(.rel.dyn
section由连接时为ld指定-pie选项产生),如下图所示:
.rel.dyn section由若干.rel.dyn entry组成,一个entry记录了一个Lable的信息(ELFstandard定义.rel.dyn entry 为ELF32_Rel结构体,具体内容请参考ELF standard 和),如上图所示,第一个entry记录了Lable"_undefined_instruction"的信息,其地址为0x40200020,relocatetype为R_ARM_RELATIVE。无论汇编语言定义的Lable或是C语言定义的Lable,只要得到该Lable的.rel.dynentry,就可以对其进行relocation。
如上一篇文章所讲,arm_pic被整体copy到0x80000000地址后,将GOT中每一个entry的内容累加上偏移量0x3fe00000,这样还不能让其正常地从新地址中运行(修改GOTentry只解决了C变量的relocation),完美的做法是——遍历.rel.dyn section,将每一个entry所指地址中的值加上偏移量,这样无论汇编定义的Lable,还是C定义的Lable,所有的Lable都被relocation,U-Bootrelocation使用的就是这种方法。
U-Boot 2011.12relocation分析
事实上u-boot
2011.12并没有使用到“-fpic”或“-fpie”编译选项,只用到“-pie”连接选项,指定了“-pie”连接选项所产生的elf文件包含
了.rel.dynsection,U-Boot 2011.12 relocation只需借助.rel.dyn提供的信息就足够了。
上图的代码可在 /u-boot-2011-12/arch/arm/cpu/armv7/start.S中找到,这段代码用于完成U-Boot
2011.12
relocation。“fixloop”循环遍历.rel.dynsection,“fixabs”和"fixrel"分别
relocate"R_ARM_ABS32"和“R_ARM_RELATIVE”两种类型的Lable,其中,“R_ARM_ABS32”类型的
Lable在relocate的时候还需要引用到.dynsymsection的数据,而“R_ARM_RELATIVE”的处理则简单许多,只需在原地
址值的基础上加上offset即可。
现在还有以下这3个问题:
- .dynsym section包含什么数据?
- "R_ARM_ABS32"和“R_ARM_RELATIVE”的区别是什么?
- "R_ARM_ABS32"和“R_ARM_RELATIVE” relocate的具体细节是什么?
我想这3个问题就留给读者自己去研究吧:)
全文完
阅读(2302) | 评论(0) | 转发(0) |