VMA != LMA 时加载 ELF

ELF loading when VMA != LMA


我对此有疑问。我正在使用带 DS-5 的 ARM Cortex-A9 创建裸机固件。我修改了我的链接器文件,故意将 .data 部分 LMA 放在文本和 rodata 部分附近,因为它的默认 运行-time VMA 位于 1MB 之外,而 .bin 图像大约为 1MB,但包含 90% 的零。所以我故意让 LMA != VMA 来保存 space。我还在 start.S 中添加了一个代码,将 .data 部分从其 lma 重新定位到 vma。

然而,在 DS-5 中加载生成的 elf 文件时,它已经将所有部分加载到他们的 VMA 中。结果,我的 start.S 本应重新定位数据的代码,从带有垃圾内容的 LMA 复制到已经正确的 VMA,不久之后这些垃圾导致了错误。

我在Cortex-M4的二进制文件中遇到过不相等的VMA和LMA,并使用gdb进行elf调试,那里没有问题,但它是微控制器。在我当前的 arm 处理器应用程序中,我将如何在 elf 中模拟调试将数据从其 LMA 正确复制到 VMA 的场景。使用二进制格式独立启动时很可能不会出现问题,但现在我们仍在进行 elf 调试,所以我必须解决这个问题。

问题已解决...我想分享给我的解决方案:

有助于认识到 "VMA" 和 "LMA" 是 GNU 实用程序术语,不在 ELF 规范中。一旦你认真地从解释一个ELF可执行文件来看它,你会发现有一个名为"p_paddr"的程序头字段和一个名为"p_vaddr"的程序头字段——这样更容易搜索!在 DS-5 中使用 p_paddr 所需的选项是:

ARM DS-5 调试器命令参考:1.3.138 set elf load-segments-at-p_paddr

默认情况下,DS-5 使用 p_vaddr,这是标准的。 p_paddr 的使用是实现的质量,并且在规范中定义得非常松散。 ARM 编译器、链接器和 C 库不会生成此信息,因为重定位过程是在内部处理的(分散加载)。有些环境使用 p_paddr 不是物理地址,而是加载地址(因此 "LMA"),有些环境使用它作为地址来解析启用 MMU 前后的符号..