| /* 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 | |
| * } | |
| * 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_top_aligned - _sstack); | |
| /* 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 = .; | |
| _sstack = .; | |
| KEEP(*(.stack_buffer)) | |
| _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") |