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

时间:2019-01-01 16:44:12

标签: c gcc arm lto

我的目标设备是基于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模式下的行为也相同。

预先感谢您的任何想法!

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

1 个答案:

答案 0 :(得分:3)

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

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