如何防止包含 C 库析构函数和 atexit()? [英] How to prevent inclusion of C library destructors and atexit()?

查看:33
本文介绍了如何防止包含 C 库析构函数和 atexit()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

arm-none-eabi-gcc 用于 Cortex-M4(裸机应用程序),即使我从未在代码中使用 malloc,也会发出 malloc 的代码.

Using arm-none-eabi-gcc for Cortex-M4 (baremetal application), the code for malloc is also emitted even though I never use malloc in my code.

arm-none-eabi-objdump -xS obj.elf看到汇编输出,看来malloc是被__register_exitproc调用的由 atexit 调用,由 register_fini

Seeing the assembly output with arm-none-eabi-objdump -xS obj.elf, it seems that malloc is called by __register_exitproc called by atexit called by register_fini

004036a8 <register_fini>:
  4036a8:       4b02            ldr     r3, [pc, #8]    ; (4036b4 <register_fini+0xc>)
  4036aa:       b113            cbz     r3, 4036b2 <register_fini+0xa>
  4036ac:       4802            ldr     r0, [pc, #8]    ; (4036b8 <register_fini+0x10>)
  4036ae:       f000 b805       b.w     4036bc <atexit>
  4036b2:       4770            bx      lr
  4036b4:       00000000        .word   0x00000000
  4036b8:       004036c9        .word   0x004036c9

然而,register_fini 从未在代码中被调用.main() 使用以下启动代码调用,因此即使 main 退出,析构函数(或使用 atexit() 注册的函数)也不会被调用.

However, register_fini is never called in the code. main() is called using the following startup code, so even if main exits, the destructors (or functions registered with atexit()) will not get called.

/**
 * \brief This is the code that gets called on processor reset.
 * To initialize the device, and call the main() routine.
 */
void Reset_Handler(void)
{
    uint32_t *pSrc, *pDest;

    /* Initialize the relocate segment */
    pSrc = &_etext;
    pDest = &_srelocate;

    if (pSrc > pDest) {
        for (; pDest < &_erelocate;) {
            *pDest++ = *pSrc++;
        }
    } else if (pSrc < pDest) {
        uint32_t nb_bytes = (uint32_t)&_erelocate - (uint32_t)&_srelocate;
        pSrc = (uint32_t*)((uint32_t)pSrc + nb_bytes) - 1;
        pDest = (uint32_t*)((uint32_t)pDest + nb_bytes) - 1;
        for (;nb_bytes;nb_bytes -= 4) {
            *pDest-- = *pSrc--;
        }
    }
    __NOP();

    /* Clear the zero segment */
    for (pDest = &_szero; pDest < &_ezero;) {
        *pDest++ = 0;
    }

    /* Set the vector table base address */
    pSrc = (uint32_t *) & _sfixed;
    SCB->VTOR = ((uint32_t) pSrc);

    /* Initialize the C library */
    __libc_init_array();

    /* Branch to main function */
    main();

    /* Infinite loop */
    while (1);
}

代码使用 -ffunction-sections-fdata-sections 编译并与标志 --gc-sections 链接,以便输出文件中不包含任何无法访问的代码/函数.

The code is compiled with -ffunction-sections and -fdata-sections and linked with the flag --gc-sections so that any unreachable code/functions are not included in the output file.

那么,如何防止我的代码中从未使用过的这些函数(register_finiatexitmalloc 等)被包含在目标文件中吗?

So, how can I prevent these functions (register_fini, atexit, malloc, etc) that are never used in my code from being included in the object file?

编译选项

arm-none-eabi-gcc -o build/main.o -c -mcpu=cortex-m4 -mthumb -pipe -g3 -Wall -Wextra -Wno-expansion-to-defined -Werror -std=gnu11 -fno-strict-aliasing -ffunction-sections -fdata-sections -DARM_MATH_CM4=true -D__SAM4SD32C__ -Ibunch -Iof -Iinclude -Idirs src/main.c

链接选项

arm-none-eabi-g++ -o build/tnc.elf -mcpu=cortex-m4 -mthumb -pipe -Wl,--entry=Reset_Handler -Wl,--gc-sections -Wl,--script my/linker/script.ld build/src/bunch.o build/src/of.o build/src/object.o build/src/files.o build/src/main.o -lm

推荐答案

可能你需要 -fno-use-cxa-atexit 编译器参数.

Probably you need -fno-use-cxa-atexit argument for compiler.

看看这个简单的例子,在纯裸机上获得 C++ 代码:https://github.com/cortexm/baremetal

Look on this simple example to get working C++ code on pure bare-metal: https://github.com/cortexm/baremetal

这篇关于如何防止包含 C 库析构函数和 atexit()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆