简体   繁体   English

防止 GCC LTO 删除函数

[英]Prevent GCC LTO from deleting function

I work with GCC-ARM-Embedded and FreeRTOS.我使用 GCC-ARM-Embedded 和 FreeRTOS。 FreeRTOS has the function vTaskSwitchContext() which is used only in some inline assembler code. FreeRTOS 具有函数vTaskSwitchContext() ,该函数仅用于某些内联汇编代码。

The problem is: When I use LTO, GCC does not consider the inline assembler code and thinks the function is not used, thus removes it.问题是:当我使用LTO时,GCC没有考虑内联汇编代码并认为该函数没有使用,因此将其删除。 The linker then fails because the function call in the inline assembler code cannot be resolved.然后链接器失败,因为无法解析内联汇编代码中的函数调用。

I would apply __attribute__((used)) but I don't want to touch the FreeRTOS code (it's generated by STM32CubeMX).我会应用__attribute__((used))但我不想接触 FreeRTOS 代码(它由 STM32CubeMX 生成)。

I tried putting this in my code, but actually GCC is smart enough to not allow this to work:我试着把它放在我的代码中,但实际上 GCC 足够聪明,不允许它工作:

if(false)
    vTaskSwitchContext();

Is there some way to tell GCC in a different source file, or via parameter, that this function should not be removed?有没有办法在不同的源文件中或通过参数告诉 GCC 不应删除此函数?

Example示例

// file1.c
void vTaskSwitchContext( void )
{
    ...
}

// file2.c
void xPortPendSVHandler( void )
{
    __asm volatile
    (
    ...
    "   isb                                 \n"
    "   bl vTaskSwitchContext               \n"
    "   mov r0, #0                          \n"
    ...
    );
}

Try calling the function from a separate function which is marked used .尝试从标记为used的单独函数调用该函数。

void dummyFunction(void) __attribute__((used));

// Never called.
void dummyFunction(void) {
    vTaskSwitchContext();
}

您可以将-Wl,--undefined=vTaskSwitchContext添加到您的LDFLAGS

For some reason, the solution that Dietrich proposed didn't work for me.出于某种原因,Dietrich 提出的解决方案对我不起作用。 I'm using Infineon's DAVE 4 (basically eclipse with a fancy code generation plugin for their line of XMC microcontrollers), which may be the reason why it didn't work.我正在使用 Infineon 的 DAVE 4(基本上是 Eclipse,他们的 XMC 微控制器系列带有一个花哨的代码生成插件),这可能是它不起作用的原因。 For me, I had to call vTaskSwitchContext() after vTaskStartScheduler() :对我来说,我不得不在vTaskStartScheduler()之后调用vTaskSwitchContext() vTaskStartScheduler()

int main(){

    initializationCode();

    vTaskStartScheduler();

    //Code never reaches here
    vTaskSwitchContext();
}

If your version of FreeRTOS uses already uses the macro portDONT_DISCARD for vTaskSwitchContext() you can define portDONT_DISCARD in your own portmacro.h如果您FreeRTOS的用途版本已经使用宏portDONT_DISCARDvTaskSwitchContext()可以定义portDONT_DISCARD在自己portmacro.h

#define portDONT_DISCARD __attribute__((used))

Essentially backporting https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e基本上向后移植https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM