在老的uboot中,如果我们想要uboot启动后把自己拷贝到内存中的某个地方,只要把要拷贝的地址写给TEXT_BASE即可,然后boot启动后就会把自己拷贝到TEXT_BASE内的地址处运行,在拷贝之前的代码都是相对的,不能出现绝对的跳转,否则会跑飞。
在最新的uboot里(2013.07),TEXT_BASE的含义改变了。他表示用户要把这个代码下载到哪里,通常是通过串口等工具。然后搬移的时候由uboot自己计算一个地址来进行搬移。在init_f函数中计算出了要搬移到的地方,然后relocate.S来进行搬移。问题是我们在编译的时候明明指定的TEXT_BASE和这个地址不一致,那么在搬移到新的地址后,代码运行不会跑飞吗?在代码阅读的过程中发现,新版的uboot采用了动态链接技术,在lds文件中有__rel_dyn_start和__rel_dyn_end,这两个符号之间的区域存放着动态链接符号,只要给这里面的符号加上一定的偏移,拷贝到内存中代码的后面相应的位置处,就可以在绝对跳转中找到正确的函数。
我的开发环境是2440,现在还留有两个问题:
1.在新版的uboot中如果我定义TEXT_BASE是0x32000000,但是下载代码到0x30000000启动会不会能正确运行?
初步分析:不能
因为在拷贝之前执行了init_f函数,这个函数中程序跑飞了,具体原因可能是有绝对的跳转,但是没有足够证据。
2.在relocate.S中有以下代码:
copy_loop:这段主要是进行代码段拷贝
46 ldmia r1!, {r10-r11} /* copy from source address [r1] */
47 stmia r0!, {r10-r11} /* copy to target address [r0] */
48 cmp r1, r2 /* until source end address [r2] */
49 blo copy_loop
50
51 /*
52 * fix .rel.dyn relocations
53 */
54 ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */
55 ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
56 fixloop:/这段进行了根据动态链接区域修改函数跳转表的动作,加了偏移的地址
57 ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */
58 and r1, r1, #0xff
59 cmp r1, #23 /* relative fixup? */
60 bne fixnext
61
62 /* relative fix: increase location by offset */
63 add r0, r0, r9/r9为偏移数值,基本原理就是取出之前函数对应的位置,加上偏移,写到新地址的对应位置处(应该是跳转表什么的)。
64 ldr r1, [r0]
65 add r1, r1, r9
66 str r1, [r0]
67 fixnext:
68 cmp r2, r3
69 blo fixloop
这里有个疑问,这里判断r1 和#23的关系,通过察看二进制文件可以发现确实有这样的一个排布:
7545 001d780: 1700 0000 3800 0032 1700 0000 8407 0032 ....8..2.......2
7546 001d790: 1700 0000 8807 0032 1700 0000 8c07 0032 .......2.......2
7547 001d7a0: 1700 0000 e407 0032 1700 0000 e807 0032 .......2.......2
7548 001d7b0: 1700 0000 ec07 0032 1700 0000 f007 0032 .......2.......2
7549 001d7c0: 1700 0000 4808 0032 1700 0000 4c08 0032 ....H..2....L..2
7550 001d7d0: 1700 0000 7808 0032 1700 0000 4009 0032
....x..2....@..27551 001d7e0: 1700 0000 4409 0032 1700 0000 4809 0032 ....D..2....H..2
7552 001d7f0: 1700 0000 4c09 0032 1700 0000 5009 0032 ....L..2....P..2
7553 001d800: 1700 0000 5409 0032 1700 0000 5809 0032 ....T..2....X..2
7554 001d810: 1700 0000 5c09 0032 1700 0000 6009 0032 ....\..2....`..2
7555 001d820: 1700 0000 6409 0032 1700 0000 a00a 0032 ....d..2.......2
7556 001d830: 1700 0000 a40a 0032 1700 0000 a80a 0032 .......2.......2
这里为什么要用0x17(23)呢?他的来历是什么?每一个地址后面都跟了一个0x17.比如:
0x32000038 0x00000017
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。