blob: 38624a0ce1b9857af6deb7161f9fcdab28c58c5d [file] [log] [blame]
/* Layout file for Tock process binaries that use libtock-rs. This currently
* implements static linking, because we do not have a working
* position-independent relocation solution. This layout works for all
* platforms libtock-rs supports (ARM and RISC-V).
*
* This layout should be included by a script that defines the FLASH and RAM
* regions for the board as well as TBF_HEADER_SIZE. Here is a an example
* process binary linker script to get started:
* MEMORY {
* FLASH (X) : ORIGIN = 0x10000, LENGTH = 0x10000
* RAM (W) : ORIGIN = 0x20000, LENGTH = 0x10000
* }
* TBF_HEADER_SIZE = 0x40;
* INCLUDE ../libtock-rs/layout.ld
*
* FLASH refers to the area the process binary occupies in flash, including TBF
* headers. RAM refers to the area the process will have access to in memory.
* STACK_SIZE is the size of the process' stack (this layout file may round the
* stack size up for alignment purposes). TBF_HEADER_SIZE must correspond to the
* --protected-region-size flag passed to elf2tab.
*
* This places the flash sections in the following order:
* 1. .rt_header -- Constants used by runtime initialization.
* 2. .text -- Executable code.
* 3. .rodata -- Read-only global data (e.g. most string constants).
* 4. .data -- Read-write data, copied to RAM at runtime.
*
* This places the RAM sections in the following order:
* 1. .stack -- The stack grows downward. Putting it first gives us
* MPU-based overflow detection.
* 2. .data -- Read-write data, initialized by copying from flash.
* 3. .bss -- Zero-initialized read-write global data.
* 4. Heap -- The heap (optional) comes after .bss and grows upwards to
* the process break.
*/
/* GNU LD looks for `start` as an entry point by default, while LLVM's LLD looks
* for `_start`. To be compatible with both, we manually specify an entry point.
*/
ENTRY(start)
SECTIONS {
/* Sections located in FLASH at runtime.
*/
/* Add a section where elf2tab will place the TBF headers, so that the rest
* of the FLASH sections are in the right locations. */
.tbf_header (NOLOAD) : {
. = . + TBF_HEADER_SIZE;
} > FLASH
/* Runtime header. Contains values the linker knows that the runtime needs
* to look up.
*/
.rt_header : {
rt_header = .;
LONG(start);
LONG(ADDR(.bss) + SIZEOF(.bss)); /* Initial process break */
LONG(_stack_top);
LONG(SIZEOF(.data));
LONG(LOADADDR(.data));
LONG(ADDR(.data));
LONG(SIZEOF(.bss));
LONG(ADDR(.bss));
} > FLASH
/* Text section -- the application's code. */
.text ALIGN(4) : {
*(.start)
*(.text)
} > FLASH
/* Read-only data section. Contains strings and other global constants. */
.rodata ALIGN(4) : {
*(.rodata)
/* .data is placed after .rodata in flash. data_flash_start is used by
* AT() to place .data in flash as well as in rt_header.
*/
_data_flash_start = .;
} > FLASH
/* Sections located in RAM at runtime.
*/
/* Reserve space for the stack. Aligned to a multiple of 16 bytes for the
* RISC-V calling convention:
* https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
*/
.stack (NOLOAD) : {
KEEP(*(.stack_buffer))
_stack_top = ALIGN(16); /* Used in rt_header */
} > RAM
/* Read-write data section. This is deployed as part of FLASH but is copied
* into RAM at runtime.
*/
.data ALIGN(4) : AT(_data_flash_start) {
data_ram_start = .;
/* .sdata is the RISC-V small data section */
*(.sdata .data)
/* Pad to word alignment so the relocation loop can use word-sized
* copies.
*/
. = ALIGN(4);
} > RAM
/* BSS section. These are zero-initialized static variables. This section is
* not copied from FLASH into RAM but rather directly initialized, and is
* mainly put in this linker script so that we get an error if it overflows
* the RAM region.
*/
.bss ALIGN(4) (NOLOAD) : {
/* .sbss is the RISC-V small data section */
*(.sbss .bss)
} > RAM
_heap_start = ADDR(.bss) + SIZEOF(.bss); /* Used by rt_header */
/* Sections we do not need. */
/DISCARD/ :
{
*(.ARM.exidx .eh_frame)
}
}