ARM Uboot经历——Uboot代码重定位

Uboot的重定位是将其从外部RAM移动到内部RAM以提高性能。这一过程涉及编译器如何处理地址限制,包括启动、拷贝和修改三个步骤。lds文件用于内存划分,启动代码计算拷贝范围,.rel段保存了需要修正的跳转地址。通过理解这些,可以更好地掌握ARM的重定位过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Uboot重定位是uboot启动后的一个重要功能,重定位的目的是为了让uboot运行在速度性能更好的RAM上,一般是从外部RAM搬移到内部RAM。重定位这块说简单也简单,说复杂也复杂,主要涉及到编译和链接等相关原理才能很好的理解整个过程。另外,理解了ARM的重定位,对于Kernel启动过程的重定位也就理解了。

编译器惹的祸

uboot重定位不是简单的copy,归根结底在于gcc的编译和链接过程。编译和链接的过程决定了重定位不是简单的copy,而是一件包含有技术含量的事情。

举个简单的例子来说明为什么不是简单的copy。ARM访问一个全局变量,一般的情况是先将地址写到寄存器里面,然后通过寄存器寻址来访问。假设地址是0xC0000000,那么ARM指令是无法直接将地址写入的,因为ARM最长指令也才32bit,不可能包含一个32bit的地址。那是不是可以分两步写?这个是可以,但ARM的编译器通常不这么做。

ARM会在编译的时候产生一个section,这个section是紧邻着代码段,这个section就会保留一个word存储了0xC0000000这个地址。当ARM在这段代码中要访问这个全局变量的时候,ARM会寻到这个section的起始地址,然后编译器计算这个偏移,根据起始地址和偏移计算得到保存0xC0000000的地址,最终得到这个需要地址再进行寻址。注意,从section的首地址到计算偏移这个过程是在编译链接的时候就完成了,因此代码中看到的汇编就是对地址的直接访问。

举例来说:

0x0000   test()
...
/* read 全局变量,地址为0xC0000000 */
0x0010   ldr r1, [r0] /* 读取保存0xC0000000的地址 */
0x0014 ldr r2, [r1] /* 读取0xc0000000的内容 */
...
0x0100  .section
0x0100  0xC0000000

简单来说,在每个代码段都会包含一个section,这个section保留了代码里面由于指令长度限制不能直接访问的变量或者函数的地址。

那么,重定位的时候,所有代码和数据都不在原来位置上了,那么这个section里面的所有数据的内容也就要改变。因此,简单的copy是不行的,还有些section里面的数据要重新写入。<

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值