lib gcc _init() 函数将地址作为指令执行

lib gcc _init() function executing address as instruction

提问人:Luis Sanchez 提问时间:10/11/2023 最后编辑:Luis Sanchez 更新时间:10/16/2023 访问量:68

问:

使用 gcc-arm-none-eabi 和默认 libc 对 cortex M4 目标进行编译将产生一个 _init() 函数,该函数执行内存位置,就好像它是一个函数一样。_()init 的解析是:

0002810c <_init>:
   2810c:   b5f8        push    {r3, r4, r5, r6, r7, lr}
   2810e:   bf00        nop

00028110 <__frame_dummy_init_array_entry>:
   28110:   0000529d    muleq   r0, sp, r2
   28114:   bcf8        pop {r3, r4, r5, r6, r7}
   28116:   bc08        pop {r3}
   28118:   469e        mov lr, r3
   2811a:   4770        bx  lr

在指令之后,指令被执行,但这实际上是指向函数的指针。拆解 crtio.o,位于何处,得出的 init 函数确实如上所述。2810e28110: muleq r0, sp, r2 0000529c <frame_dummy>:_init()

以下是我们正在使用的相关标志:

-Os -g -mthumb -ffunction-sections -fdata-sections -nostdinc -MD -mcpu=cortex-m4

下面是使用的链接器脚本:

    MEMORY
{
    FLASH_BOOTLOADER    (rx)    : ORIGIN = 0x00000000,    LENGTH = 0x00003000
    FLASH_FIRMWARE      (rx)    : ORIGIN = 0x00003000,    LENGTH = 0x0007D000

    RAM_FIRMWARE        (xrw)   : ORIGIN = 0x20000000,    LENGTH = 0x0001FFF8
    RAM_BL_NOINIT       (rw)    : ORIGIN = 0x0001FFF8,    LENGTH = 0x8
}

/* Entry Point */
ENTRY(boot)

/* Lowest address of the kernel stack (MSP) */
_estack = 0x200
_sstack = 0;

/* Compatibility with bm startup routines */
_estack_app_stack = _estack;
_sstack_app_stack = _sstack;

/* Define output sections */
SECTIONS
{
    /* The main ISR vector table goes first into program FLASH */
    /* The vectors follow immediately (aligned) after the bootloader, instead of a fixed adress */
    .isr_vector :
    {
        . = ALIGN(0x0200);  /* according to a comment, the ISR vectors must be aligned to 0x200 boundary */
        *(.isr_vector)
        KEEP(*(.isr_vector)) /* Startup code */
        . = ALIGN(4);
    } >FLASH_FIRMWARE

    .fwinfo :
    {
        . = ALIGN(4);
        *(.fwinfo_section)
        KEEP(*(.fwinfo_section))
        . = ALIGN(4);
    } >FLASH_FIRMWARE

    /* The program code and other data goes into FLASH */
    .text ALIGN(4):
    {
        *(.text)           /* .text sections (code) */
        *(.text*)          /* .text* sections (code) */

        . = ALIGN(4);
        _etext = .;        /* define a global symbols at end of code */
    } >FLASH_FIRMWARE

    /* Constant data goes into FLASH */
    .rodata ALIGN(4):
    {
        *(.rodata)         /* .rodata sections (constants, strings, etc.) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
        . = ALIGN(4);
    } >FLASH_FIRMWARE

    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } >FLASH_FIRMWARE

    .ARM : {
        __exidx_start = .;
        *(.ARM.exidx*)
        __exidx_end = .;
    } >FLASH_FIRMWARE

    _mdata = .;

    . = . + (_edata - _sdata);

    _marker_end_of_prg_flash = .;


    /* Used by the startup to initialize data */
    _sidata = LOADADDR(.data);
    
    .app_stack (NOLOAD) : AT (0)
    {
        . = ALIGN(4);
        . = . + GLB_STACK_SIZE;
        . = ALIGN(4);
    } >RAM_FIRMWARE

     /* Uninitialized data section */
    .bss :
    {
        /* This is used by the startup in order to initialize the .bss secion */
        . = ALIGN(4);
        _sbss = .;        /* define a global symbol at bss start */
        __bss_start__ = _sbss;
        *(.bss.fwp_stack)
        . = ALIGN(4);
        _sbss_dma_buffers = .;
        *(.bss.dma_buffers)
        . = ALIGN(4);
        _ebss_dma_buffers = .;
        *(.bss)
        *(.bss*)
        *(COMMON)

        . = ALIGN(4);
        _ebss = .;         /* define a global symbol at bss end */
        __bss_end__ = _ebss;
    } >RAM_FIRMWARE

    /* Initialized data sections goes into RAM, load LMA copy after code */
    .data : AT (_mdata)
    {
        . = ALIGN(4);
        _sdata = .;       /* create a global symbol at data start */
        *(.data)          /* .data sections */
        *(.data*)         /* .data* sections */

        . = ALIGN(4);
        KEEP(*(.boot_code_in_ram))
        . = ALIGN(4);
        /* All data end */
        . = ALIGN(4);
        _edata = .;       /* define a global symbol at data end */
    } >RAM_FIRMWARE

    /* Non zeroed variables */
    .noinit (NOLOAD) :
    {
        . = ALIGN(4);
        _snoinit = .;        /* define a global symbol at noinit start */
        __noinit_start__ = _snoinit;
        *(.noinit)
        *(.noinit*)
        *(COMMON)

        . = ALIGN(4);
        _enoinit = .;         /* define a global symbol at noinint end */
        __noinit_end__ = _enoinit;
    } >RAM_FIRMWARE

    /*
    .check_for_fwp_and_priv_ram (NOLOAD) :
    {
        . = ALIGN(4);
        . = . + FWP_RAM_SIZE;
        . = . + PRIVILEGED_DATA_SIZE;
    } >RAM_FIRMWARE
    */

    /* Used by the startup to initialize data */
    /* _si_priv_data = LOADADDR(.privileged_data); */


    .boot_shared_ram(NOLOAD) :
    {
        . = ALIGN(4);
        KEEP(*(.boot_shared_ram))
        . = ALIGN(4);
    } >RAM_BL_NOINIT

/*
    .boot_persistant_data :
    {
        . = ALIGN(4);
        _boot_persistant_data = .;
        KEEP(*(.boot_persistant_data))
        . = ALIGN(4);
    } >RAM_PERSISTANT_DATA
*/

    /* Remove information from the standard libraries */
    /DISCARD/ :
    {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
    }

    .ARM.attributes 0 : { *(.ARM.attributes) }
}

我们应该如何正确链接 libc 才能正确执行 _init()? 我们还注意到,如果我们添加: -nostartfiles 然后为 提供实现,问题就会得到解决,我仍然想了解以前的链接过程出了什么问题,因为默认实现应该有效。_init()

add: -nostartfiles,然后为 _init() 提供实现。按预期工作。

C 组件 GCC glibc Cortex-M

评论

0赞 0___________ 10/11/2023
-mcpu=cortex-m4
0赞 0___________ 10/11/2023
GCC 始终生成正确的代码。也许你的库不适合这种架构。
1赞 user1048576 10/12/2023
你能分享你的链接器脚本吗?

答: 暂无答案