Skip to content
Snippets Groups Projects
layout.ld 4.84 KiB
Newer Older
Jean-Michel Picod's avatar
Jean-Michel Picod committed
/* Userland Generic Layout
 *
 * Currently, due to incomplete ROPI-RWPI support in rustc (see
 * https://github.com/tock/libtock-rs/issues/28), this layout implements static
 * linking. An application init script must define the FLASH and SRAM address
 * ranges as well as MPU_MIN_ALIGN before including this layout file.
 *
 * Here is a an example application linker script to get started:
 *     MEMORY {
 *         /* FLASH memory region must start immediately *after* the Tock
 *          * Binary Format headers, which means you need to offset the
 *          * beginning of FLASH memory region relative to where the
 *          * application is loaded.
 *         FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0
 *         SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000
 *     }
 *     STACK_SIZE = 2048;
 *     MPU_MIN_ALIGN = 8K;
 *     INCLUDE ../libtock-rs/layout.ld
 */

ENTRY(_start)

SECTIONS {
    /* Section for just the app crt0 header.
     * This must be first so that the app can find it.
     */
    .crt0_header :
    {
        _beginning = .; /* Start of the app in flash. */
        /**
         * Populate the header expected by `crt0`:
         *
         *  struct hdr {
         *    uint32_t got_sym_start;
         *    uint32_t got_start;
         *    uint32_t got_size;
         *    uint32_t data_sym_start;
         *    uint32_t data_start;
         *    uint32_t data_size;
         *    uint32_t bss_start;
         *    uint32_t bss_size;
         *    uint32_t reldata_start;
         *    uint32_t stack_size;
         *  };
         */
        /* Offset of GOT symbols in flash */
        LONG(LOADADDR(.got) - _beginning);
        /* Offset of GOT section in memory */
        LONG(_got);
        /* Size of GOT section */
        LONG(SIZEOF(.got));
        /* Offset of data symbols in flash */
        LONG(LOADADDR(.data) - _beginning);
        /* Offset of data section in memory */
        LONG(_data);
        /* Size of data section */
        LONG(SIZEOF(.data));
        /* Offset of BSS section in memory */
        LONG(_bss);
        /* Size of BSS section */
        LONG(SIZEOF(.bss));
        /* First address offset after program flash, where elf2tab places
         * .rel.data section */
        LONG(LOADADDR(.endflash) - _beginning);
        /* The size of the stack requested by this application */
        LONG(STACK_SIZE);
        /* Pad the header out to a multiple of 32 bytes so there is not a gap
         * between the header and subsequent .data section. It's unclear why,
         * but LLD is aligning sections to a multiple of 32 bytes. */
        . = ALIGN(32);
    } > FLASH =0xFF

    /* Text section, Code! */
    .text :
    {
        . = ALIGN(4);
        _text = .;
        KEEP (*(.start))
        *(.text*)
        *(.rodata*)
        KEEP (*(.syscalls))
        *(.ARM.extab*)
        . = ALIGN(4); /* Make sure we're word-aligned here */
        _etext = .;
    } > FLASH =0xFF

    /* Application stack */
    .stack :
    {
        . = . + STACK_SIZE;

	_stack_top_unaligned = .;
        . = ALIGN(8);
	_stack_top_aligned = .;
    } > SRAM

    /* Data section, static initialized variables
     *  Note: This is placed in Flash after the text section, but needs to be
     *  moved to SRAM at runtime
     */
    .data : AT (_etext)
    {
        . = ALIGN(4); /* Make sure we're word-aligned here */
        _data = .;
        KEEP(*(.data*))
        . = ALIGN(4); /* Make sure we're word-aligned at the end of flash */
    } > SRAM

    /* Global Offset Table */
    .got :
    {
        . = ALIGN(4); /* Make sure we're word-aligned here */
        _got = .;
        *(.got*)
        *(.got.plt*)
        . = ALIGN(4);
    } > SRAM

    /* BSS section, static uninitialized variables */
    .bss :
    {
        . = ALIGN(4); /* Make sure we're word-aligned here */
        _bss = .;
        KEEP(*(.bss*))
        *(COMMON)
        . = ALIGN(4);
    } > SRAM

    /* End of flash. */
    .endflash :
    {
    } > FLASH

    /* ARM Exception support
     *
     * This contains compiler-generated support for unwinding the stack,
     * consisting of key-value pairs of function addresses and information on
     * how to unwind stack frames.
     * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf
     *
     * .ARM.exidx is sorted, so has to go in its own output section.
     *
     * __NOTE__: It's at the end because we currently don't actually serialize
     * it to the binary in elf2tbf. If it was before the RAM sections, it would
     * through off our calculations of the header.
     */
    PROVIDE_HIDDEN (__exidx_start = .);
    .ARM.exidx :
    {
      /* (C++) Index entries for section unwinding */
      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > FLASH
    PROVIDE_HIDDEN (__exidx_end = .);
}

ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, "
STACK_SIZE must be 8 byte multiple")