_main 函数中会调用 relocate_code 函数。
relocate_code 函数分两个部分:
1. 拷贝 uboot 代码部分
2. 有关 " 重定位后有关函数调用或全局变量地址的问题"的解决方法。
本文继上一篇文章的学习,地址如下:
uboot启动流程-uboot代码重定位说明一_凌肖战的博客-CSDN博客
这里学习 uboot 重定位的第二部分内容:重定位后有关函数调用或全局变量地址的问题。
具体问题描述:
重定位 就是 uboot 将自身拷贝到 DRAM 的另一个地放去继续运行(DRAM 的高地址处)。
我们知道,一个可执行的 bin 文件,其链接地址和运行地址要相等,也就是链接到哪个地址, 在运行之前,就要拷贝到哪个地址去。现在我们重定位以后,运行地址就和链接地址不同了,这 样寻址的时候不会出问题吗?
当简单粗暴的将uboot从0X87800000 拷贝到其他地方以后,关于函数调用、全局变量引用就会出问题。Uboot对于这个的处理方法就是采用位置无关码,这个就需要借助于 .rel.dyn段。
- int board_early_init_f(void)
- {
- setup_iomux_uart();
-
- return 0;
- }
-
- static int rel_a = 0;
-
- void rel_test()
- {
- rel_a = 100;
- printf("rel_test\r\n");
- }
-
- int board_init(void)
- {
- rel_test();
- ......
- }
./imx6ull_alientek_nand.sh
编译完成以后,使用 arm-linux-gnueabihf-objdump 将 u-boot 进行反汇编,得到 u-boot.dis 这个汇编文件,命令如下:
arm-linux-gnueabihf-objdump -D -m arm u-boot > u-boot.dis
- 87804088 <rel_test>:
- 87804088: e59f300c ldr r3, [pc, #12] ; 8780409c <rel_test+0x14>
- 8780408c: e3a02064 mov r2, #100 ; 0x64
- 87804090: e59f0008 ldr r0, [pc, #8] ; 878040a0 <rel_test+0x18>
- 87804094: e5832000 str r2, [r3]
- 87804098: ea00faff b 87842c9c <printf>
- 8780409c: 8786b180 strhi fp, [r6, r0, lsl #3]
- 878040a0: 8784b1c3 strhi fp, [r4, r3, asr #3]
-
- 878040a4 <board_init>:
- 878040a4: e92d4010 push {r4, lr}
- 878040a8: ebfffff6 bl 87804088 <rel_test>
- ......
-
- 8786b180 <rel_a>:
- 8786b180: 00000000 andeq r0, r0, r0
0X87804088+0X18747000 = 0X9FF4B088
保 存 变 量 rel_a 地 址 的 Label 为:
下一篇了解 uboot 重定位后函数调用地址问题进行的处理。