Pat
Pat

Reputation: 2022

Linker Script: Mark a section as occupying space in two memory segments

I have a linker script for an embedded system that's doing some relocations (code that is loaded onto the flash of the device, but copied to RAM on boot for execution). It's using the AT feature of the linker, which seems designed to do this.

The problem is that the size of the relocation section is currently only charged to the ram memory region, when in practice it should be charged to both the rom and ram regions (it occupies the former when the device is at rest and the latter when it's active). Currently, if the data alone fits in rom but the data + relocation exceeds rom, you won't get any errors or warnings.

How do I get the .relocate section to charge its size to both the rom and ram memory regions?

Minimalized linker script:

MEMORY
{
  rom (rx)  : ORIGIN =  ROM_ORIGIN, LENGTH =  ROM_LENGTH
  ram (rwx) : ORIGIN =  RAM_ORIGIN, LENGTH =  RAM_LENGTH
}

__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x1000;

SECTIONS
{
    .text :
    {
        . = ALIGN(4);
        _stext = .;         /* First of standard s,e (start/end) pair */
        KEEP(*(.vectors .vectors.*))
        KEEP(*(.irqs))

        *(.text .text.* .gnu.linkonce.t.*)
        *(.rodata .rodata* .gnu.linkonce.r.*)
    } > rom

    /* Mark the end of static elements */
    . = ALIGN(4);
    _etext = .;

    /* This is program data that is exepected to live in SRAM, but is
     * initialized with a value. This data is physically placed into flash and
     * is copied into SRAM at boot. The symbols here will be defined with
     * addresses in SRAM.
     *
     * This is the section that needs to be charged to BOTH rom and ram */
    .relocate : AT (_etext)
    {
        . = ALIGN(4);
        _srelocate = .;
        *(.ramfunc .ramfunc.*);
        *(.data .data.*);

        . = ALIGN(4);
        _erelocate = .;
    } > ram

    .sram (NOLOAD) :
    {
        . = ALIGN(8);
         _sstack = .;

        . = . + __stack_size__;

        . = ALIGN(8);
        _estack = .;


        /* BSS section. Memory that is expected to be initialized to zero. */
        . = ALIGN(4);
        _szero = .;

        *(.bss .bss.*)
        *(COMMON)

        . = ALIGN(4);
        _ezero = .;
    } > ram
}

Or here is the complete linker script file.

Upvotes: 3

Views: 1788

Answers (1)

Pat
Pat

Reputation: 2022

We managed to solve this. The solution is to change how the location of the relocate section is specified, specifically, this is wrong:

# Bad:
.relocate : AT (_etext)
{
...
} > ram

Rather, the AT directive should go at the end, like this:

# Correct
.relocate :
{
...
} > ram AT > rom

This will cause the linker to charge the size of .relocate to both ram and rom, while placing the section "physically" in rom.

(Final applied patch to the full linker script linked in the question)

Upvotes: 3

Related Questions