Skip to content

Commit

Permalink
Use tbf_protected_region_size to indicate intended load address
Browse files Browse the repository at this point in the history
This removes the special `.tbf_header` section previously created by
`libtock-rs`, in favor of setting the `tbf_protected_region_size`
symbol and shifting the application's FLASH section by
`TBF_HEADER_SIZE`.

While adding a `.tbf_header` section is a convenient way to reserve
space for elf2tab to insert a TBF header, it causes issues with recent
versions of elf2tab and certain Rust toolchains:

- it seems that elf2tab no longer considers this region to not be
  included in the actual TBF binary. Instead, it is included and loaded
  in the final TBF, and as a result the application is offset by an
  incorrect amount (twice the `TBF_HEADER_SIZE`).

- depending on factors such as the Rust toolchain version and the
  precise FLASH address, the linker may choose to place the RAM
  section before the FLASH section in the generated ELF file. This is
  perfectly legal for the linker to do: the intended load address for
  those sections are still maintained and included in the appropriate
  section headers. Furthermore, internal references in the ELF
  file (such as the addresses in the `rt_header`) will rely on this
  ordering of sections -- meaning that elf2tab is not allowed to
  rearrange them. However, when including a `.tbf_header` section at
  the start of the FLASH section, this may then not actually be
  located at the start of the ELF binary itself.

This change tries to retain the previous semantics (developers only
specify the intended load address in their platform linker scripts),
while using a more reliable mechanism for elf2tab to prefix the
generated binary with TBF headers and a protected region that, when
prepended, aligns to this intended load address.

Most importantly, we exclude the TBF header from any of the app's
MEMORY sections, giving the linker free reign over their layout. A
special symbol, `tbf_protected_region_size`, communicates to elf2tab
the intended protected region size, which matches the FLASH-section's
ORIGIN of `$INTENDED_LOAD_ADDRESS + TBF_HEADER`.

With this change, as long as elf2tab can reliably detect the app's
fixed flash address, RAM address and `.start` symbol offset, the ELF's
particular layout should now be irrelevant for elf2tab.
  • Loading branch information
Leon Schuermann committed Jun 28, 2023
1 parent 0f7c976 commit 7b4ab7c
Show file tree
Hide file tree
Showing 20 changed files with 81 additions and 69 deletions.
8 changes: 0 additions & 8 deletions runner/src/elf2tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@ pub fn convert_elf(cli: &Cli, platform: &str) -> OutFiles {
let package_name = cli.elf.file_stem().expect("ELF must be a file");
let mut tab_path = cli.elf.clone();
tab_path.set_extension("tab");
let protected_size = TBF_HEADER_SIZE.to_string();
if cli.verbose {
println!("Package name: {:?}", package_name);
println!("TAB path: {}", tab_path.display());
println!("Protected region size: {}", protected_size);
}
let stack_size = read_stack_size(cli);
let elf = cli.elf.as_os_str();
Expand Down Expand Up @@ -71,7 +69,6 @@ pub fn convert_elf(cli: &Cli, platform: &str) -> OutFiles {
"--kernel-minor".as_ref(), "0".as_ref(),
"-n".as_ref(), package_name,
"-o".as_ref(), tab_path.as_os_str(),
"--protected-region-size".as_ref(), protected_size.as_ref(),
"--stack".as_ref(), stack_size.as_ref(),
format!("{},{}", elf.to_str().unwrap(), architecture).as_ref(),
]);
Expand Down Expand Up @@ -113,11 +110,6 @@ pub struct OutFiles {
pub tbf_path: PathBuf,
}

// The amount of space to reserve for the TBF header. This must match the
// TBF_HEADER_SIZE value in the layout file for the platform, which is currently
// 0x60 for all platforms.
const TBF_HEADER_SIZE: u32 = 0x60;

// Reads the stack size, and returns it as a String for use on elf2tab's command
// line.
fn read_stack_size(cli: &Cli) -> String {
Expand Down
7 changes: 4 additions & 3 deletions runtime/layouts/apollo3.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Apollo3 MCU, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00040000, LENGTH = 0x00060000
RAM (W) : ORIGIN = 0x10002000, LENGTH = 0x2000
FLASH (X) : ORIGIN = 0x00040000 + TBF_HEADER_SIZE, LENGTH = 0x00060000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x10002000 , LENGTH = 0x2000
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/clue_nrf52840.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the micro:bit v2 board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00080000, LENGTH = 512K
RAM (W) : ORIGIN = 0x20006000, LENGTH = 216K
FLASH (X) : ORIGIN = 0x00080000 + TBF_HEADER_SIZE, LENGTH = 512K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20006000 , LENGTH = 216K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/esp32_c3_devkitm_1.ld
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* Layout for the esp32c3 DevKit M1 board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
/* Note that the SRAM address may need to be changed depending on
* the kernel binary, check for the actual address of APP_MEMORY!
*/
FLASH (X) : ORIGIN = 0x403B0000, LENGTH = 0x30000
RAM (W) : ORIGIN = 0x3FCA1800, LENGTH = 0x2E800
FLASH (X) : ORIGIN = 0x403B0000 + TBF_HEADER_SIZE, LENGTH = 0x30000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x3FCA1800 , LENGTH = 0x2E800
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/hail.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Hail board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x00040000
RAM (W) : ORIGIN = 0x20008000, LENGTH = 62K
FLASH (X) : ORIGIN = 0x00030000 + TBF_HEADER_SIZE, LENGTH = 0x00040000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20008000 , LENGTH = 62K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/hifive1.ld
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* Layout for the RISC-V 32 boards, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
/* Note that the SRAM address may need to be changed depending on
* the kernel binary, check for the actual address of APP_MEMORY!
*/
FLASH (X) : ORIGIN = 0x20040000, LENGTH = 32M
RAM (W) : ORIGIN = 0x80002800, LENGTH = 0x1800
FLASH (X) : ORIGIN = 0x20040000 + TBF_HEADER_SIZE, LENGTH = 32M - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x80002800 , LENGTH = 0x1800
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/imix.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Imix board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00040000, LENGTH = 0x00040000
RAM (W) : ORIGIN = 0x20008000, LENGTH = 62K
FLASH (X) : ORIGIN = 0x00040000 + TBF_HEADER_SIZE, LENGTH = 0x00040000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20008000 , LENGTH = 62K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/imxrt1050.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the iMX.RT1050 board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x63002000, LENGTH = 0x1000000
RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
FLASH (X) : ORIGIN = 0x63002000 + TBF_HEADER_SIZE, LENGTH = 0x1000000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 112K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/microbit_v2.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the micro:bit v2 board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00040000, LENGTH = 256K
RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
FLASH (X) : ORIGIN = 0x00040000 + TBF_HEADER_SIZE, LENGTH = 256K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 112K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/msp432.ld
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00020000, LENGTH = 0x00020000
RAM (W) : ORIGIN = 0x20004000, LENGTH = 0x2000
FLASH (X) : ORIGIN = 0x00020000 + TBF_HEADER_SIZE, LENGTH = 0x00020000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 0x2000
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/nano_rp2040_connect.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Raspberry Pi Pico board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x10020000, LENGTH = 256K
RAM (W) : ORIGIN = 0x20004000, LENGTH = 248K
FLASH (X) : ORIGIN = 0x10020000 + TBF_HEADER_SIZE, LENGTH = 256K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 248K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/nrf52.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the nRF52-DK, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x00060000
RAM (W) : ORIGIN = 0x20004000, LENGTH = 62K
FLASH (X) : ORIGIN = 0x00030000 + TBF_HEADER_SIZE, LENGTH = 0x00060000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 62K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/nrf52840.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the nRF52840-DK, usable by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x00030000, LENGTH = 0x000D0000
RAM (W) : ORIGIN = 0x20008000, LENGTH = 46K
FLASH (X) : ORIGIN = 0x00030000 + TBF_HEADER_SIZE, LENGTH = 0x000D0000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20008000 , LENGTH = 46K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/nucleo_f429zi.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Nucleo F429zi, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x08040000, LENGTH = 255K
RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
FLASH (X) : ORIGIN = 0x08040000 + TBF_HEADER_SIZE, LENGTH = 255K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 112K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/nucleo_f446re.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Nucleo F446re, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x08040000, LENGTH = 255K
RAM (W) : ORIGIN = 0x20004000, LENGTH = 176K
FLASH (X) : ORIGIN = 0x08040000 + TBF_HEADER_SIZE, LENGTH = 255K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 176K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/opentitan.ld
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* Layout for the RISC-V 32 boards, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x80;

MEMORY {
/* Note that the SRAM address may need to be changed depending on
* the kernel binary, check for the actual address of APP_MEMORY!
*/
FLASH (X) : ORIGIN = 0x20030000, LENGTH = 32M
RAM (W) : ORIGIN = 0x10004000, LENGTH = 512K
FLASH (X) : ORIGIN = 0x20030000 + TBF_HEADER_SIZE, LENGTH = 32M - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x10004130 , LENGTH = 512K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/raspberry_pi_pico.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the Raspberry Pi Pico board, used by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x10040000, LENGTH = 256K
RAM (W) : ORIGIN = 0x20011800, LENGTH = 194K
FLASH (X) : ORIGIN = 0x10040000 + TBF_HEADER_SIZE, LENGTH = 256K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20011800, LENGTH = 194K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/stm32f3discovery.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the stm32f3discovery board, usable by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x08020000, LENGTH = 0x00020000
RAM (W) : ORIGIN = 0x20004000, LENGTH = 48K
FLASH (X) : ORIGIN = 0x08020000 + TBF_HEADER_SIZE, LENGTH = 0x00020000 - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 48K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
7 changes: 4 additions & 3 deletions runtime/layouts/stm32f412gdiscovery.ld
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* Layout for the stm32f412gdiscovery board, usable by the examples in this repository. */

TBF_HEADER_SIZE = 0x60;

MEMORY {
FLASH (X) : ORIGIN = 0x08030000, LENGTH = 256K
RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K
FLASH (X) : ORIGIN = 0x08030000 + TBF_HEADER_SIZE, LENGTH = 256K - TBF_HEADER_SIZE
RAM (W) : ORIGIN = 0x20004000 , LENGTH = 112K
}

TBF_HEADER_SIZE = 0x60;
INCLUDE libtock_layout.ld
16 changes: 9 additions & 7 deletions runtime/libtock_layout.ld
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,21 @@
ENTRY(start)

SECTIONS {
/* Sections located in FLASH at runtime.
/* The FLASH memory section is placed at a TBF_HEADER_SIZE offset, to give
* elf2tab room to prepend the TBF headers. Communicate this reservation to
* elf2tab, such that it fills up the space after the TBF headers (if any)
* as part of the protected region trailer:
*/
tbf_protected_region_size = TBF_HEADER_SIZE;

/* 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
/* Sections located in FLASH at runtime.
*/

/* Runtime header. Contains values the linker knows that the runtime needs
* to look up.
*/
.start ALIGN(4) : {
. = ALIGN(4);
.start : {
/* We combine rt_header and _start into a single section. If we don't,
* elf2tab does not parse the ELF file correctly for unknown reasons.
*/
Expand Down

0 comments on commit 7b4ab7c

Please sign in to comment.