我正在为软件使用模块化构建系统,而不是在 ARM 嵌入式目标以及普通 X86 (linux) 机器上运行。我正在使用 GNU 工具链进行编译,因此使用ld
.
其中一个模块使用链接脚本技巧来组装一组“已注册”对象。这些对象是使用这样的宏创建的:
#define RegObject(name, arg1, arg2, etc) \
static TRegObject name \
__attribute__((section ("regobj_table"), used)) = \
{ arg1, arg2, etc }
该模块还向链接步骤添加了一个隐式链接器脚本,如下所示:
SECTIONS
{
.data : ALIGN(4)
{
regobj_table_start = .;
KEEP(*(regobj_table))
regobj_table_end = .;
}
}
代码使用regobj_table_start
和regobj_table_end
符号来查找已注册的对象。此解决方案适用于本机 (Linux) 编译目标。
但是,这不适用于 ARM 目标。原因是我有一个用于目标的自定义默认链接器脚本(它是一个微型微控制器,在没有操作系统的情况下运行),它定义了该.data
部分的加载内存地址。这是因为该部分存储在闪存中,但是一旦微控制器启动,它就会被复制到 RAM。链接描述文件的相关部分如下所示:
MEMORY
{
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 512k
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 32k
}
SECTIONS
{
/* ... other stuff ... */
.data :
{
_data = .;
*(.data)
*(.data.*)
} >RAM AT>ROM
/* ... even more stuff ... */
}
这会将.data
部分的 VMA 设置为 0x4000000 范围内的某个位置,并将 LMA 设置为 0x00000000 范围内的某个位置。
问题是,当隐式链接器脚本被添加到命令行时ld
,它只是忘记了 LMA,它再次变得等于 VMA。我正在拼命寻找一种方法来告诉ld
在加载隐式链接器脚本时不要触摸 LMA。