blob: d11d311f9e2a39edaccc0933e5270d3130400e53 [file] [log] [blame]
/*
* This is the generic linker script for Tock. For most developers, it should
* be sufficient to define {ROM/PROG/RAM}_{ORIGIN/LENGTH} (6 variables, the
* start and length for each), MPU_MIN_ALIGN (the minimum alignment
* granularity supported by the MPU) and PAGE_SIZE (the size of a flash page).
* If undefined, PAGE_SIZE uses the default value of 512 bytes.
*
* --------------------------------------------------------------------------
*
* If you wish to create your own linker script from scratch, you must define
* the following symbols:
*
* `_etext`, `_srelocate`, `_erelocate`
* The `_etext` symbol marks the end of data stored in flash that should
* stay in flash. `_srelocate` and `_erelocate` mark the address range in
* SRAM that mutable program data is copied to.
*
* Tock will copy `_erelocate` - `_srelocate` bytes of data from the
* `_etext` pointer to the `_srelocate` pointer.
*
* `_szero`, `_ezero`
*
* The `_szero` and `_ezero` symbols define the range of the BSS, SRAM that
* Tock will zero on boot.
*
* `_sapps`, `_eapps`
*
* The `_sapps` symbol marks the beginning of application memory in flash.
* The `_eapps` symbol marks the end of application memory in flash by
* pointing to next address after application flash.
*
* `_sappmem`, `_eappmem`
*
* The `_sappmem` symbol marks the beginning of application memory in RAM.
* The `_eappmem` symbol marks the end of application memory in RAM by
* pointing to next address after application RAM.
*/
PAGE_SIZE = DEFINED(PAGE_SIZE) ? PAGE_SIZE : 512;
SECTIONS
{
.stack (NOLOAD) :
{
/* Kernel stack.
*
* Tock places the kernel stack at the bottom of SRAM so that the
* kernel will trigger memory fault if it exceeds its stack depth,
* rather than silently overwriting valuable data.
*/
. = ALIGN(8);
_sstack = .;
/* For GNU LD, we can just advance the location pointer (".") here to
* reserve space for the stack. That, however, doesn't seem to work
* for LLVM LLD. The resulting ELF has a stack section that shows the
* correct size, but the next section (in our case .relocate) is not
* moved down as well, instead it sits at the same address as .stack.
* To work around this, we declare a dummy buffer and then insert it
* here in the .stack section. This sets the stack size correctly and
* places the .relocate section at the correct address. */
KEEP(*(.stack_buffer))
/*. = . + 0x1000;*/ /*This is the original method. */
. = ALIGN(8);
_estack = .;
} > ram
/* STATIC ELEMENTS FOR TOCK KERNEL */
.text :
{
. = ALIGN(4);
_textstart = .; /* Symbol expected by some MS build toolchains */
_stext = .; /* First of standard s,e (start/end) pair */
/* Place vector table at the beginning of ROM.
*
* The first 16 entries in the ARM vector table are defined by ARM and
* are common among all ARM chips. The remaining entries are
* chip-specific, which Tock defines in a separate .irqs section
*
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BABIFJFG.html
*/
KEEP(*(.vectors .vectors.*))
KEEP(*(.irqs))
/* RISC-V
* There is no vector table in RISCV, so .vectors and .irqs will be
* empty. Instead, the _start function needs to be first in the binary
* for it to correctly be executed. We also need to include the trap
* handler assembly function.
*
* These are expected to just be empty on other platforms so they
* shouldn't have any effect.
*/
KEEP(*(.riscv.start));
/* For RISC-V we need the `_start_trap` function to be 256 byte aligned,
* and that function is at the start of the .riscv.trap section. If that
* function does not exist (as for non-RISC-V platforms) then we do not
* need any unusual alignment.
* The allignment is implementation specific, so we currently use 256 to
* work with the lowRISC CPUs.
*/
. = DEFINED(_start_trap) ? ALIGN(256) : ALIGN(1);
KEEP(*(.riscv.trap_vectored));
KEEP(*(.riscv.trap));
/* .text and .rodata hold most program code and immutable constants */
/* .gnu.linkonce hold C++ elements with vague linkage
https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html */
*(.text .text.* .gnu.linkonce.t.*)
*(.rodata .rodata.* .gnu.linkonce.r.*)
/* C++ exception unwinding information */
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* glue_7 and glue_7t hold helper functions emitted by the compiler to
support interworking (linking between functions in ARM and THUMB
mode). Note that Cortex-M's do not support ARM mode, but this is left
here to save someone headache if they ever attempt to port Tock to a
Cortex-A core. */
*(.glue_7t) *(.glue_7)
/* Constructor and destructor sections:
- init/fini
Defined by ELF as sections that hold `process
initialization/termination code`
- {pre}{init/fini}_array_{start/end}
Symbols used by the C runtime for initialization / termination
- ctors/dtors
Symbols used by the C++ runtime for initialization / termination
*/
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
/* End constructor/destructor */
} > rom
/* 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.
*/
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
/* (C++) Index entries for section unwinding */
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
/* Region for on-chip kernel non-volatile storage.
*
* Align on PAGE_SIZE number of bytes. Volumes within this region are
* allocated with the storage_volume! macro in utils.rs.
*/
.storage :
{
. = ALIGN(PAGE_SIZE);
_sstorage = .;
*(.storage* storage*)
_estorage = .;
. = ALIGN(PAGE_SIZE);
} > rom
. = ALIGN(PAGE_SIZE);
/* Mark the end of static elements */
. = ALIGN(4);
_etext = .;
_textend = .; /* alias for _etext expected by some MS toolchains */
/* Customer configuration is most often located at the end of the rom. It is
* conditional, and won't be written if not specified in the board specific
* linker file.
*/
.ccfg : {
KEEP(*(.ccfg))
} > ccfg
/* Section for application binaries in flash.
*
* This section is put into the "prog" memory, which is reserved for
* applications. This section is not used for the kernel, but including it
* in the .elf file allows for concatenating application binaries with the
* kernel.
*/
.apps :
{
/* _sapps symbol used by Tock to look for first application. */
. = ALIGN(4);
_sapps = .;
/* Include a placeholder byte in this section so that the linker
* includes a segment for it. Otherwise the section will be empty and
* the linker will ignore it when defining the segments.
*/
BYTE(0)
} > prog
/* _eapps symbol used by tock to calculate the length of app flash */
_eapps = _sapps + LENGTH(prog);
/* Kernel data that must be relocated. This is program data that is
* expected to live in SRAM, but is initialized with a value. This data is
* physically placed into flash and is copied into SRAM by Tock. The
* symbols here will be defined with addresses in SRAM.
*
* Tock assumes the relocation section follows all static elements and will
* copy (_erelocate - _srelocate) bytes from _etext to _srelocate.
*/
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
/* The Global Pointer is used by the RISC-V architecture to provide
* "gp-relative" addressing. The global pointer is set to the gp
* register once on boot, and the linker can then take advantage of this
* when emitting instructions by using offsets relative to this known
* value. Since RISC-V has only 12 bit immediates, this can help reduce
* code size.
*
* The standard is to set the global pointer to 0x800 past the beginning
* of the data section in RAM. This allows instructions to use 12 bit
* immediates to access the first 4KB of data memory. In theory the GP
* can be set to any value, but it should be placed near actual data for
* the compiler to actually be able to use it.
*
* Per convention, the variable _must_ be called __global_pointer$ for
* the linker to actually take advantage of it.
*/
PROVIDE(__global_pointer$ = . + 0x800);
*(.ramfunc .ramfunc.*);
*(.sdata .sdata.* .gnu.linkonce.r.*)
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
.sram (NOLOAD) :
{
/* Kernel BSS section. Memory that is expected to be initialized to
* zero.
*
* Elements in this section do not contribute to the binary size. Tock
* initialization will write zeros to the memory between _szero and
* _ezero.
*
* Elements placed in the .bss and .COMMON sections are simply used to
* measure amount of memory to zero out.
*/
. = ALIGN(4);
_szero = .;
/* In addition to the traditional .bss section, RISC-V splits out a "small data" section
* see: https://github.com/riscv/riscv-pk/blob/a3e4ac61d2b1ff37a22b9193b85d3b94273e80cb/pk/pk.lds#L84
*/
*(.sbss .sbss.* .bss .bss.*);
*(COMMON)
. = ALIGN(4);
_ezero = .;
/* Application Memory.
*
* Tock uses the remainder of SRAM for application memory.
*
* Currently, Tock allocates a fixed array of application memories at
* compile-time, and that array is simply placed here. A possible
* future enhancement may allow the kernel to parcel this memory space
* dynamically, requiring changes to this section.
*/
. = ALIGN(MPU_MIN_ALIGN);
_sappmem = .;
*(.app_memory)
} > ram
_eappmem = ORIGIN(ram) + LENGTH(ram);
/* Discard RISC-V relevant .eh_frame, we are not doing unwind on panic
so it is not needed. */
/DISCARD/ :
{
*(.eh_frame);
}
}
ASSERT((_etext-_stext) + (_erelocate-_srelocate) < LENGTH(rom), "
Text plus relocations exceeds the available ROM space.");