LLVM lld链接Cortex-M4固件时栈位置错误该如何修复?
问题根因
LLD与GNU LD的链接脚本语义存在兼容差异:
- 原生CMSIS链接脚本针对GNU LD编写,依赖GNU LD的隐式规则分配栈地址,LLD不会自动处理未显式定义的栈段位置,导致栈被错误分配到Flash区域。
- 你修改时添加的
(COPY)属性是给需要从Flash加载到RAM的初始化数据段使用的,栈属于纯运行时内存不需要该属性,LLD识别到该属性后会错误计算段的加载地址范围,最终触发溢出报错。
修正方案
- 替换
.stack段定义,移除COPY属性,新增NOLOAD标识告知链接器该段无需写入固件镜像:
.stack (NOLOAD) : ALIGN(8) { . = ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE; __StackLimit = .; . = . + __STACK_SIZE; __StackTop = .; } > RAM PROVIDE(__stack = __StackTop);
- 在
.bss段之后、.stack段之前显式定义堆段,保证__HeapLimit计算正确:
.heap (NOLOAD) : ALIGN(8) { __HeapBase = .; . += __HEAP_SIZE; __HeapLimit = .; } > RAM
- 保留原有的
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")断言即可。
验证逻辑
修改完成后重新链接,用nm命令查看符号:
__StackTop应为0x20010000(RAM基地址0x20000000 + 64KB RAM大小)__StackLimit应为0x2000FC00(栈顶减1KB栈大小)__HeapLimit应位于0x200018a8(bss段结束地址)之后,且远小于__StackLimit,不会触发溢出断言。
内容的提问来源于stack exchange,提问作者filo
相关产品推荐
相关产品推荐

