【问题标题】:GNU linker ARM - why my sections overlap?GNU 链接器 ARM - 为什么我的部分重叠?
【发布时间】:2018-01-05 16:58:38
【问题描述】:

我需要添加一个小堆以在 TM4C 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 函数时,所有内容都会编译和链接,输出二进制文件会正确运行。

我应该如何调整脚本以在 bss 之后正确放置堆?

【问题讨论】:

    标签: gcc arm ld linker-scripts


    【解决方案1】:

    事实证明,我的堆和 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 链接器脚本)。现在一切都链接并运行良好。

    【讨论】:

    【解决方案2】:

    如果您使用的是 TivaWare 库,我建议您使用在 Code Composer 中创建相应项目时生成的链接器脚本。您可以将其复制到您的项目中。例如,对于 tm4c123glx 启动板评估板上的处理器,名称将是 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 的文件,该文件将包含启动代码,可以按原样使用或作为指导。

    您会注意到它们在初始化各个部分所需的变量方面做得很好。避免 user2162550 提出的问题。

    顺便说一句 - 我注意到在使用 -O2 编译时,链接器错误有点混淆 - 如果您的代码适合,请关闭它,直到您获得所需的所有内容。

    【讨论】:

      猜你喜欢
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 2015-07-01
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      相关资源
      最近更新 更多