Strange linker behavior or broken map file in case of assembler memory arrays allocated using .skip or .space

Asked by Tamas Kleiber

Hi,

 I am using GCC ARM Embedded 4.7 update 4. I am using the standard assembler start-up file templates from ARM CMSIS 4.2 (CMSIS-SP-00300-r4p2-00rel0) for ARM Cortex-M3.

The system heap and system stack are allocated as follows (only stack is shown, heap is very similar; stripped down inactive conditional switches):

 .syntax unified
 .arch armv7-m

 .section .stack
 .align 3
 .equ Stack_Size, __STACK_SIZE
 .globl __StackTop
 .globl __StackLimit
__StackLimit:
 .space Stack_Size
 .size __StackLimit, . - __StackLimit
__StackTop:
 .size __StackTop, . - __StackTop

The linker script is again the same basic setup from CMSIS (stripped down comments):

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

 .stack_dummy (COPY):
 {
  KEEP(*(.stack*))
 } > RAM

 __StackTop = ORIGIN(RAM) + LENGTH(RAM);
 __StackLimit = __StackTop - SIZEOF(.stack_dummy);
 PROVIDE(__stack = __StackTop);

The produced map file for such a configuration with base default RAM memory region (no fancy changes, or anything special) looks as follows:

.heap 0x20003730 0x358
                0x20003730 __end__ = .
                0x20003730 end = __end__
                0x20003730 _end = __end__
 *(.heap*)
 .heap 0x20003730 0x358 build/startup.o
                0x20003730 __HeapBase
                0x20003a88 __HeapLimit = .

.stack_dummy 0x20003730 0x100
 *(.stack)
 .stack 0x20003730 0x100 build/startup.o
                0x20020000 __StackTop = (ORIGIN (RAM) + 0x20000)
                0x2001ff00 __StackLimit = (__StackTop - SIZEOF (.stack_dummy))
                0x20020000 PROVIDE (__stack, __StackTop)

Why does the .heap and .stack_dummy sections start from the same address?

__HeapLimit is correctly set by using the "." variable which is the actual location pointer used by ld. So based on the linker script above ld should not reset the location pointer back to the address of __HeapBase when the actual location is already at __HeapLimit.

The issue seems to be somehow related to the assembler start-up code and the use of the .space (same as .skip) keyword to allocate space for an array in assembly.

Do you know what could be the problem? Or how to overcome the issue without switching to the C implementation of the startup file from ARM CMSIS? The __StackTop and __StackLimit symbols are correctly set I know, but as soon as I would want to relocate the system heap or the system stack to somewhere else it really causes problems...

Thanks in advance for your kind response.

Best regards,
 Tamas

_

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Tamas Kleiber
Solved:
Last query:
Last reply:
Revision history for this message
Joey Ye (jinyun-ye) said :
#1

Tamas,

Heap and stack are dummy in this case, as they were specified (COPY)
attribute. If you going to make then real sections and relocate them,
please just try remove the (COPY) attribute.

Thanks,
Joey

On Wed, Dec 10, 2014 at 9:36 PM, Tamas Kleiber <
<email address hidden>> wrote:

> New question #258876 on GCC ARM Embedded:
> https://answers.launchpad.net/gcc-arm-embedded/+question/258876
>
> Hi,
>
> I am using GCC ARM Embedded 4.7 update 4. I am using the standard
> assembler start-up file templates from ARM CMSIS 4.2
> (CMSIS-SP-00300-r4p2-00rel0) for ARM Cortex-M3.
>
> The system heap and system stack are allocated as follows (only stack is
> shown, heap is very similar; stripped down inactive conditional switches):
>
> .syntax unified
> .arch armv7-m
>
> .section .stack
> .align 3
> .equ Stack_Size, __STACK_SIZE
> .globl __StackTop
> .globl __StackLimit
> __StackLimit:
> .space Stack_Size
> .size __StackLimit, . - __StackLimit
> __StackTop:
> .size __StackTop, . - __StackTop
>
> The linker script is again the same basic setup from CMSIS (stripped down
> comments):
>
> .heap (COPY):
> {
> __HeapBase = .;
> __end__ = .;
> end = __end__;
> KEEP(*(.heap*))
> __HeapLimit = .;
> } > RAM
>
> .stack_dummy (COPY):
> {
> KEEP(*(.stack*))
> } > RAM
>
> __StackTop = ORIGIN(RAM) + LENGTH(RAM);
> __StackLimit = __StackTop - SIZEOF(.stack_dummy);
> PROVIDE(__stack = __StackTop);
>
>
> The produced map file for such a configuration with base default RAM
> memory region (no fancy changes, or anything special) looks as follows:
>
> .heap 0x20003730 0x358
> 0x20003730 __end__ = .
> 0x20003730 end = __end__
> 0x20003730 _end = __end__
> *(.heap*)
> .heap 0x20003730 0x358 build/startup.o
> 0x20003730 __HeapBase
> 0x20003a88 __HeapLimit = .
>
> .stack_dummy 0x20003730 0x100
> *(.stack)
> .stack 0x20003730 0x100 build/startup.o
> 0x20020000 __StackTop = (ORIGIN (RAM) +
> 0x20000)
> 0x2001ff00 __StackLimit = (__StackTop -
> SIZEOF (.stack_dummy))
> 0x20020000 PROVIDE (__stack, __StackTop)
>
>
> Why does the .heap and .stack_dummy sections start from the same address?
>
> __HeapLimit is correctly set by using the "." variable which is the actual
> location pointer used by ld. So based on the linker script above ld should
> not reset the location pointer back to the address of __HeapBase when the
> actual location is already at __HeapLimit.
>
> The issue seems to be somehow related to the assembler start-up code and
> the use of the .space (same as .skip) keyword to allocate space for an
> array in assembly.
>
> Do you know what could be the problem? Or how to overcome the issue
> without switching to the C implementation of the startup file from ARM
> CMSIS? The __StackTop and __StackLimit symbols are correctly set I know,
> but as soon as I would want to relocate the system heap or the system stack
> to somewhere else it really causes problems...
>
>
> Thanks in advance for your kind response.
>
> Best regards,
> Tamas
>
> _
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Tamas Kleiber (kleiber-tamas) said :
#2

Hi Joey,

 I already tried many things, including removing the (COPY) tag. I even tried with (NOLOAD) tag plus { ... }>RAM AT>RAM to get rid of the invalid load addresses which are showing up in the map file normally for the .heap and .stack sections to see whether it makes any difference. Apparently no.

Revision history for this message
Tamas Kleiber (kleiber-tamas) said :
#3

I solved the issue by explicitly setting the VMA address of the section found after .heap and .stack.

Example:

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

  .stack ADDR(.heap) + SIZEOF(.heap) (NOLOAD) :
  {
    . = ALIGN (8);
    __StackLimit = .;
    KEEP(*(.stack*))
    __StackTop = .;
  } > RAM