防止 GCC LTO 删除函数
Posted
技术标签:
【中文标题】防止 GCC LTO 删除函数【英文标题】:Prevent GCC LTO from deleting function 【发布时间】:2016-11-18 06:51:28 【问题描述】:我使用 GCC-ARM-Embedded 和 FreeRTOS。
FreeRTOS 具有 vTaskSwitchContext()
功能,仅在某些情况下使用
内联汇编代码。
问题是:当我使用 LTO 时,GCC 不考虑内联汇编代码并认为该函数没有被使用,因此将其删除。然后链接器失败,因为内联汇编代码中的函数调用无法解析。
我会申请__attribute__((used))
,但我不想接触 FreeRTOS 代码(由 STM32CubeMX 生成)。
我尝试将它放入我的代码中,但实际上 GCC 足够聪明,不允许它工作:
if(false)
vTaskSwitchContext();
有没有办法在不同的源文件中或通过参数告诉 GCC,这个函数不应该被删除?
示例
// file1.c
void vTaskSwitchContext( void )
...
// file2.c
void xPortPendSVHandler( void )
__asm volatile
(
...
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
...
);
【问题讨论】:
我想知道这是怎么发生的。链接器查看目标文件及其外部引用。符号是从 C 代码引用还是从内联汇编引用的,这无关紧要。 @undur_gongor:LTO 改变了很多事情,通常会引起意外。 “链接器”实际上并不查看目标文件和外部引用,而是链接器充当编译器后端的前端,然后将编译器后端的结果链接起来。 【参考方案1】:尝试从标记为used
的单独函数调用该函数。
void dummyFunction(void) __attribute__((used));
// Never called.
void dummyFunction(void)
vTaskSwitchContext();
【讨论】:
【参考方案2】:您可以将-Wl,--undefined=vTaskSwitchContext
添加到您的LDFLAGS
。
【讨论】:
【参考方案3】:由于某种原因,Dietrich 提出的解决方案对我不起作用。我正在使用 Infineon 的 DAVE 4(基本上是 eclipse,为他们的 XMC 微控制器系列提供了一个花哨的代码生成插件),这可能是它不起作用的原因。对我来说,我不得不在vTaskStartScheduler()
之后打电话给vTaskSwitchContext()
:
int main()
initializationCode();
vTaskStartScheduler();
//Code never reaches here
vTaskSwitchContext();
【讨论】:
【参考方案4】:如果您的 FreeRTOS 版本已使用宏 portDONT_DISCARD
代表 vTaskSwitchContext()
,您可以在自己的 portmacro.h
中定义 portDONT_DISCARD
#define portDONT_DISCARD __attribute__((used))
基本上是向后移植https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e
【讨论】:
以上是关于防止 GCC LTO 删除函数的主要内容,如果未能解决你的问题,请参考以下文章
24 GCC LTO - Link Time Optimization