ARM64裸机程序数组未按链接脚本指定地址分配问题
AArch64裸机程序中段地址不符问题分析
从你提供的map文件和链接脚本来看,核心问题是目标文件中的.axpudata_args0等子段本身已经被赋予了固定的VMA(虚拟内存地址)0x14000000系列,导致链接器无法按照你在链接脚本中指定的ARGBUF0(0xa0000000)等地址分配这些段,只能在.axpudata段起始地址0xa0000000到子段实际地址之间填充大量空间。
具体原因拆解
目标文件段的固定地址属性
你在C代码中给数组指定段属性时,可能无意中(或通过编译选项/隐式规则)给这些段设置了绝对地址。比如代码中如果用了类似:__attribute__((section(".axpudata_args0"), address(0x14000000))) char args_buffer_0[0x2000];或者编译器/汇编器的默认配置强制给这些段分配了0x14000000起始的地址,链接器会优先尊重目标文件中已有的段地址,而非链接脚本中的定位指令。
内存区域未正确声明
链接脚本中可能缺失MEMORY区域定义,没有明确标记0xa0000000所在的地址范围是可用的RAM/外设内存区域。链接器找不到对应内存区域时,会将段放到默认的内存区域(通常是0x14000000起始的系统RAM),同时尝试按照你指定的.axpudata起始地址填充空间,最终形成大尺寸填充区。链接脚本的定位逻辑冲突
你在.axpudata段内用. = ARGBUF0指令尝试定位子段,但如果子段本身有固定地址,这个定位指令只会修改链接器的当前位置计数器,却无法覆盖子段的固有地址,导致当前位置计数器和子段地址之间的空隙被自动填充。
排查与解决步骤
- 检查目标文件段信息:用
objdump -h aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o查看目标文件中.axpudata_args0等段的VMA字段,确认是否目标文件本身就指定了0x14000000的地址。 - 清理段的固定地址属性:如果C代码中给数组加了
address属性,将其移除;检查编译选项(比如-Wl,--section-start类参数)是否强制设置了这些段的地址,一并移除。 - 补充链接脚本的MEMORY定义:在链接脚本开头添加内存区域声明,比如:
然后在MEMORY { AXPUDATA (rw) : ORIGIN = 0xa0000000, LENGTH = 0x400000 ; 4*0x100000 RAM (rw) : ORIGIN = 0x14000000, LENGTH = 0x2000000 }.axpudata段的定义中关联到该区域:.axpudata : { . = ARGBUF0; *(.axpudata_args0) . = ARGBUF1; *(.axpudata_args1) // ... 其他子段定义 } > AXPUDATA - 验证链接脚本常量:用
ld -T your_script.ld --verbose查看链接器解析后的常量值,确认ARGBUF0等地址是否符合预期,排查是否存在重复定义覆盖的情况。
内容的提问来源于stack exchange,提问作者Chan Kim
相关产品推荐
相关产品推荐

