Skip to content

Commit 8037168

Browse files
committed
Stop using r0 crate for user programs.
r0 is likely unsound. This replaces the data/bss init with an assembly routine that is guaranteed not to get mangled by the compiler. Context: rust-lang/unsafe-code-guidelines#259
1 parent cd91bce commit 8037168

File tree

4 files changed

+63
-28
lines changed

4 files changed

+63
-28
lines changed

Cargo.lock

+1-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

task-link.x

+6-4
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ SECTIONS
2929
__erodata = .;
3030
} > FLASH
3131

32-
/* ## Sections in RAM */
33-
/* ### .data */
32+
/*
33+
* Sections in RAM
34+
*
35+
* NOTE: the userlib runtime assumes that these sections
36+
* are 4-byte aligned and padded to 4-byte boundaries.
37+
*/
3438
.data : AT(__erodata) ALIGN(4)
3539
{
3640
. = ALIGN(4);
@@ -43,7 +47,6 @@ SECTIONS
4347
/* LMA of .data */
4448
__sidata = LOADADDR(.data);
4549

46-
/* ### .bss */
4750
.bss : ALIGN(4)
4851
{
4952
. = ALIGN(4);
@@ -53,7 +56,6 @@ SECTIONS
5356
__ebss = .;
5457
} > RAM
5558

56-
/* ### .uninit */
5759
.uninit (NOLOAD) : ALIGN(4)
5860
{
5961
. = ALIGN(4);

userlib/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ log-semihosting = []
1212

1313
[dependencies]
1414
abi = {path = "../abi"}
15-
r0 = "1.0.0"
1615
serde = { version = "1.0.114", default-features = false }
1716
ssmarshal = { version = "1.0.0", default-features = false }
1817
zerocopy = "0.3.0"

userlib/src/lib.rs

+56-15
Original file line numberDiff line numberDiff line change
@@ -802,29 +802,70 @@ macro_rules! sys_log {
802802
#[doc(hidden)]
803803
#[no_mangle]
804804
#[link_section = ".text.start"]
805+
#[naked]
805806
pub unsafe extern "C" fn _start() -> ! {
806-
// Symbols from the linker script:
807-
extern "C" {
808-
static mut __sbss: u32;
809-
static mut __ebss: u32;
810-
static mut __sdata: u32;
811-
static mut __edata: u32;
812-
static __sidata: u32;
813-
}
814-
815807
// Provided by the user program:
816808
extern "Rust" {
817809
fn main() -> !;
818810
}
819811

820-
// Initialize RAM
821-
r0::zero_bss(&mut __sbss, &mut __ebss);
822-
r0::init_data(&mut __sdata, &mut __edata, &__sidata);
812+
asm!("
813+
@ Copy data initialization image into data section.
814+
@ Note: this assumes that both source and destination are 32-bit
815+
@ aligned and padded to 4-byte boundary.
816+
817+
movw r0, #:lower16:__edata @ upper bound in r0
818+
movt r0, #:upper16:__edata
819+
820+
movw r1, #:lower16:__sidata @ source in r1
821+
movt r1, #:upper16:__sidata
822+
823+
movw r2, #:lower16:__sdata @ dest in r2
824+
movt r2, #:upper16:__sdata
825+
826+
b 1f @ check for zero-sized data
827+
828+
2: ldr r3, [r1], #4 @ read and advance source
829+
str r3, [r2], #4 @ write and advance dest
830+
831+
1: cmp r2, r0 @ has dest reached the upper bound?
832+
bne 2b @ if not, repeat
833+
834+
@ Zero BSS section.
823835
824-
// Do *not* reorder any instructions from main above this point.
825-
core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
836+
movw r0, #:lower16:__ebss @ upper bound in r0
837+
movt r0, #:upper16:__ebss
826838
827-
main()
839+
movw r1, #:lower16:__sbss @ base in r1
840+
movt r1, #:upper16:__sbss
841+
842+
movs r2, #0 @ materialize a zero
843+
844+
b 1f @ check for zero-sized BSS
845+
846+
2: str r2, [r1], #4 @ zero one word and advance
847+
848+
1: cmp r1, r0 @ has base reached bound?
849+
bne 2b @ if not, repeat
850+
851+
@ Be extra careful to ensure that those side effects are
852+
@ visible to the user program.
853+
854+
dsb @ complete all writes
855+
isb @ and flush the pipeline
856+
857+
@ Now, to the user entry point. We call it in case it
858+
@ returns. (It's not supposed to.) We reference it through
859+
@ a sym operand because it's a Rust func and may be mangled.
860+
bl {main}
861+
862+
@ The noreturn option below will automatically generate an
863+
@ undefined instruction trap past this point, should main
864+
@ return.
865+
",
866+
main = sym main,
867+
options(noreturn),
868+
)
828869
}
829870

830871
#[cfg(feature = "panic-messages")]

0 commit comments

Comments
 (0)