user654789384
user654789384

Reputation: 395

GCC BareMetal Linker Issue - Cortex M3

I have an issue during the linkage of my project. I use the GCC linker script from the manufacturer.

In there, i define the code section as follows:

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

so the code section beginning is located at 0xB000 and has a length of 0x74000. The length is 116 x 4096 bytes => 475136 bytes code size

my binary builds with the following size:

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

therefore, it should link OK since the used size of 432372 (text + data) is way smaller than the available space of 475136.

it links ok as long as the binary code size is < ~422kBytes, as soon as it gets bigger, the linker tells me CODE section overflow, cannot link.

can someone explain me why not? i cannot see a reason for the link to tell me my code is too big, because it is not!

LINKER SCRIPT

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 !")
}

at the last lines, i assert code size:

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

__etext should be the actual size of text (code) usage, .data should be zero

Upvotes: 0

Views: 403

Answers (1)

Turbo J
Turbo J

Reputation: 7691

can someone explain me why not?

Just look into the linker script:

CODE (rx ) : ORIGIN = 0x0000B000, LENGTH = 0x00074000 /* 116 page(s) */

0x74000 hex is ‭475136‬ decimal, or 464KB.

__etext should be the actual size of text (code) usage, .data should be zero

Not according to the linker script. In the posted script, __etext is the end address of the code segment. Or simply the size of the code segment plus its start address (which is nonzero).

In other words, your last ASSERT() is coded wrong and bails out 0xB000 bytes too early. And 0x74000-0xB000 = 0x69000 (or ‭430080‬ decimal).

Upvotes: 2

Related Questions