GCC BareMetal连接器问题-皮质M3

9w11ddsr  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(138)

我在连接我的项目时遇到了问题。我使用来自制造商的GCC链接器脚本。
在这里,我定义了如下代码段:

MEMORY
{
  // .. deleted other sections
  CODE  (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000   /* 116 page(s) */
  // .. deleted other sections
}

因此,代码段开始位于0xB 000,长度为0x 74000。长度为116 x4096字节=>475136字节代码大小
我的二进制版本大小如下:

text    data     bss     dec     hex filename
 432372       0  112048  522420   7f8b4 project.elf

因此,它应该链接OK,因为使用的大小432372(文本+数据)比可用空间475136小得多。
只要二进制代码大小< ~ 422 kBytes,它就可以链接,一旦它变大,链接器告诉我CODE部分溢出,无法链接。
有人能解释一下为什么吗?我看不出链接告诉我我的代码太大的原因,因为它不是!

链接脚本

MEMORY
{
  // ... removed sections here .. irelevant for discussion ...
  CODE  (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000   /* 116 page(s) */
  // ... removed sections here .. irelevant for discussion ...
  RAM                    (xrw) : ORIGIN = 0x20000040, LENGTH = 20000
  MEMORY_B1              (rx ) : ORIGIN = 0x60000000, LENGTH = 0K
}

/* The '__stack' definition is required by crt0, do not remove it            */
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack; 

__Main_Stack_Size = 2048 ;

PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;

__Main_Stack_Limit = __stack  - __Main_Stack_Size ;

/*"PROVIDE" allows to easily override these values from an object file or the command line. */
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;

/*
 * There will be a link error if there is not this amount of 
 * RAM free at the end. 
 */
_Minimum_Stack_Size = 2048 ;

/*
 * Default heap definitions.
 * The heap start immediately after the last statically allocated 
 * .sbss/.noinit section, and extends up to the main stack limit.
 */
/*PROVIDE ( _Heap_Begin = _end_noinit ) ;  */
/*PROVIDE ( _Heap_Limit = _end_noinit ) ;   */

_Min_Heap_Size  = 0x100; /* required amount of heap  (256 bytes) */
_Min_Stack_Size = 0x400; /* required amount of stack (1kByte)    */

ENTRY(Reset_Handler)

SECTIONS
{
  .text :
  {
    KEEP(*(.vectors))
    __Vectors_End = .;
    __Vectors_Size = __Vectors_End - __Vectors;
    __end__ = .;

    *(.text*)

    KEEP(*(.init))
    KEEP(*(.fini))

    /* .ctors */
    *crtbegin.o(.ctors)
    *crtbegin?.o(.ctors)
    *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
    *(SORT(.ctors.*))
    *(.ctors)

    /* .dtors */
    *crtbegin.o(.dtors)
    *crtbegin?.o(.dtors)
    *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
    *(SORT(.dtors.*))
    *(.dtors)

    *(.rodata*)

    KEEP(*(.eh_frame*))
  } > CODE

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

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

  /* To copy multiple ROM to RAM sections,
   * uncomment .copy.table section and,
   * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
  /*
  .copy.table :
  {
    . = ALIGN(4);
    __copy_table_start__ = .;
    LONG (__etext)
    LONG (__data_start__)
    LONG (__data_end__ - __data_start__)
    LONG (__etext2)
    LONG (__data2_start__)
    LONG (__data2_end__ - __data2_start__)
    __copy_table_end__ = .;
  } > CODE
  */

  /* To clear multiple BSS sections,
   * uncomment .zero.table section and,
   * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
  /*
  .zero.table :
  {
    . = ALIGN(4);
    __zero_table_start__ = .;
    LONG (__bss_start__)
    LONG (__bss_end__ - __bss_start__)
    LONG (__bss2_start__)
    LONG (__bss2_end__ - __bss2_start__)
    __zero_table_end__ = .;
  } > CODE
  */

  __etext = .;

  .data : AT (__etext)
  {
    __data_start__ = .;
    *(vtable)
    *(.data*)
    . = ALIGN (4);
    *(.ram)

    . = ALIGN(4);
    /* preinit data */
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP(*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);

    . = ALIGN(4);
    /* init data */
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP(*(SORT(.init_array.*)))
    KEEP(*(.init_array))
    PROVIDE_HIDDEN (__init_array_end = .);

    . = ALIGN(4);
    /* finit data */
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP(*(SORT(.fini_array.*)))
    KEEP(*(.fini_array))
    PROVIDE_HIDDEN (__fini_array_end = .);

    KEEP(*(.jcr*))
    . = ALIGN(4);
    /* All data end */
    __data_end__ = .;

  } > RAM

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

  .heap (COPY):
  {
    __HeapBase = .;
    __end__ = .;
    end = __end__;
    _end = __end__;
    KEEP(*(.heap*))
    __HeapLimit = .;
  } > RAM

  /* .stack_dummy section doesn't contains any symbols. It is only
   * used for linker to calculate size of stack sections, and assign
   * values to stack symbols later */
  .stack_dummy (COPY):
  {
    KEEP(*(.stack*))
  } > RAM

  /* Set stack top to end of RAM, and stack limit move down by
   * size of stack_dummy section */
  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
  PROVIDE(__stack = __StackTop);

  /* Check if data + heap + stack exceeds RAM limit */
  ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")

  /* Check if CODE usage exceeds CODE size */
  ASSERT( LENGTH(CODE) >= (__etext + SIZEOF(.data)), "CODE memory overflowed !")
}

在最后一行,我Assert代码大小:

/* Check if CODE usage exceeds CODE size */
  ASSERT( LENGTH(CODE) >= (__etext + SIZEOF(.data)), "CODE memory overflowed !")

__etext应该是文本(代码)使用的实际大小,.data应该为零

hgncfbus

hgncfbus1#

有人能解释一下为什么吗?
查看链接器脚本:
CODE (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000 /* 116 page(s) */
0x 74000十六进制是475136十进制,或464 KB。
__etext应该是文本(代码)使用的实际大小,.data应该为零
不是根据链接器脚本。在发布的脚本中,__etext是代码段的结束地址。或者简单地说,代码段的大小加上它的起始地址(非零)。
换句话说,最后一个ASSERT()编码错误,过早地释放了0xB 000字节。0x 74000 - 0xB 000 = 0x 69000(或430080十进制)。

相关问题