LTO 模式下的 ARM 的 GCC 8 正在删除中断处理程序和弱函数 - 如何防止它?

GCC 8 for ARM in LTO mode is removing interrupt handlers and weak functions - how to prevent it?

我的目标设备是基于 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 模式下以同样的方式表现不正常。

提前感谢您的任何想法!

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

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

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