gcc GNU链接器ARM -为什么我的部分重叠?

6yoyoihd  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(177)

我需要添加一个小堆来使用TM 4C ARM微控制器上的标准库函数(_sbrk需要end符号)。
这是我的链接器脚本(附带一个微控制器演示):

/* Entry Point */
ENTRY(Reset_Handler)

HEAP_SIZE = 1024;

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}

SECTIONS
{
    .text :
    {
        _text = .;
        KEEP(*(.isr_vector))
        *(.text*)
        *(.rodata*)
        _etext = .;
    } > FLASH

    .data : AT(ADDR(.text) + SIZEOF(.text))
    {
        _data = .;
        _ldata = LOADADDR (.data);
        *(vtable)
        *(.data*)
        _edata = .;
    } > SRAM

    .bss :
    {
        _bss = .;
        *(.bss*)
        *(COMMON)
        _ebss = .;
    } > SRAM

    .heap : AT(ADDR(.bss) + SIZEOF(.bss))
    {
        . = ALIGN(8);
        __end__ = .;
        PROVIDE(end = .);
        __HeapBase = .;
        . += HEAP_SIZE;
        __HeapLimit = .;
    } > SRAM
}

我只是在.bss之后添加了.heap,类似于.data/.text,但我得到了链接错误:

ld: section .init loaded at [000126b4,000126bf] overlaps section .data loaded at [000126b4,00012f8f]
collect2: error: ld returned 1 exit status

当我删除AT(ADDR(.bss) + SIZEOF(.bss))时也会发生这种情况。当我删除.heap并调用libc函数时,所有的东西都会编译和链接,输出的二进制文件会正确运行。
我应该如何调整脚本以正确地将heap放置在bss之后?

332nm8kg

332nm8kg1#

事实证明我的heap和bss是正确的,但是当链接标准库函数时,添加了名为.init和.fini的新部分-它们与. data冲突。

/* Entry Point */
ENTRY(Reset_Handler)

HEAP_SIZE = 1024;

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}

SECTIONS
{
    .text :
    {
        _text = .;
        KEEP(*(.isr_vector))
        *(.text*)
        *(.rodata*)
        KEEP (*(.init))
        KEEP (*(.fini))
        _etext = .;
    } > FLASH

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

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

    __end_code = .;

    .data : AT(__end_code)
    {
        _data = .;
        _ldata = LOADADDR (.data);
        *(vtable)
        *(.data*)
        _edata = .;
    } > SRAM

    .bss :
    {
        _bss = .;
        *(.bss*)
        *(COMMON)
        _ebss = .;
    } > SRAM

    .heap : AT(_ebss)
    {
        . = ALIGN(8);
        __end__ = .;
        PROVIDE(end = .);
        __HeapBase = .;
        . += HEAP_SIZE;
        __HeapLimit = .;
    } > SRAM
}

我添加了KEEP (*(.init))KEEP (*(.fini)).ARM行(来自另一个MCU链接器脚本)。现在一切都链接并运行良好。

mcvgt66p

mcvgt66p2#

如果你使用的是TivaWare库,我建议你使用在Code Composer中创建相应项目时生成的链接器脚本。你可以直接将它复制到你的项目中。例如,tm 4c 123 glx launchpad评估板上的处理器的名称应该是tm4c123gh6pm.lds。我将它粘贴在这里:

/******************************************************************************
 *
 * Default Linker script for the Texas Instruments TM4C123GH6PM
 *
 * This is derived from revision 15071 of the TivaWare Library.
 *
 *****************************************************************************/

MEMORY
{
    FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (WX)  : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
REGION_ALIAS("REGION_ARM_EXTAB", FLASH);

SECTIONS {

    PROVIDE (_intvecs_base_address = 0x0);

    .intvecs (_intvecs_base_address) : AT (_intvecs_base_address) {
        KEEP (*(.intvecs))
    } > REGION_TEXT

    PROVIDE (_vtable_base_address = 0x20000000);

    .vtable (_vtable_base_address) : AT (_vtable_base_address) {
        KEEP (*(.vtable))
    } > REGION_DATA

    .text : {
        CREATE_OBJECT_SYMBOLS
        *(.text)
        *(.text.*)
        . = ALIGN(0x4);
        KEEP (*(.ctors))
        . = ALIGN(0x4);
        KEEP (*(.dtors))
        . = ALIGN(0x4);
        __init_array_start = .;
        KEEP (*(.init_array*))
        __init_array_end = .;
        *(.init)
        *(.fini*)
    } > REGION_TEXT

    PROVIDE (__etext = .);
    PROVIDE (_etext = .);
    PROVIDE (etext = .);

    .rodata : {
        *(.rodata)
        *(.rodata*)
    } > REGION_TEXT

    .data : ALIGN (4) {
        __data_load__ = LOADADDR (.data);
        __data_start__ = .;
        *(.data)
        *(.data*)
        . = ALIGN (4);
        __data_end__ = .;
    } > REGION_DATA AT> REGION_TEXT

    .ARM.exidx : {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } > REGION_ARM_EXIDX

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

    .bss : {
        __bss_start__ = .;
        *(.shbss)
        *(.bss)
        *(.bss.*)
        *(COMMON)
        . = ALIGN (4);
        __bss_end__ = .;
    } > REGION_BSS

    .heap : {
        __heap_start__ = .;
        end = __heap_start__;
        _end = end;
        __end = end;
        KEEP(*(.heap))
        __heap_end__ = .;
        __HeapLimit = __heap_end__;
    } > REGION_HEAP

    .stack : ALIGN(0x8) {
        _stack = .;
        __stack = .;
        KEEP(*(.stack))
    } > REGION_STACK
}

然后确保你的启动代码初始化了正确的部分(你也会得到一个名为tm4c123gh6pm_startup_ccs_gcc.c的文件,其中包含启动代码,可以按原样使用,也可以作为指导。
你会注意到它们对初始化不同部分所需的变量做得很好,避免了 * user 2162550 * 带来的问题。
顺便说一句,我注意到当用-O2链接器编译时,错误有点模糊-如果你的代码适合,关闭它,直到你得到你想要的一切。

vsdwdz23

vsdwdz233#

我遇到了与现有ld脚本相同的问题。通过添加链接选项-nostartfiles解决了这个问题

相关问题