| /* 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 (NOLOAD) : |
| { |
| /* elf2tab requires that the `_sram_origin` symbol be present to |
| * mark the first address in the SRAM memory. Since ELF files do |
| * not really need to specify this address as they only care about |
| * loading into flash, we need to manually mark this address for |
| * elf2tab. elf2tab will use it to add a fixed address header in the |
| * TBF header if needed. |
| */ |
| _sram_origin = .; |
| |
| . = . + 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*)) |
| *(.sdata*) /* RISC-V small-pointer data section */ |
| . = 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* .sbss*)) |
| *(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") |