一,前言
既然是第二轮学习,当然要比第一轮增加深度,获取更多技能和通用方法论。之前我想通过代码关闭relocate功能,结果一尝试就复位了,看来没我想的简单,还是先了解下relocate的代码。
二,源码分析
调用前r0有传参为gd->relocaddr,也就是一个指针地址保存在r0。
arch/arm/lib/crt0.S
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
relocate_code的整个过程分析,关于我的理解都添加了注释。
arch/arm/lib/relocate.S
ENTRY(relocate_code)
relocate_base:
adr r3, relocate_base /* 读取运行地址到r3 */
ldr r1, _image_copy_start_ofs /* _image_copy_start和relocate_base的地址差保存到r1 */
add r1, r3 /* 运行时的_image_copy_start地址保存到r1 */
/* 这里说下,要获取运行时候地址正常来说是可以直接读,但是_image_copy_start是编译时候的一个变量值,这个变量值代表了一个地址,所以才要用这样的方法 */
subs r4, r0, r1 /* gd->relocaddr的指针地址,再减去运行时候_image_copy_start_ofs的值,获取差值,是relocate要修改的offset值 */
beq relocate_done /* 若差值为0就不做重定向了 */
ldr r1, _image_copy_start_ofs
add r1, r3 /* r1 relocaddr)中,由于r1是源,然后源地址加加后直到与r2地址值一样,就停止copy了。而r1是运行时的image_copy_start,r2是image_copy_end,这样就完成了uboot的重定向copy */
/* 根据u-boot.lds__image_copy_end后紧接着就是__rel_dyn_start,而这段是重定向的关键,但是内容不做迁移,仅对内容值做修改 */
/*
* fix .rel.dyn relocations
*/
ldr r1, _rel_dyn_start_ofs
add r2, r1, r3 /* r2 relocaddr地址的,而这个地址和编译生成的地址的offset保存在r4,所以r0需要加r4,接下来就是写值了,看起来是提取2个值,但是写入的新值仅1个,猜测已经够了,应该是23不需要再写入了。*/
ldr r1, [r0] /* 把r0地址中的值保存到r1 */
add r1, r1, r4 /* r1增加offset值后保存到r1 */
str r1, [r0] /* 把r1的值保存到r0地址的内容中 */
/* 如上3行的时候,r1其实之前mask过0xff已经不需要保存了,可以用来做其它事情,所以3行主要是处理r0地址中的内容,为其加offset值后在存入r0 */
fixnext: /* 全部遍历完r2(start)值已经增长到了r3(end),那么就停止循环了。*/
cmp r2, r3
blo fixloop
relocate_done:
这里add r0, r0, r4
我有一个猜测,就是23类型不用再写入了。但是地址信息需要写入,这是什么原理,我要继续找原因。
三,源码仿真调试
之前qemu可以仿真vexpress,所以我单步调试了下。对我理解的代码进行了闭环验证,至少我理解是正确的。关于寄存器值的变换我都添加在每行后面了。
ENTRY(relocate_code)
relocate_base:
adr r3, relocate_base // r3 = 0x60801608 , r0 = 0x7ff55000
ldr r1, _image_copy_start_ofs // r1 = 0xffffe9f8
add r1, r3 /* r1
rel_dyn_start_ofs地址中服务器托管网的值确实能看到23,见下图
四,疑问项
之前我猜测rel_dyn_start_ofs中仅需要前4个字节改变地址,后面23不需要了,这是为什么呢,之后再研究。估计就是要symbol表得到地址,所以23可以不需要,但是地址是需要的。
五,小结
深度思考就是多服务器托管网问几个why。为什么要这样设计,为什么其他人会知道答案,我不知道,原因就是我一定缺少或者误解了某些信息。看来我要再看一遍,我记得里面对代码编译链接都写的很详细,以前细节估计看漏了,或者理解不清晰导致我会有这样的疑问项。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
Java字符串转换成算术表达式计算并输出结果,通过这个工具可以直接对字符串形式的算术表达式进行运算,并且使用非常简单。 这个工具中包含两个类 Calculator 和 ArithHelper Calculator 代码如下: import java.util.…