5

我的目标设备是基于 EFM32 Cortex-M3 的设备。我的工具链是官方的 ARM GNU 工具链 gcc-arm-none-eabi-8-2018-q4-major。

没有 LTO 一切正常,但要使 LTO 工作,我必须用 . 标记所有中断处理程序代码-fno-lto。我想摆脱这种解决方法。

问题是,每个中断处理程序都从最终的二进制文件中删除。(我正在检查arm-none-eabi-nm --print-size --size-sort --radix=d -C -n file.out)这会导致二进制崩溃。

深入挖掘并在谷歌搜索类似问题后:

来自定义默认中断处理程序的示例代码startup_efm32gg.c如下:

void DMA_IRQHandler(void) __attribute__ ((weak, alias("Default_Handler")));
/* many other interrupts */
void Default_Handler(void) { while (1); }

常规中断处理程序定义也会发生同样的问题(例如,没有别名且不弱)

这可能是相关的,但似乎弱符号在 LTO 模式下以同样的方式行为不端。

提前感谢您的任何想法!

编辑:查看我对标记答案的回复以获得完整的解决方案!

4

1 回答 1

3

您的中断处理程序是从哪里引用的?就像未引用的静态函数和对象将从单个翻译单元中删除一样,未使用的外部函数和对象将在 LTO 期间删除。为了防止这种情况(并且为了让您的程序在抽象模型中仍然有效),需要一些引用链,从入口点开始,通向函数和对象;如果不存在,那么您实际上并没有在程序中使用它们

如果引用来自链接器脚本或 asm 源文件,这可能是 LTO 中的一个错误,并且它没有看到应有的引用。在这种情况下,您可能可以__attribute__((__used__))对受影响的函数定义应用 hack。或者,您可以对它们进行虚假引用,例如通过将它们的地址存储到虚拟易失性对象或在输入约束中使用它们的地址来清空内联 asm 块。作为另一种选择,可能有一种方法可以重做您对 asm 源文件或链接脚本所做的任何事情,以在 C 级别制作您的中断表,并在特殊部分使用适当的结构/数组,以便编译器实际上可以看到参考资料,而您不必伪造它们。

于 2019-01-01T16:58:08.437 回答