加载地址、运行地址以及链接地址

一、背景

我们以一块 ARM64 开发板为例,芯片内部有 SRAM,起始地址为 0x0, DDR 内存的起始
地址为 0x40000000。通常代码存储在 Nor Flash 存储器或者 Nand Flash 存储器中, 芯片内部的 BOOT ROM 会把开始的小部分代码装载到 SRAM 中。芯片上电复位之后,从 SRAM 中取指令。由于 UBoot 的映像太大了, SRAM 放不下,因此该映像必须要放在 DDR 内存中。通常编译 UBoot 时链接地址都设置到 DDR 内存中,也就是 0x40000000 地址处。这时运行地址和链接地址就不一样了。运行地址为 0x0,链接地址变成 0x40000000,那么程序为什么还能运行呢?

二、定义

加载地址:存储代码的物理地址,在 GNU 链接脚本里称为 LMA。例如, ARM64 处
理器上电复位后是从异常向量表开始取第一条指令的,所以通常这个地方存放代码最
开始的部分,如异常向量表的处理代码。
运行地址:程序运行时的地址,在 GNU 链接脚本里称为 VMA。
链接地址:在编译、链接时指定的地址,编程人员设想将来程序要运行的地址。
程序中所有标号的地址在链接后便确定了,不管程序在哪里运行都不会改变。当
使用 aarch64-linux-gnu-objdump(简称 objdump) 工具进行反汇编时, 查看的就是
链接地址。


加载地址和运行地址可以相同,也可以不同,通常情况下,这两个地址是相同的。 不过,它们也有可能不相同,例如,一个代码段被加载到 ROM 中,在程序启动时被复制到 RAM 中。在这种情况下, ROM 地址将是加载地址,RAM 地址将是虚拟地址

链接地址和加载地址可以相同,也可以不同,下面就是加载地址不等于链接地址
 

在第 13 行里使用 AT 表明代码段的加载地址为 TEXT_ROM(0x90000)。此时,代码段的
加载地址就与链接地址不一样,而链接地址与运行地址一样。代码段的链接地址可以通过
benos.map 来查看。

链接地址和运行地址可以相同,也可以不同,下面就是运行地址不等于链接地址

在第 6 行中,当前位置计数器(LC)把代码段的链接地址设置为 0xFFFF000010080000,这
是内核空间的一个地址。 树莓派 4B 上电复位后使 benos.bin 加载并跳转到 0x80000 地址处。 此时,运行地址和加载地址都为 0x80000,而链接地址为 0xFFFF000010080000 

如果链接地址与运行地址不同,我们需要在汇编代码里初始化 MMU, 并且把 DDR 内存映射到内核空间, 然后做一次重定位的操作, 让 CPU 的运行地址重定位到链接地址。
 

三、原理

如果所有代码都在 ROM(或 Nor Flash 存储器)中执行,那么链接地址可以与加载地址
相同。而在实际项目应用中,往往想要把程序加载到 DDR 内存中, DDR 内存的访问速度比
ROM 的要快很多,而且容量也大,所以设置链接地址在 DDR 内存中,而程序的加载地址设
置到 ROM 中,这两个地址是不相同的。如何让程序能在链接地址上运行呢?

常见的思路就是,
让程序的加载地址等于 ROM 的起始地址(或者片内 SRAM 地址),而链接地址等于 DDR 内
存中某一处的起始地址(暂且称为 ram_start)。程序先从 ROM 中启动,最先启动的部分要实
现代码复制功能(把整个 ROM 代码复制到 DDR 内存中),并通过 LDR 指令来跳转到 DDR
内存中, 也就是在链接地址里运行(B 指令没法实现这个跳转)。 上述重定位过程在 Uboot 中
实现,如图 9.6 所示。

当跳转到 Linux 内核中时, Uboot 需要把 Linux 内核映像的内容复制到 DDR 内存中, 然后
跳转到内核入口地址处(stext 函数)。当跳转到内核入口地址(stext 函数)时,程序运行在运
行地址, 即 DDR 内存的地址。 但是我们从 vmlinux 看到的 stext 函数的链接地址是虚拟地址。 内核启动汇编代码也需要一个重定位过程。 这个重定位过程在__primary_switch 汇编函数中完成。

__primary_switch 汇编函数的主要功能是初始化 MMU 和实现重定位。启动 MMU 之后,通过 LDR 指令把__primary_switched 函数的链接地址加载到 X8寄存器中,然后通过 BR 指令跳转到__primary_switched 函数的链接地址处,从而实现重定位, 

参考:

链接地址、运行地址、加载地址、存储地址-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值