From 572cd5a5a2a4901bfe2a8b4df4de559a77bff282 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Thu, 29 Jun 2023 08:49:09 -0400 Subject: [PATCH 1/2] runtime/libtock_layout.ld: place `.data` into FLASH at next offset There's no reason as to why `.data` should be placed directly after `.rodata` in FLASH. We can use the `> $VMASEGMENT AT > $LMASEGMENT` syntax to simply place it at the next well-aligned offset in the FLASH segment. This reduces the overall complexity of the linker scripts, and avoids accidentally placing multiple sections at competing addresses. --- runtime/libtock_layout.ld | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/runtime/libtock_layout.ld b/runtime/libtock_layout.ld index 5463f26a..7efd3e74 100644 --- a/runtime/libtock_layout.ld +++ b/runtime/libtock_layout.ld @@ -81,10 +81,6 @@ SECTIONS { /* 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. @@ -107,7 +103,7 @@ SECTIONS { /* 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 ALIGN(4) : { data_ram_start = .; /* .sdata is the RISC-V small data section */ *(.sdata .data) @@ -115,7 +111,7 @@ SECTIONS { * copies. */ . = ALIGN(4); - } > RAM + } > RAM AT > FLASH /* BSS section. These are zero-initialized static variables. This section is * not copied from FLASH into RAM but rather directly initialized, and is From 536dcf85184cce5828e1862a46217748c4a7f130 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Thu, 29 Jun 2023 08:52:00 -0400 Subject: [PATCH 2/2] runtime/libtock_layout.ld: use FLASH-segment LMAs for all sections Previously, `.stack` and `.bss` sections were simply instructed to be placed into RAM. Without an explicitly specified load address or load address region, this means that their ELF-segment's `PhysAddr` will be set to its `VirtAddr` (and hence point into RAM): Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001000 0x20030000 0x20030000 0x00000 0x00060 R 0x1000 LOAD 0x001060 0x20030060 0x20030060 0x00d64 0x00d64 R E 0x1000 LOAD 0x001dc4 0x20030dc4 0x20030dc4 0x001ec 0x001ec R 0x1000 LOAD 0x002000 0x10004000 0x10004000 0x00000 0x00100 RW 0x1000 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0 Section to Segment mapping: Segment Sections... 00 .tbf_header 01 .start .text 02 .rodata 03 .stack 04 When, for any reason, these segments contain any actual data (`FileSiz` != 0), for instance under certain alignment constraints[1], this will cause a ROM-loader such as elf2tab to place them at their specified `PhysAddr` offset. As a result, if `ORIGIN(FLASH)` precedes `ORIGIN(RAM)`, the binary is blown up due to padding. If `ORIGIN(RAM)` precedes `ORIGIN(FLASH)`, the `rt_header` internal offsets are incorrect because the actual FLASH load address is now offset by `ORIGIN(FLASH) - ORIGIN(RAM)`. With this change, no `LOAD`able segment will have a `PhysAddr` outside of the `FLASH` memory region. This does not have any effect on zero-sized sections (they will not increase flash usage): Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x001000 0x20030000 0x20030000 0x00fb0 0x00fb0 RWE 0x1000 LOAD 0x000800 0x10004800 0x20030fb0 0x00000 0x00100 RW 0x1000 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 Section to Segment mapping: Segment Sections... 00 .tbf_header .start .text .rodata 01 .stack 02 The reason why this worked in the past was that `elf2tab` skipped segments with a `FileSiz` == 0, and did so even before calculating paddings. We should probably not rely on such an implementation detail of our loader, which can further break if the linker were to insert any padding into a segment. [1]: See https://github.com/tock/libtock-rs/pull/477 for an example. --- runtime/libtock_layout.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/libtock_layout.ld b/runtime/libtock_layout.ld index 7efd3e74..f5555c92 100644 --- a/runtime/libtock_layout.ld +++ b/runtime/libtock_layout.ld @@ -98,7 +98,7 @@ SECTIONS { KEEP(*(.stack_buffer)) . = ALIGN(16); _stack_top = .; /* Used in rt_header */ - } > RAM + } > RAM AT > FLASH /* Read-write data section. This is deployed as part of FLASH but is copied * into RAM at runtime. @@ -121,7 +121,7 @@ SECTIONS { .bss ALIGN(4) (NOLOAD) : { /* .sbss is the RISC-V small data section */ *(.sbss .bss.*) - } > RAM + } > RAM AT > FLASH _heap_start = ADDR(.bss) + SIZEOF(.bss); /* Used by rt_header */