You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clang+CMake交叉编译ARM Cortex M4固件启用C++异常失效且生成.got段问题

修复方案

1. 消除不必要的GOT段

你遇到的GOT段自动插入问题,本质是Clang默认启用了位置无关代码(PIC)生成,静态链接的裸机固件完全不需要该特性。在CMAKE_CXX_FLAGS_INIT和CMAKE_EXE_LINKER_FLAGS_INIT中添加以下编译参数,即可彻底关闭PIC相关逻辑,不再生成GOT段:

-fno-pic -fno-pie -fno-plt

添加后不需要再手动修改链接脚本插入.got段配置,也不会再出现全局变量地址偏移错误的问题。

2. 匹配异常处理模型

Clang针对ARM Cortex-M裸机目标,需要显式指定与GCC libgcc兼容的异常处理和调用约定,在CMAKE_CXX_FLAGS_INIT中补充以下参数:

-funwind-tables
-fasynchronous-unwind-tables
-mabi=aapcs

上述参数会强制Clang生成符合ARM AAPCS标准的调用栈,以及GCC libgcc可识别的unwind栈信息,用于异常抛出后的栈展开。

3. 调整链接库顺序

链接器按照从左到右的顺序解析符号依赖,你当前的链接库顺序不符合C++异常处理的依赖关系,将CMAKE_EXE_LINKER_FLAGS_INIT最后的库参数调整为:

-lstdc++ -lgcc -lc -lm -lnosys -lgcc

调整逻辑是:libstdc++的异常实现依赖libgcc的unwind功能,libc依赖libgcc的内置函数,末尾重复添加-lgcc用于解决libgcc和libc之间的循环依赖问题。

4. 兼容性排查

如果完成上述配置后异常仍然无法捕获,按以下步骤排查:

  • 临时删除编译和链接参数中的-flto选项测试,LLVM 13的LTO实现与GCC 10的libgcc存在已知的unwind符号兼容问题,关闭LTO后如果异常正常工作,可升级LLVM到15及以上版本,或添加LTO参数-Wl,-plugin-opt=-emulated-tls解决兼容问题。
  • 使用arm-none-eabi-readelf -u 编译生成的elf文件命令验证unwind段是否正常生成,如果没有输出unwind信息,回到第二步确认编译参数是否正确添加。
  • 在HardFault_Handler中添加断点,查看故障触发时的调用栈,确认是否是__cxa_throw函数执行过程中触发的异常,如果是则检查链接的libgcc是否是对应Cortex-M4硬浮点版本的库。

内容的提问来源于stack exchange,提问作者K. Koovalsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 11:15:05