链接时出现Small data重定位错误,尝试读取栈内存
链接器报错:Small data relocation against an object not in a named small data section(符号__CPU_STACK)
我现在要实现一个从栈内存地址读取值的功能,通过引用链接脚本里定义的外部符号__CPU_STACK来获取栈地址,但编译构建时链接器抛出了这个错误,我对Small data相关知识不了解,查资料也没找到这个错误的明确定义。
代码片段
extern uint32 __CPU_STACK; uint32* core1_stackHighAddress = (uint32*) __CPU_STACK; boolean expected_value = (PREDEFINED_VALUE == *(stack_lowAddress));
问题
- 这个错误到底是什么意思?
- 应该从哪些方面排查问题?
- 我猜测会不会是因为后台运行嵌入式OS,用户函数无权读取该内存地址?
错误含义解释
这个错误是链接器的小数据区(Small Data Section)机制导致的:
- 很多嵌入式编译器(比如ARM系的RVCT、GCC的
-mshort-data选项)会把小尺寸全局变量放到专门的小数据段(比如.sdata/.sbss),用短偏移寻址(比如16位偏移)提升访问效率。 - 链接器检测到你试图用小数据段的寻址方式去访问
__CPU_STACK这个符号,但该符号并不在任何标记为小数据的段里,因此抛出冲突错误。
排查方向
- 检查链接脚本中
__CPU_STACK的定义:确认这个符号是栈的起始/结束地址(通常是地址常量,不是变量),比如是不是用PROVIDE(__CPU_STACK = ORIGIN(STACK) + LENGTH(STACK));这类方式定义的。地址常量不能直接当作变量引用,得用指针形式声明。 - 修正代码的符号引用方式:把
extern uint32 __CPU_STACK;改成extern uint32 __CPU_STACK[];,直接取地址而非把符号值当作变量。正确写法示例:
如果extern uint32 __CPU_STACK[]; uint32* core1_stackHighAddress = (uint32*)__CPU_STACK;__CPU_STACK是栈起始地址常量,也可以写成:extern uint32 __CPU_STACK; uint32* core1_stackHighAddress = &__CPU_STACK; - 检查编译器/链接器的小数据相关选项:比如有没有开启
-mshort-data、-msdata这类强制小数据段的选项,若不需要可尝试关闭;或者手动将__CPU_STACK归入小数据段(但栈地址通常是全局常量,不适合这么做)。 - 关于嵌入式OS权限的猜测:这个错误是链接阶段的问题,和运行时权限无关——如果是权限问题,会在运行时触发内存访问错误(比如HardFault),不会在链接时报错,所以可以排除这个猜测。
内容的提问来源于stack exchange,提问作者haru
相关产品推荐
相关产品推荐

