0

I had a complicated problem that I needed to access the .data initialization data as a separate segment for an Arm bare-metal application.

I was able to achieve it using Output Section Region.

My original linker script went something like this:

SECTIONS
{
    /*
     * For Cortex-M devices, the beginning of the startup code is stored in
     * the .interrupt_vector section, which goes to FLASH
     */
    .text :
    {
        . = ALIGN(4);
        KEEP(*(.interrupt_vector))
        KEEP(*(.reset))

        *(.text .text.*)            /* all remaining code */
        *(.rodata .rodata.*)        /* read-only data (constants) */
        . = ALIGN(4);
    } >FLASH
   /*
     * This address is used by the startup code to
     * initialize the .data section.
     */
    . = ALIGN(4);
    __data_init__ = .;

    .data  : AT ( __data_init__ )
    {
        . = ALIGN(4);

        /* This is used by the startup code to initialize the .data section */
        __data_start__ = . ;
        *(.data_begin .data_begin.*)
        *(.data .data.*)
        *(.data_end .data_end.*)
        . = ALIGN(4);

        /* This is used by the startup code to initialize the .data section */
        __data_end__ = . ;
    } >RAM

    .bss (NOLOAD) :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss_begin .bss_begin.*)

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

        *(.bss_end .bss_end.*)
        . = ALIGN(4);
        __bss_end__ = .;
    } >RAM

And my startup function has:

    /* Copy .data from FLASH to RAM */
    src = &__data_init__;
    dest = &__data_start__;
    end = &__data_end__;

    while(dest < end) {
      *dest++ = *src++;
    }

I changed my linker script to:

SECTIONS
{
    /*
     * For Cortex-M devices, the beginning of the startup code is stored in
     * the .interrupt_vector section, which goes to FLASH
     */
    .text :
    {
        . = ALIGN(4);
        KEEP(*(.interrupt_vector))
        KEEP(*(.reset))

        *(.text .text.*)            /* all remaining code */
        *(.rodata .rodata.*)        /* read-only data (constants) */
        . = ALIGN(4);
    } >FLASH
    .data :
    {
        . = ALIGN(4);
        __data_init__ = LOADADDR (.data);

        /* This is used by the startup code to initialize the .data section */
        __data_start__ = . ;
        *(.data_begin .data_begin.*)
        *(.data .data.*)
        *(.data_end .data_end.*)
        . = ALIGN(4);

        /* This is used by the startup code to initialize the .data section */
        __data_end__ = . ;
    } >RAM AT > FLASH

    .bss (NOLOAD) :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss_begin .bss_begin.*)

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

        *(.bss_end .bss_end.*)
        . = ALIGN(4);
        __bss_end__ = .;
    } >RAM AT > RAM

And now I have .data as an entirely separate ELF segment:

arm-none-eabi-readelf.exe -l ../../../firmware/Cortex-M3/cm3-bootloader/Release/cm3-bootloader.elf

Elf file type is EXEC (Executable file)
Entry point 0x601b9
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010000 0x00060000 0x00060000 0x067fc 0x067fc R E 0x10000
  LOAD           0x019b30 0x20019b30 0x000667fc 0x00064 0x00064 RW  0x10000
  LOAD           0x029b2c 0x20019b2c 0x20019b2c 0x00000 0x060e8 RW  0x10000

 Section to Segment mapping:
  Segment Sections...
   00     .text .ARM.exidx.reset
   01     .data
   02     .systemclock .bss ._stack

Also, __data_init__ still points exactly where .data LMA is:

.data           0x20019b30       0x64 load address 0x000680f4
                0x20019b30                . = ALIGN (0x4)
                0x000680f4                __data_init__ = LOADADDR (.data)
                0x20019b30                __data_start__ = .

This is not a question, this is just to register how I did this in case it's helpful to someone else.

Leonardo
  • 1,533
  • 17
  • 28
  • Shouldn't you post this as a self-answer? It would help if the "question" part could explain more completely what you aimed to accomplish, and why, because that might help others with the same problem find it. You wanted to make `.data` a "separate segment" - separate from what? – Nate Eldredge Mar 03 '21 at 17:22
  • This is question dumb, the correct answer is [How to put 2 sections in 1 segment (Using ld scripts)](https://stackoverflow.com/questions/11247098/how-to-put-2-sections-in-1-segment-using-ld-scripts) – Leonardo Mar 03 '21 at 17:24

0 Answers0