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

ARM Cortex-M33下arm-none-eabi-gcc -Os优化栈帧错误致硬故障

问题描述

我使用以下ARM GNU工具链为ARM Cortex-M33编译代码,全局启用-Os优化:

arm-none-eabi-gcc.exe (Arm GNU Toolchain 14.3.Rel1 (Build arm-14.174)) 14.3.1 20250623
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

部分函数的序言会将r0、r1、r2压入栈中(并非所有函数都有此行为):

23d8:   e92d 41ff   stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
    23dc:   460c        mov r4, r1
    23de:   4605        mov r5, r0

当这类函数需要传递参数给其他函数时,生成的代码中SP操作存在错误,导致弹出到错误位置:

24f2:   b004        add sp, #16
    24f4:   e8bd 81f0   ldmia.w sp!, {r4, r5, r6, r7, r8, pc}

这会导致指针指向设备不存在的地址,触发硬故障。通过ARM内核的Tarmac跟踪确认:压栈时R0值为20001910,但出栈后对应值变为00000100;而R4弹出的值会用于MLA指令计算指针,预期R4应保留20001910。

将出现问题的函数单独设置为-O2优化后,硬故障不再出现。我尝试关联栈帧大小、调用栈深度等因素,但未发现明确规律。代码库中无裸函数或手动操作MSP的逻辑,仅包含部分CMSIS内联汇编或ARM GCC intrinsics。

请问如何在保留全局-Os优化的前提下缓解该问题?

缓解方案
  • 针对单个问题函数调整优化级别:在问题函数的声明或定义前添加__attribute__((optimize("O2"))),全局仍保持-Os,只对出问题的函数单独提升优化级别,这是最直接的临时解决方法。
  • 检查CMSIS内联汇编与GCC intrinsics:排查代码中使用的内联汇编或intrinsics是否存在破坏栈帧规则的情况,比如未正确保存/恢复寄存器、或与编译器的栈帧布局假设冲突。确保内联汇编遵循ARM AAPCS标准,尤其是寄存器使用和栈操作部分。
  • 尝试调整编译器的栈帧相关选项:可以尝试添加编译选项-fno-omit-frame-pointer强制保留帧指针,帮助编译器更准确地计算栈偏移;或者使用-fno-stack-reuse禁止编译器复用栈空间,避免SP计算错误。
  • 切换编译器版本:当前使用的是GCC 14.3.1的新发布版本,可能存在针对Cortex-M33和-Os优化的栈处理bug。尝试切换到稳定的旧版本(比如13.2.Rel1)或更新的测试版本,看是否能修复该问题。
  • 启用栈保护机制:添加-fstack-protector-all编译选项,虽然会增加少量代码体积,但可以帮助检测栈溢出或非法修改,同时可能迫使编译器生成更规范的栈操作代码。
  • 提交编译器bug报告:收集问题函数的简化可复现示例、编译选项、反汇编代码和Tarmac跟踪日志,提交到ARM GNU Toolchain的官方bug跟踪系统,推动官方修复底层编译逻辑问题。

内容的提问来源于stack exchange,提问作者Hari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:43:19