From 641b820b1c54146ca5f4ee762212fa91385d067b Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Mon, 8 Jul 2024 22:17:49 +0000 Subject: [PATCH 01/20] trivial: Remove trailing whitespace Signed-off-by: Nick Spinale --- crates/examples/microkit/banscii/pds/serial-driver/Cargo.nix | 1 - crates/sel4-capdl-initializer/core/Cargo.nix | 1 - crates/sel4-shared-ring-buffer/smoltcp/Cargo.nix | 1 - hacking/cargo-manifest-management/README.md | 2 +- hacking/nix/scope/default.nix | 2 +- 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/examples/microkit/banscii/pds/serial-driver/Cargo.nix b/crates/examples/microkit/banscii/pds/serial-driver/Cargo.nix index 1aa5bfcb3..849699bff 100644 --- a/crates/examples/microkit/banscii/pds/serial-driver/Cargo.nix +++ b/crates/examples/microkit/banscii/pds/serial-driver/Cargo.nix @@ -12,7 +12,6 @@ mk { inherit (localCrates) sel4-microkit-message sel4-microkit-driver-adapters - ; sel4-microkit = localCrates.sel4-microkit // { default-features = false; }; sel4-pl011-driver = localCrates.sel4-pl011-driver // { optional = true; }; diff --git a/crates/sel4-capdl-initializer/core/Cargo.nix b/crates/sel4-capdl-initializer/core/Cargo.nix index b47850cbd..b8260a931 100644 --- a/crates/sel4-capdl-initializer/core/Cargo.nix +++ b/crates/sel4-capdl-initializer/core/Cargo.nix @@ -8,7 +8,6 @@ mk { package.name = "sel4-capdl-initializer-core"; - dependencies = { inherit (versions) log; inherit (localCrates) diff --git a/crates/sel4-shared-ring-buffer/smoltcp/Cargo.nix b/crates/sel4-shared-ring-buffer/smoltcp/Cargo.nix index 5d3f3a8e7..71de65be2 100644 --- a/crates/sel4-shared-ring-buffer/smoltcp/Cargo.nix +++ b/crates/sel4-shared-ring-buffer/smoltcp/Cargo.nix @@ -18,5 +18,4 @@ mk { ; sel4-externally-shared = localCrates.sel4-externally-shared // { features = [ "unstable" ]; }; }; - } diff --git a/hacking/cargo-manifest-management/README.md b/hacking/cargo-manifest-management/README.md index b7d8225ca..054224cf7 100644 --- a/hacking/cargo-manifest-management/README.md +++ b/hacking/cargo-manifest-management/README.md @@ -28,7 +28,7 @@ Concrete benefits of using this tool include: - The ability to refer to version bounds and Git sources of remote dependencies symbolically. Using consistent version bounds and Git sources for each instance of a given remote dependency throughout the project enables proper dependency resolution. Referring to these symbolically makes - this less tedious, and also makes updating dependencies in an intentional way easy. + this less tedious, and also makes updating dependencies in an intentional way easy. You don't need to have experience with Nix to create and modify `Cargo.nix` files. They are written using the Nix programming language, but they don't depend on any of the advanced features of Nixpkgs diff --git a/hacking/nix/scope/default.nix b/hacking/nix/scope/default.nix index 7e27298be..74db4bf64 100644 --- a/hacking/nix/scope/default.nix +++ b/hacking/nix/scope/default.nix @@ -139,7 +139,7 @@ superCallPackage ../rust-utils {} self // nativeBuildInputs = (super.nativeBuildInputs or []) ++ [ makeWrapper ]; postBuild = '' wrapProgram $out/bin/${rootCrate.name} \ - --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ rustEnvironment.rustToolchain ]} + --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ rustEnvironment.rustToolchain ]} ''; }); }; From 20430a14672a993deafc90f529b7465bfe894b95 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 3 Jul 2024 09:56:25 +0000 Subject: [PATCH 02/20] nix: Actually use callPlatform extraDebuggingLinks arg Signed-off-by: Nick Spinale --- hacking/nix/scope/world/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hacking/nix/scope/world/default.nix b/hacking/nix/scope/world/default.nix index 679114660..8a625f5fa 100644 --- a/hacking/nix/scope/world/default.nix +++ b/hacking/nix/scope/world/default.nix @@ -204,7 +204,7 @@ self: with self; ) // extraPlatformArgs); in { links = linkFarm "links" ( - system.debuggingLinks ++ platformSystemExtension.links + system.debuggingLinks ++ platformSystemExtension.links ++ extraDebuggingLinks ); } // platformSystemExtension.attrs From 5cf8145a1f8f34eba45b75043084e88057f71c1b Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Fri, 28 Jun 2024 23:07:01 +0000 Subject: [PATCH 03/20] nix: Pass sysroot through mkTask Signed-off-by: Nick Spinale --- hacking/nix/scope/world/mk-task.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hacking/nix/scope/world/mk-task.nix b/hacking/nix/scope/world/mk-task.nix index 2f7b446cd..09505d0a7 100644 --- a/hacking/nix/scope/world/mk-task.nix +++ b/hacking/nix/scope/world/mk-task.nix @@ -89,6 +89,7 @@ let theseLastLayerModifications = crateUtils.elaborateModifications { modifyDerivation = drv: drv.overrideAttrs (self: super: seL4RustEnvVars // { passthru = (super.passthru or {}) // { + inherit sysroot; elf = getELF self.finalPackage; split = { full = self.finalPackage.elf; From cf21d3748da369620a479ab6a69ad02b4a322b41 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sun, 30 Jun 2024 07:16:04 +0000 Subject: [PATCH 04/20] nix: Default to "release" profile for sysroot Signed-off-by: Nick Spinale --- hacking/nix/scope/world/mk-task.nix | 34 ++++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/hacking/nix/scope/world/mk-task.nix b/hacking/nix/scope/world/mk-task.nix index 09505d0a7..601e5a705 100644 --- a/hacking/nix/scope/world/mk-task.nix +++ b/hacking/nix/scope/world/mk-task.nix @@ -33,12 +33,28 @@ in , release ? true , profile ? if release then "release" else (if test then "test" else "dev") +, sameProfileForSysroot ? false +, profileForSysroot ? if sameProfileForSysroot then profile else "release" + , test ? false , ... } @ args: let + commonProfile = crateUtils.clobber [ + { + codegen-units = 1; + incremental = false; + build-override = { + opt-level = 0; + debug = false; + strip = true; + }; + } + extraProfile + ]; + profiles = crateUtils.clobber [ { profile.release = { @@ -46,25 +62,17 @@ let }; } { - profile.${profile} = crateUtils.clobber [ - { - codegen-units = 1; - incremental = false; - build-override = { - opt-level = 0; - debug = false; - strip = true; - }; - } - extraProfile - ]; + profile.${profile} = commonProfile; + } + { + profile.${profileForSysroot} = commonProfile; } ]; sysroot = (if replaceSysroot != null then replaceSysroot else buildSysroot) { inherit rustEnvironment; inherit targetTriple; - inherit profile; + profile = profileForSysroot; extraManifest = profiles; }; From 494e2c17baa078e0543d8a16f9d69881ef1a1e2b Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 3 Jul 2024 09:54:41 +0000 Subject: [PATCH 05/20] nix: Fix microkit links Signed-off-by: Nick Spinale --- hacking/nix/scope/microkit/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hacking/nix/scope/microkit/default.nix b/hacking/nix/scope/microkit/default.nix index 01908859e..c6b8d97f7 100644 --- a/hacking/nix/scope/microkit/default.nix +++ b/hacking/nix/scope/microkit/default.nix @@ -152,7 +152,7 @@ let inherit loader; loaderImage = loader.image; debuggingLinks = [ - { name = "loader.img"; path = loader; } + { name = "loader.img"; path = "${loader}/loader.img"; } { name = "report.txt"; path = "${loader}/report.txt"; } { name = "sdk/elf"; path = "${sdk}/board/${board}/${config}/elf"; } { name = "sel4-symbolize-backtrace"; From 98c3aa3fbacba05bf9b54e9b190b58fd6da54073 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Sun, 30 Jun 2024 07:29:06 +0000 Subject: [PATCH 06/20] crates/sel4-runtime-common: Remove unecessary unsafe block Signed-off-by: Nick Spinale --- crates/sel4-runtime-common/src/start.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sel4-runtime-common/src/start.rs b/crates/sel4-runtime-common/src/start.rs index 20241d7fc..0b4a65565 100644 --- a/crates/sel4-runtime-common/src/start.rs +++ b/crates/sel4-runtime-common/src/start.rs @@ -53,7 +53,7 @@ macro_rules! declare_stack { static __sel4_runtime_common__stack_top: $crate::_private::start::StackTop = { static STACK: $crate::_private::start::Stack<{ $size }> = $crate::_private::start::Stack::new(); - unsafe { STACK.top() } + STACK.top() }; }; } From 9da168ca548afd4dcbc1c6dcf3da2c99b90e6e00 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 27 Jun 2024 14:51:25 +0000 Subject: [PATCH 07/20] crates/sel4-microkit: Add Handler impl for Never Signed-off-by: Nick Spinale --- crates/sel4-microkit/base/src/handler.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/sel4-microkit/base/src/handler.rs b/crates/sel4-microkit/base/src/handler.rs index 32a3a8486..c60f649bd 100644 --- a/crates/sel4-microkit/base/src/handler.rs +++ b/crates/sel4-microkit/base/src/handler.rs @@ -97,6 +97,10 @@ pub trait Handler { #[doc(hidden)] pub enum Never {} +impl Handler for Never { + type Error = Infallible; +} + /// A [`Handler`] implementation which does not override any of the default method implementations. pub struct NullHandler(()); From 03feb320e02440de82835bc8275ee7a8441d977d Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Thu, 4 Jul 2024 07:39:25 +0000 Subject: [PATCH 08/20] crates/sel4-render-elf-with-data: Fix layout bug Signed-off-by: Nick Spinale --- crates/sel4-render-elf-with-data/src/render.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/sel4-render-elf-with-data/src/render.rs b/crates/sel4-render-elf-with-data/src/render.rs index 20db60fd6..02e5a8fe6 100644 --- a/crates/sel4-render-elf-with-data/src/render.rs +++ b/crates/sel4-render-elf-with-data/src/render.rs @@ -45,9 +45,10 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { .iter() .map(|symbolic_injection| { let filesz = symbolic_injection.filesz(); + let memsz = symbolic_injection.memsz; let offset = writer.reserve(filesz.to_usize().unwrap(), 1); let vaddr = symbolic_injection.align_from(next_vaddr); - next_vaddr = vaddr.checked_add(&filesz).unwrap(); + next_vaddr = vaddr.checked_add(&memsz).unwrap(); Ok((symbolic_injection.locate(vaddr)?, offset)) }) .collect::, usize)>>>()? From f31985cddaf0b8e467668033292b02df55fb99e6 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Mon, 1 Jul 2024 03:01:43 +0000 Subject: [PATCH 09/20] crates/sel4-render-elf-with-data: Simplify trait Signed-off-by: Nick Spinale --- crates/sel4-render-elf-with-data/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/sel4-render-elf-with-data/src/lib.rs b/crates/sel4-render-elf-with-data/src/lib.rs index 4fef089b9..9f74336e2 100644 --- a/crates/sel4-render-elf-with-data/src/lib.rs +++ b/crates/sel4-render-elf-with-data/src/lib.rs @@ -33,9 +33,7 @@ impl ElfBitWidth { pub type ConcreteFileHeader32 = FileHeader32; pub type ConcreteFileHeader64 = FileHeader64; -pub trait FileHeaderExt: - FileHeader + FileHeader -{ +pub trait FileHeaderExt: FileHeader { fn checked_add_signed(x: Self::Word, y: Self::Sword) -> Option; fn write_word_bytes(endian: impl Endian, n: Self::Word) -> Vec; } From 51ec22f9b4ac696b0886411ff39373cc0c5e6d14 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Mon, 1 Jul 2024 09:06:21 +0000 Subject: [PATCH 10/20] crates/sel4-render-elf-with-data: Make API more abstract Signed-off-by: Nick Spinale --- .../sel4-render-elf-with-data/src/render.rs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/sel4-render-elf-with-data/src/render.rs b/crates/sel4-render-elf-with-data/src/render.rs index 02e5a8fe6..f6828d063 100644 --- a/crates/sel4-render-elf-with-data/src/render.rs +++ b/crates/sel4-render-elf-with-data/src/render.rs @@ -11,6 +11,7 @@ use num::{CheckedAdd, NumCast, ToPrimitive}; use object::{ elf::{PF_R, PF_W, PT_LOAD}, read::elf::{ElfFile, FileHeader, ProgramHeader as _}, + read::ReadRef, write::elf::{ProgramHeader, Writer}, Object, ObjectSegment, ObjectSymbol, }; @@ -19,7 +20,13 @@ use crate::{FileHeaderExt, Injection, Input}; impl<'a, T: FileHeaderExt> Input<'a, T> { pub fn render_with_data(&self, orig: &[u8]) -> Result> { - let orig_obj: &ElfFile = &ElfFile::parse(orig)?; + self.render_with_data_already_parsed(&ElfFile::parse(orig)?) + } + + pub fn render_with_data_already_parsed<'b, R: ReadRef<'b>>( + &self, + orig_obj: &ElfFile<'b, T, R>, + ) -> Result> { let orig_endian = orig_obj.endian(); let orig_image_end = next_vaddr(orig_obj)?; @@ -97,7 +104,7 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { for (phdr, revised_offset) in loadable_segments(orig_obj).zip(&revised_offsets) { writer.pad_until(*revised_offset); - writer.write(phdr.data(orig_endian, orig).ok().unwrap()); + writer.write(phdr.data(orig_endian, orig_obj.data()).ok().unwrap()); } for (injection, offset) in &new_segments { @@ -145,15 +152,18 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { } } -fn loadable_segments<'a, T: FileHeaderExt>( - obj: &'a ElfFile, -) -> impl Iterator::ProgramHeader> { +fn loadable_segments<'a, 'b, T: FileHeaderExt, R: ReadRef<'b>>( + obj: &'a ElfFile<'b, T, R>, +) -> impl Iterator::ProgramHeader> + 'a { obj.raw_segments() .iter() .filter(|phdr| phdr.p_type(obj.endian()) == PT_LOAD) } -fn get_symbol_vaddr(obj: &ElfFile, name: &str) -> Result { +fn get_symbol_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>( + obj: &ElfFile<'a, T, R>, + name: &str, +) -> Result { for symbol in obj.symbols() { if symbol.name()? == name { ensure!(usize::try_from(symbol.size()).unwrap() == mem::size_of::()); @@ -163,7 +173,10 @@ fn get_symbol_vaddr(obj: &ElfFile, name: &str) -> Result(obj: &ElfFile, vaddr: T::Word) -> Result +fn vaddr_to_offset<'a, T: FileHeaderExt, R: ReadRef<'a>>( + obj: &ElfFile<'a, T, R>, + vaddr: T::Word, +) -> Result where { for segment in obj.segments() { @@ -182,7 +195,7 @@ where )) } -fn first_vaddr(obj: &ElfFile) -> Result +fn first_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>(obj: &ElfFile<'a, T, R>) -> Result where { loadable_segments(obj) @@ -191,7 +204,7 @@ where .ok_or(anyhow!("no segments")) } -fn next_vaddr(obj: &ElfFile) -> Result +fn next_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>(obj: &ElfFile<'a, T, R>) -> Result where { loadable_segments(obj) From 47c44c33e3826e5c780b4dc7c4d7db10da691263 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Tue, 2 Jul 2024 00:42:05 +0000 Subject: [PATCH 11/20] Bump object dependency Signed-off-by: Nick Spinale --- Cargo.lock | 54 ++++++------------- .../examples/root-task/spawn-task/Cargo.toml | 2 +- .../root-task/spawn-task/src/child_vspace.rs | 6 +-- .../addr2line-context-helper/Cargo.nix | 3 +- .../addr2line-context-helper/Cargo.toml | 7 +-- .../addr2line-context-helper/src/lib.rs | 8 +-- crates/sel4-backtrace/cli/Cargo.nix | 3 +- crates/sel4-backtrace/cli/Cargo.toml | 4 +- .../cli/src/bin/sel4-symbolize-backtrace.rs | 6 +-- .../embedded-debug-info/Cargo.toml | 4 +- crates/sel4-backtrace/types/Cargo.nix | 2 +- crates/sel4-backtrace/types/Cargo.toml | 4 +- .../add-spec/Cargo.toml | 2 +- crates/sel4-kernel-loader/Cargo.toml | 2 +- .../sel4-kernel-loader/add-payload/Cargo.toml | 2 +- .../add-payload/src/serialize_payload.rs | 8 +-- crates/sel4-kernel-loader/build.rs | 6 +-- crates/sel4-render-elf-with-data/Cargo.toml | 2 +- .../sel4-render-elf-with-data/src/render.rs | 4 +- crates/sel4-reset/cli/Cargo.toml | 25 +++++++++ .../manifest-scope.nix | 6 +-- 21 files changed, 82 insertions(+), 78 deletions(-) create mode 100644 crates/sel4-reset/cli/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 32d3ff219..24764d80b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,15 +33,13 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "7b9d03130b08257bc8110b0df827d8b137fdf67a95e2459eaace2e13fecf1d72" dependencies = [ "cpp_demangle", "fallible-iterator 0.3.0", - "gimli 0.28.1", - "memmap2", - "object", + "gimli 0.30.0", "rustc-demangle", "smallvec", ] @@ -548,17 +546,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "digest" version = "0.10.7" @@ -819,11 +806,10 @@ checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "gimli" -version = "0.28.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9" dependencies = [ - "fallible-iterator 0.3.0", "stable_deref_trait", ] @@ -1053,15 +1039,6 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - [[package]] name = "meta" version = "0.1.0" @@ -1394,9 +1371,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "crc32fast", "flate2", @@ -1854,12 +1831,11 @@ dependencies = [ [[package]] name = "ruzstd" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +checksum = "5022b253619b1ba797f243056276bed8ed1a73b0f5a7ce7225d524067644bf8f" dependencies = [ "byteorder", - "derive_more", "twox-hash", ] @@ -1997,7 +1973,8 @@ name = "sel4-backtrace-addr2line-context-helper" version = "0.1.0" dependencies = [ "addr2line", - "gimli 0.28.1", + "gimli 0.30.0", + "object", "stable_deref_trait", ] @@ -2005,10 +1982,10 @@ dependencies = [ name = "sel4-backtrace-cli" version = "0.1.0" dependencies = [ - "addr2line", "clap", "hex", "object", + "sel4-backtrace-addr2line-context-helper", "sel4-backtrace-types", ] @@ -3436,12 +3413,11 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasmparser" -version = "0.118.2" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" +checksum = "8d28bc49ba1e5c5b61ffa7a2eace10820443c4b7d1c0b144109261d14570fdf8" dependencies = [ - "indexmap", - "semver", + "bitflags 2.4.2", ] [[package]] diff --git a/crates/examples/root-task/spawn-task/Cargo.toml b/crates/examples/root-task/spawn-task/Cargo.toml index 0aec577c0..6a929d10d 100644 --- a/crates/examples/root-task/spawn-task/Cargo.toml +++ b/crates/examples/root-task/spawn-task/Cargo.toml @@ -17,6 +17,6 @@ edition = "2021" license = "BSD-2-Clause" [dependencies] -object = { version = "0.32.1", default-features = false, features = ["read"] } +object = { version = "0.36.1", default-features = false, features = ["read"] } sel4 = { path = "../../../sel4" } sel4-root-task = { path = "../../../sel4-root-task" } diff --git a/crates/examples/root-task/spawn-task/src/child_vspace.rs b/crates/examples/root-task/spawn-task/src/child_vspace.rs index 78a4aa14c..22a3c78a4 100644 --- a/crates/examples/root-task/spawn-task/src/child_vspace.rs +++ b/crates/examples/root-task/spawn-task/src/child_vspace.rs @@ -18,7 +18,7 @@ const GRANULE_SIZE: usize = sel4::FrameObjectType::GRANULE.bytes(); pub(crate) fn create_child_vspace<'a>( allocator: &mut ObjectAllocator, - image: &'a impl Object<'a, 'a>, + image: &'a impl Object<'a>, caller_vspace: sel4::cap::VSpace, free_page_addr: usize, asid_pool: sel4::cap::AsidPool, @@ -57,7 +57,7 @@ pub(crate) fn create_child_vspace<'a>( (child_vspace, ipc_buffer_addr, ipc_buffer_cap) } -fn footprint<'a>(image: &'a impl Object<'a, 'a>) -> Range { +fn footprint<'a>(image: &'a impl Object<'a>) -> Range { let min: usize = image .segments() .map(|seg| seg.address()) @@ -104,7 +104,7 @@ fn map_image<'a>( allocator: &mut ObjectAllocator, vspace: sel4::cap::VSpace, footprint: Range, - image: &'a impl Object<'a, 'a>, + image: &'a impl Object<'a>, caller_vspace: sel4::cap::VSpace, free_page_addr: usize, ) { diff --git a/crates/sel4-backtrace/addr2line-context-helper/Cargo.nix b/crates/sel4-backtrace/addr2line-context-helper/Cargo.nix index bbe2c7ce9..17d9fc876 100644 --- a/crates/sel4-backtrace/addr2line-context-helper/Cargo.nix +++ b/crates/sel4-backtrace/addr2line-context-helper/Cargo.nix @@ -9,8 +9,9 @@ mk { package.name = "sel4-backtrace-addr2line-context-helper"; dependencies = { - addr2line = { version = versions.addr2line; default-features = false; features = [ "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "object" ]; }; + addr2line = { version = versions.addr2line; default-features = false; features = [ "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" ]; }; gimli = { version = versions.gimli; default-features = false; features = [ "endian-reader" ]; }; + object = { version = versions.object; default-features = false; features = [ "read" ]; }; stable_deref_trait = { version = "1.1.0"; default-features = false; features = [ "alloc" ]; }; }; } diff --git a/crates/sel4-backtrace/addr2line-context-helper/Cargo.toml b/crates/sel4-backtrace/addr2line-context-helper/Cargo.toml index 3cc718b60..02c644951 100644 --- a/crates/sel4-backtrace/addr2line-context-helper/Cargo.toml +++ b/crates/sel4-backtrace/addr2line-context-helper/Cargo.toml @@ -17,10 +17,11 @@ edition = "2021" license = "BSD-2-Clause" [dependencies] -gimli = { version = "0.28.0", default-features = false, features = ["endian-reader"] } +gimli = { version = "0.30.0", default-features = false, features = ["endian-reader"] } +object = { version = "0.36.1", default-features = false, features = ["read"] } stable_deref_trait = { version = "1.1.0", default-features = false, features = ["alloc"] } [dependencies.addr2line] -version = "0.21.0" +version = "0.23.0" default-features = false -features = ["rustc-demangle", "cpp_demangle", "fallible-iterator", "smallvec", "object"] +features = ["rustc-demangle", "cpp_demangle", "fallible-iterator", "smallvec"] diff --git a/crates/sel4-backtrace/addr2line-context-helper/src/lib.rs b/crates/sel4-backtrace/addr2line-context-helper/src/lib.rs index 7f298bec1..39dff1fa1 100644 --- a/crates/sel4-backtrace/addr2line-context-helper/src/lib.rs +++ b/crates/sel4-backtrace/addr2line-context-helper/src/lib.rs @@ -11,20 +11,20 @@ extern crate alloc; use alloc::borrow::Cow; use alloc::rc::Rc; -use addr2line::object::{Object, ObjectSection}; use addr2line::Context as AbstractContext; +use object::{Object, ObjectSection}; pub use addr2line::gimli::Error; pub type Context = AbstractContext>; -pub fn new_context<'data: 'file, 'file, O: Object<'data, 'file>>( +pub fn new_context<'data: 'file, 'file, O: Object<'data>>( file: &'file O, ) -> Result { new_context_with_sup(file, None) } -pub fn new_context_with_sup<'data: 'file, 'file, O: Object<'data, 'file>>( +pub fn new_context_with_sup<'data: 'file, 'file, O: Object<'data>>( file: &'file O, sup_file: Option<&'file O>, ) -> Result { @@ -40,7 +40,7 @@ pub fn new_context_with_sup<'data: 'file, 'file, O: Object<'data, 'file>>( endian: Endian, ) -> Result, Error> where - O: Object<'data, 'file>, + O: Object<'data>, Endian: gimli::Endianity, { let data = file diff --git a/crates/sel4-backtrace/cli/Cargo.nix b/crates/sel4-backtrace/cli/Cargo.nix index f0a6ab65b..05516cd59 100644 --- a/crates/sel4-backtrace/cli/Cargo.nix +++ b/crates/sel4-backtrace/cli/Cargo.nix @@ -9,8 +9,9 @@ mk { package.name = "sel4-backtrace-cli"; dependencies = { - inherit (versions) object addr2line clap; + inherit (versions) object clap; hex = "0.4.3"; + inherit (localCrates) sel4-backtrace-addr2line-context-helper; sel4-backtrace-types = localCrates.sel4-backtrace-types // { features = [ "full" ]; }; }; } diff --git a/crates/sel4-backtrace/cli/Cargo.toml b/crates/sel4-backtrace/cli/Cargo.toml index 96b350b7b..da8ea2b1c 100644 --- a/crates/sel4-backtrace/cli/Cargo.toml +++ b/crates/sel4-backtrace/cli/Cargo.toml @@ -17,8 +17,8 @@ edition = "2021" license = "BSD-2-Clause" [dependencies] -addr2line = "0.21.0" clap = "4.4.6" hex = "0.4.3" -object = "0.32.1" +object = "0.36.1" +sel4-backtrace-addr2line-context-helper = { path = "../addr2line-context-helper" } sel4-backtrace-types = { path = "../types", features = ["full"] } diff --git a/crates/sel4-backtrace/cli/src/bin/sel4-symbolize-backtrace.rs b/crates/sel4-backtrace/cli/src/bin/sel4-symbolize-backtrace.rs index 194833d08..91de889c1 100644 --- a/crates/sel4-backtrace/cli/src/bin/sel4-symbolize-backtrace.rs +++ b/crates/sel4-backtrace/cli/src/bin/sel4-symbolize-backtrace.rs @@ -6,9 +6,9 @@ use std::fs; -use addr2line::Context; use clap::{arg, Command}; +use sel4_backtrace_addr2line_context_helper::new_context; use sel4_backtrace_types::Backtrace; fn main() { @@ -23,8 +23,8 @@ fn main() { .or(bt.preamble.image.as_ref()) .expect("ELF file neither embedded nor provided"); let elf_file_contents = fs::read(elf_file_path).unwrap(); - let elf_obj = &object::File::parse(&*elf_file_contents).unwrap(); - let ctx = Context::new(elf_obj).unwrap(); + let obj = object::File::parse(&*elf_file_contents).unwrap(); + let ctx = new_context(&obj).unwrap(); println!("backtrace: {}", elf_file_path); let mut s = String::new(); bt.symbolize(&ctx, &mut s).unwrap(); diff --git a/crates/sel4-backtrace/embedded-debug-info/Cargo.toml b/crates/sel4-backtrace/embedded-debug-info/Cargo.toml index 6995d9af2..e47325eff 100644 --- a/crates/sel4-backtrace/embedded-debug-info/Cargo.toml +++ b/crates/sel4-backtrace/embedded-debug-info/Cargo.toml @@ -17,6 +17,6 @@ edition = "2021" license = "BSD-2-Clause" [dependencies] -addr2line = { version = "0.21.0", default-features = false } -object = { version = "0.32.1", default-features = false, features = ["read"] } +addr2line = { version = "0.23.0", default-features = false } +object = { version = "0.36.1", default-features = false, features = ["read"] } sel4-backtrace-addr2line-context-helper = { path = "../addr2line-context-helper" } diff --git a/crates/sel4-backtrace/types/Cargo.nix b/crates/sel4-backtrace/types/Cargo.nix index b208f6b0a..1e883311b 100644 --- a/crates/sel4-backtrace/types/Cargo.nix +++ b/crates/sel4-backtrace/types/Cargo.nix @@ -16,7 +16,7 @@ mk rec { inherit (versions) cfg-if; serde = serdeWith [ "derive" ] // { optional = true; }; postcard = postcardWith [] // { optional = true; }; - addr2line = { version = versions.addr2line; default-features = false; features = [ "rustc-demangle" "cpp_demangle" "object" "fallible-iterator" "smallvec" ]; optional = true; }; + addr2line = { version = versions.addr2line; default-features = false; features = [ "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" ]; optional = true; }; }; features = { alloc = [ diff --git a/crates/sel4-backtrace/types/Cargo.toml b/crates/sel4-backtrace/types/Cargo.toml index 1dcb80c9e..b07e9137e 100644 --- a/crates/sel4-backtrace/types/Cargo.toml +++ b/crates/sel4-backtrace/types/Cargo.toml @@ -29,7 +29,7 @@ postcard = { version = "1.0.2", default-features = false, optional = true } serde = { version = "1.0.147", default-features = false, features = ["derive"], optional = true } [dependencies.addr2line] -version = "0.21.0" +version = "0.23.0" default-features = false -features = ["rustc-demangle", "cpp_demangle", "object", "fallible-iterator", "smallvec"] +features = ["rustc-demangle", "cpp_demangle", "fallible-iterator", "smallvec"] optional = true diff --git a/crates/sel4-capdl-initializer/add-spec/Cargo.toml b/crates/sel4-capdl-initializer/add-spec/Cargo.toml index a7459b075..8d2af034c 100644 --- a/crates/sel4-capdl-initializer/add-spec/Cargo.toml +++ b/crates/sel4-capdl-initializer/add-spec/Cargo.toml @@ -21,7 +21,7 @@ anyhow = "1.0.66" clap = "4.4.6" fallible-iterator = "0.2.0" num = "0.4.1" -object = { version = "0.32.1", features = ["all"] } +object = { version = "0.36.1", features = ["all"] } postcard = { version = "1.0.2", default-features = false, features = ["alloc"] } sel4-capdl-initializer-types = { path = "../types", features = ["std", "serde", "deflate"] } sel4-render-elf-with-data = { path = "../../sel4-render-elf-with-data" } diff --git a/crates/sel4-kernel-loader/Cargo.toml b/crates/sel4-kernel-loader/Cargo.toml index 554ab3dac..91bcc31d1 100644 --- a/crates/sel4-kernel-loader/Cargo.toml +++ b/crates/sel4-kernel-loader/Cargo.toml @@ -33,7 +33,7 @@ spin = { version = "0.9.4", features = ["lock_api"] } [build-dependencies] cc = "1.0.76" glob = "0.3.0" -object = "0.32.1" +object = "0.36.1" postcard = { version = "1.0.2", default-features = false, features = ["alloc"] } quote = "1.0.23" sel4-build-env = { path = "../sel4/build-env" } diff --git a/crates/sel4-kernel-loader/add-payload/Cargo.toml b/crates/sel4-kernel-loader/add-payload/Cargo.toml index 2addcccc7..9a670845d 100644 --- a/crates/sel4-kernel-loader/add-payload/Cargo.toml +++ b/crates/sel4-kernel-loader/add-payload/Cargo.toml @@ -22,7 +22,7 @@ clap = "4.4.6" fallible-iterator = "0.2.0" heapless = "0.7.16" num = "0.4.1" -object = { version = "0.32.1", features = ["all"] } +object = { version = "0.36.1", features = ["all"] } postcard = { version = "1.0.2", default-features = false, features = ["alloc"] } sel4-config-generic-types = { path = "../../sel4/config/generic/types", features = ["serde"] } sel4-kernel-loader-config-types = { path = "../config-types" } diff --git a/crates/sel4-kernel-loader/add-payload/src/serialize_payload.rs b/crates/sel4-kernel-loader/add-payload/src/serialize_payload.rs index a6c83a9b0..438bb2b78 100644 --- a/crates/sel4-kernel-loader/add-payload/src/serialize_payload.rs +++ b/crates/sel4-kernel-loader/add-payload/src/serialize_payload.rs @@ -105,7 +105,7 @@ impl> ) { let endian = elf.endian(); for phdr in elf - .raw_segments() + .elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) { @@ -190,14 +190,14 @@ fn elf_virt_addr_range<'a, T: FileHeader, R: ) -> Range { let endian = elf.endian(); let virt_min = elf - .raw_segments() + .elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| phdr.p_vaddr(endian)) .min() .unwrap(); let virt_max = elf - .raw_segments() + .elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| { @@ -215,7 +215,7 @@ fn elf_phys_to_vaddr_offset<'a, T: FileHeader, R: R ) -> T::Word { let endian = elf.endian(); unified( - elf.raw_segments() + elf.elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| phys_to_virt_offset_for(phdr.p_paddr(endian), phdr.p_vaddr(endian))), diff --git a/crates/sel4-kernel-loader/build.rs b/crates/sel4-kernel-loader/build.rs index e7123007f..f8e801f37 100644 --- a/crates/sel4-kernel-loader/build.rs +++ b/crates/sel4-kernel-loader/build.rs @@ -289,14 +289,14 @@ impl SchemeExt for schemes::RiscV32Sv32 { fn elf_phys_addr_range<'a, R: ReadRef<'a>>(elf: &ElfFile<'a, FileHeader, R>) -> Range { let endian = elf.endian(); let virt_min = elf - .raw_segments() + .elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| phdr.p_paddr(endian)) .min() .unwrap(); let virt_max = elf - .raw_segments() + .elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| { @@ -312,7 +312,7 @@ fn elf_phys_addr_range<'a, R: ReadRef<'a>>(elf: &ElfFile<'a, FileHeader, R>) -> fn elf_phys_to_vaddr_offset<'a, R: ReadRef<'a>>(elf: &ElfFile<'a, FileHeader, R>) -> u64 { let endian = elf.endian(); unified( - elf.raw_segments() + elf.elf_program_headers() .iter() .filter(|phdr| phdr.p_type(endian) == PT_LOAD) .map(|phdr| { diff --git a/crates/sel4-render-elf-with-data/Cargo.toml b/crates/sel4-render-elf-with-data/Cargo.toml index 169602968..45bc85914 100644 --- a/crates/sel4-render-elf-with-data/Cargo.toml +++ b/crates/sel4-render-elf-with-data/Cargo.toml @@ -20,4 +20,4 @@ license = "BSD-2-Clause" anyhow = "1.0.66" fallible-iterator = "0.2.0" num = "0.4.1" -object = { version = "0.32.1", features = ["all"] } +object = { version = "0.36.1", features = ["all"] } diff --git a/crates/sel4-render-elf-with-data/src/render.rs b/crates/sel4-render-elf-with-data/src/render.rs index f6828d063..3e6e14276 100644 --- a/crates/sel4-render-elf-with-data/src/render.rs +++ b/crates/sel4-render-elf-with-data/src/render.rs @@ -62,7 +62,7 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { }; writer.write_file_header({ - let hdr = orig_obj.raw_header(); + let hdr = orig_obj.elf_header(); &object::write::elf::FileHeader { os_abi: hdr.e_ident().os_abi, abi_version: hdr.e_ident().abi_version, @@ -155,7 +155,7 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { fn loadable_segments<'a, 'b, T: FileHeaderExt, R: ReadRef<'b>>( obj: &'a ElfFile<'b, T, R>, ) -> impl Iterator::ProgramHeader> + 'a { - obj.raw_segments() + obj.elf_program_headers() .iter() .filter(|phdr| phdr.p_type(obj.endian()) == PT_LOAD) } diff --git a/crates/sel4-reset/cli/Cargo.toml b/crates/sel4-reset/cli/Cargo.toml new file mode 100644 index 000000000..040aafa06 --- /dev/null +++ b/crates/sel4-reset/cli/Cargo.toml @@ -0,0 +1,25 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-reset-cli" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +anyhow = "1.0.66" +clap = "4.4.6" +fallible-iterator = "0.2.0" +num = "0.4.1" +object = { version = "0.36.1", features = ["all"] } +sel4-render-elf-with-data = { path = "../../sel4-render-elf-with-data" } diff --git a/hacking/cargo-manifest-management/manifest-scope.nix b/hacking/cargo-manifest-management/manifest-scope.nix index 4a03c3c7c..17a6d9038 100644 --- a/hacking/cargo-manifest-management/manifest-scope.nix +++ b/hacking/cargo-manifest-management/manifest-scope.nix @@ -88,7 +88,7 @@ in rec { }; versions = { - addr2line = "0.21.0"; + addr2line = "0.23.0"; anyhow = "1.0.66"; async-unsync = "0.2.2"; cfg-if = "1.0.0"; @@ -100,14 +100,14 @@ in rec { fdt = "0.1.5"; futures = "0.3.28"; getrandom = "0.2.10"; - gimli = "0.28.0"; + gimli = "0.30.0"; heapless = "0.7.16"; lock_api = "0.4.12"; log = "0.4.17"; num = "0.4.1"; num_enum = "0.5.9"; num-traits = "0.2.16"; - object = "0.32.1"; + object = "0.36.1"; pin-project = "1.1.3"; postcard = "1.0.2"; proc-macro2 = "1.0.50"; From 285dfea2a6ca579408f99244faba9137540c0851 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 3 Jul 2024 06:19:33 +0000 Subject: [PATCH 12/20] Add *-resettable* rustc target specs Signed-off-by: Nick Spinale --- .reuse/dep5 | 1 + crates/sel4-generate-target-specs/src/main.rs | 47 +++++++++++++++---- .../src/microkit-resettable.lds | 9 ++++ .../aarch64-sel4-microkit-minimal.json | 2 +- ...ch64-sel4-microkit-resettable-minimal.json | 37 +++++++++++++++ .../aarch64-sel4-microkit-resettable.json | 36 ++++++++++++++ support/targets/aarch64-sel4-microkit.json | 2 +- 7 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 crates/sel4-generate-target-specs/src/microkit-resettable.lds create mode 100644 support/targets/aarch64-sel4-microkit-resettable-minimal.json create mode 100644 support/targets/aarch64-sel4-microkit-resettable.json diff --git a/.reuse/dep5 b/.reuse/dep5 index 16c118563..afa9bcdde 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -11,6 +11,7 @@ License: CC-BY-SA-4.0 Files: Cargo.lock support/*.json + crates/sel4-generate-target-specs/src/microkit-resettable.lds hacking/cargo-manifest-management/tool/Cargo.lock hacking/unstable-feature-monitoring/wishlist/Cargo.lock hacking/nix/scope/capdl-tool/capDL-tool.nix diff --git a/crates/sel4-generate-target-specs/src/main.rs b/crates/sel4-generate-target-specs/src/main.rs index 2582b6a13..cbfeeaf80 100644 --- a/crates/sel4-generate-target-specs/src/main.rs +++ b/crates/sel4-generate-target-specs/src/main.rs @@ -21,7 +21,7 @@ use clap::{Arg, ArgAction, Command}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] struct Config { arch: Arch, - microkit: bool, + context: Context, minimal: bool, } @@ -51,6 +51,12 @@ impl RiscVArch { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum Context { + RootTask, + Microkit { resettable: bool }, +} + impl Config { fn target_spec(&self) -> Target { let mut target = match &self.arch { @@ -103,10 +109,14 @@ impl Config { options.eh_frame_header = !self.minimal; } - if self.microkit { + if let Context::Microkit { resettable } = &self.context { + let mut linker_script = String::new(); + if *resettable { + linker_script.push_str(include_str!("microkit-resettable.lds")); + } + linker_script.push_str("__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;"); let options = &mut target.options; - options.link_script = - Some("__sel4_ipc_buffer_obj = (_end + 4096 - 1) & ~(4096 - 1);".into()); + options.link_script = Some(linker_script.into()); } if !self.minimal { @@ -121,14 +131,17 @@ impl Config { } fn filter(&self) -> bool { - !self.microkit || self.arch.microkit_support() + !self.context.is_microkit() || self.arch.microkit_support() } fn name(&self) -> String { let mut name = self.arch.name(); name.push_str("-sel4"); - if self.microkit { + if let Context::Microkit { resettable } = &self.context { name.push_str("-microkit"); + if *resettable { + name.push_str("-resettable"); + } } if self.minimal { name.push_str("-minimal"); @@ -138,13 +151,12 @@ impl Config { fn all() -> Vec { let mut all = vec![]; - let all_bools = &[true, false]; for arch in Arch::all() { - for microkit in all_bools.iter().copied() { - for minimal in all_bools.iter().copied() { + for context in Context::all() { + for minimal in [true, false] { let config = Self { arch, - microkit, + context, minimal, }; if config.filter() { @@ -194,6 +206,21 @@ impl Arch { } } +impl Context { + fn is_microkit(&self) -> bool { + matches!(self, Self::Microkit { .. }) + } + + fn all() -> Vec { + let mut v = vec![]; + v.push(Self::RootTask); + for resettable in [true, false] { + v.push(Self::Microkit { resettable }); + } + v + } +} + fn builtin(triple: &str) -> Target { Target::expect_builtin(&TargetTriple::from_triple(triple)) } diff --git a/crates/sel4-generate-target-specs/src/microkit-resettable.lds b/crates/sel4-generate-target-specs/src/microkit-resettable.lds new file mode 100644 index 000000000..b63b31e0f --- /dev/null +++ b/crates/sel4-generate-target-specs/src/microkit-resettable.lds @@ -0,0 +1,9 @@ +SECTIONS { + .persistent : { + *(.persistent .persistent.*) + } +} INSERT BEFORE .data; + +ASSERT(DEFINED(_reset), "_reset is not defined") + +ENTRY(_reset) diff --git a/support/targets/aarch64-sel4-microkit-minimal.json b/support/targets/aarch64-sel4-microkit-minimal.json index 16ce9ef87..45aadf045 100644 --- a/support/targets/aarch64-sel4-microkit-minimal.json +++ b/support/targets/aarch64-sel4-microkit-minimal.json @@ -7,7 +7,7 @@ "env": "sel4", "exe-suffix": ".elf", "features": "+v8a,+strict-align,+neon,+fp-armv8", - "link-script": "__sel4_ipc_buffer_obj = (_end + 4096 - 1) & ~(4096 - 1);", + "link-script": "__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", "linker": "rust-lld", "linker-flavor": "gnu-lld", "llvm-target": "aarch64-unknown-none", diff --git a/support/targets/aarch64-sel4-microkit-resettable-minimal.json b/support/targets/aarch64-sel4-microkit-resettable-minimal.json new file mode 100644 index 000000000..3232e379a --- /dev/null +++ b/support/targets/aarch64-sel4-microkit-resettable-minimal.json @@ -0,0 +1,37 @@ +{ + "arch": "aarch64", + "crt-objects-fallback": "false", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "disable-redzone": true, + "eh-frame-header": false, + "env": "sel4", + "exe-suffix": ".elf", + "features": "+v8a,+strict-align,+neon,+fp-armv8", + "link-script": "SECTIONS {\n .persistent : {\n *(.persistent .persistent.*)\n }\n} INSERT BEFORE .data;\n\nASSERT(DEFINED(_reset), \"_reset is not defined\")\n\nENTRY(_reset)\n__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-target": "aarch64-unknown-none", + "max-atomic-width": 128, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "panic-strategy": "abort", + "pre-link-args": { + "gnu-lld": [ + "-z", + "max-page-size=4096" + ] + }, + "relocation-model": "static", + "stack-probes": { + "kind": "inline" + }, + "supported-sanitizers": [ + "kcfi", + "kernel-address" + ], + "target-pointer-width": "64" +} diff --git a/support/targets/aarch64-sel4-microkit-resettable.json b/support/targets/aarch64-sel4-microkit-resettable.json new file mode 100644 index 000000000..391e5eafd --- /dev/null +++ b/support/targets/aarch64-sel4-microkit-resettable.json @@ -0,0 +1,36 @@ +{ + "arch": "aarch64", + "crt-objects-fallback": "false", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "disable-redzone": true, + "env": "sel4", + "exe-suffix": ".elf", + "features": "+v8a,+strict-align,+neon,+fp-armv8", + "has-thread-local": true, + "link-script": "SECTIONS {\n .persistent : {\n *(.persistent .persistent.*)\n }\n} INSERT BEFORE .data;\n\nASSERT(DEFINED(_reset), \"_reset is not defined\")\n\nENTRY(_reset)\n__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-target": "aarch64-unknown-none", + "max-atomic-width": 128, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "pre-link-args": { + "gnu-lld": [ + "-z", + "max-page-size=4096" + ] + }, + "relocation-model": "static", + "stack-probes": { + "kind": "inline" + }, + "supported-sanitizers": [ + "kcfi", + "kernel-address" + ], + "target-pointer-width": "64" +} diff --git a/support/targets/aarch64-sel4-microkit.json b/support/targets/aarch64-sel4-microkit.json index 54d136bf8..75def462d 100644 --- a/support/targets/aarch64-sel4-microkit.json +++ b/support/targets/aarch64-sel4-microkit.json @@ -7,7 +7,7 @@ "exe-suffix": ".elf", "features": "+v8a,+strict-align,+neon,+fp-armv8", "has-thread-local": true, - "link-script": "__sel4_ipc_buffer_obj = (_end + 4096 - 1) & ~(4096 - 1);", + "link-script": "__sel4_ipc_buffer_obj = (__ehdr_start & ~(4096 - 1)) - 4096;", "linker": "rust-lld", "linker-flavor": "gnu-lld", "llvm-target": "aarch64-unknown-none", From c01413c6892e52f86412d9922ec21abd54fddb81 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 3 Jul 2024 06:20:45 +0000 Subject: [PATCH 13/20] crates/sel4-reset: Introduce Signed-off-by: Nick Spinale --- Cargo.lock | 27 +++ Cargo.toml | 3 + crates/private/tests/microkit/reset/Cargo.nix | 17 ++ .../private/tests/microkit/reset/Cargo.toml | 21 ++ .../tests/microkit/reset/src/bin/test.rs | 42 ++++ crates/private/tests/microkit/reset/x.system | 11 + crates/sel4-reset/Cargo.nix | 14 ++ crates/sel4-reset/Cargo.toml | 20 ++ crates/sel4-reset/cli/Cargo.nix | 23 ++ crates/sel4-reset/cli/src/args.rs | 40 ++++ crates/sel4-reset/cli/src/main.rs | 204 ++++++++++++++++++ crates/sel4-reset/src/lib.rs | 195 +++++++++++++++++ hacking/nix/scope/default.nix | 12 +- hacking/nix/scope/prepare-resettable.nix | 19 ++ hacking/nix/scope/sources.nix | 2 +- hacking/nix/scope/world/instances/default.nix | 1 + .../world/instances/microkit/default.nix | 50 ++++- 17 files changed, 697 insertions(+), 4 deletions(-) create mode 100644 crates/private/tests/microkit/reset/Cargo.nix create mode 100644 crates/private/tests/microkit/reset/Cargo.toml create mode 100644 crates/private/tests/microkit/reset/src/bin/test.rs create mode 100644 crates/private/tests/microkit/reset/x.system create mode 100644 crates/sel4-reset/Cargo.nix create mode 100644 crates/sel4-reset/Cargo.toml create mode 100644 crates/sel4-reset/cli/Cargo.nix create mode 100644 crates/sel4-reset/cli/src/args.rs create mode 100644 crates/sel4-reset/cli/src/main.rs create mode 100644 crates/sel4-reset/src/lib.rs create mode 100644 hacking/nix/scope/prepare-resettable.nix diff --git a/Cargo.lock b/Cargo.lock index 24764d80b..ded1c2e91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2529,6 +2529,25 @@ dependencies = [ "object", ] +[[package]] +name = "sel4-reset" +version = "0.1.0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "sel4-reset-cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "fallible-iterator 0.2.0", + "num", + "object", + "sel4-render-elf-with-data", +] + [[package]] name = "sel4-root-task" version = "0.1.0" @@ -3064,6 +3083,14 @@ dependencies = [ "sel4-microkit", ] +[[package]] +name = "tests-microkit-reset" +version = "0.1.0" +dependencies = [ + "sel4-microkit", + "sel4-reset", +] + [[package]] name = "tests-root-task-backtrace" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 930d75902..ba449efd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ members = [ "crates/private/tests/capdl/utcover/components/test", "crates/private/tests/microkit/passive-server-with-deferred-action/pds/client", "crates/private/tests/microkit/passive-server-with-deferred-action/pds/server", + "crates/private/tests/microkit/reset", "crates/private/tests/root-task/backtrace", "crates/private/tests/root-task/c", "crates/private/tests/root-task/config", @@ -122,6 +123,8 @@ members = [ "crates/sel4-platform-info", "crates/sel4-platform-info/types", "crates/sel4-render-elf-with-data", + "crates/sel4-reset", + "crates/sel4-reset/cli", "crates/sel4-root-task", "crates/sel4-root-task/default-test-harness", "crates/sel4-root-task/macros", diff --git a/crates/private/tests/microkit/reset/Cargo.nix b/crates/private/tests/microkit/reset/Cargo.nix new file mode 100644 index 000000000..7dc1139c2 --- /dev/null +++ b/crates/private/tests/microkit/reset/Cargo.nix @@ -0,0 +1,17 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, localCrates }: + +mk { + package.name = "tests-microkit-reset"; + dependencies = { + inherit (localCrates) + sel4-microkit + sel4-reset + ; + }; +} diff --git a/crates/private/tests/microkit/reset/Cargo.toml b/crates/private/tests/microkit/reset/Cargo.toml new file mode 100644 index 000000000..5ea3923e4 --- /dev/null +++ b/crates/private/tests/microkit/reset/Cargo.toml @@ -0,0 +1,21 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "tests-microkit-reset" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +sel4-microkit = { path = "../../../../sel4-microkit" } +sel4-reset = { path = "../../../../sel4-reset" } diff --git a/crates/private/tests/microkit/reset/src/bin/test.rs b/crates/private/tests/microkit/reset/src/bin/test.rs new file mode 100644 index 000000000..18a6baded --- /dev/null +++ b/crates/private/tests/microkit/reset/src/bin/test.rs @@ -0,0 +1,42 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] +#![no_main] + +use sel4_microkit::{debug_println, protection_domain, NullHandler}; +use sel4_reset::reset; + +const INIT: usize = 1337; + +static mut NOT_PERSISTENT: usize = INIT; + +#[link_section = ".persistent"] +static mut PERSISTENT: usize = INIT; + +#[link_section = ".persistent"] +static mut RESET_COUNT: usize = 0; + +#[protection_domain] +fn init() -> NullHandler { + unsafe { + debug_println!("NOT_PERSISTENT: {NOT_PERSISTENT}"); + debug_println!("PERSISTENT: {PERSISTENT}"); + debug_println!("RESET_COUNT: {RESET_COUNT}"); + + if RESET_COUNT == 3 { + assert_eq!(NOT_PERSISTENT, INIT); + assert_eq!(PERSISTENT, INIT + RESET_COUNT); + debug_println!("TEST_PASS"); + return NullHandler::new(); + } + + NOT_PERSISTENT += 1; + PERSISTENT += 1; + RESET_COUNT += 1; + } + reset() +} diff --git a/crates/private/tests/microkit/reset/x.system b/crates/private/tests/microkit/reset/x.system new file mode 100644 index 000000000..8126795da --- /dev/null +++ b/crates/private/tests/microkit/reset/x.system @@ -0,0 +1,11 @@ + + + + + + + diff --git a/crates/sel4-reset/Cargo.nix b/crates/sel4-reset/Cargo.nix new file mode 100644 index 000000000..b72744993 --- /dev/null +++ b/crates/sel4-reset/Cargo.nix @@ -0,0 +1,14 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, versions }: + +mk { + package.name = "sel4-reset"; + dependencies = { + inherit (versions) cfg-if; + }; +} diff --git a/crates/sel4-reset/Cargo.toml b/crates/sel4-reset/Cargo.toml new file mode 100644 index 000000000..33da63163 --- /dev/null +++ b/crates/sel4-reset/Cargo.toml @@ -0,0 +1,20 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-reset" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +cfg-if = "1.0.0" diff --git a/crates/sel4-reset/cli/Cargo.nix b/crates/sel4-reset/cli/Cargo.nix new file mode 100644 index 000000000..c3665b09d --- /dev/null +++ b/crates/sel4-reset/cli/Cargo.nix @@ -0,0 +1,23 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, localCrates, versions }: + +mk { + package.name = "sel4-reset-cli"; + dependencies = { + inherit (versions) + anyhow + fallible-iterator + num + clap + ; + object = { version = versions.object; features = [ "all" ]; }; + inherit (localCrates) + sel4-render-elf-with-data + ; + }; +} diff --git a/crates/sel4-reset/cli/src/args.rs b/crates/sel4-reset/cli/src/args.rs new file mode 100644 index 000000000..d656ec699 --- /dev/null +++ b/crates/sel4-reset/cli/src/args.rs @@ -0,0 +1,40 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use anyhow::Result; +use clap::{Arg, ArgAction, Command}; + +#[derive(Debug)] +pub struct Args { + pub in_file_path: String, + pub out_file_path: String, + pub verbose: bool, +} + +impl Args { + pub fn parse() -> Result { + let matches = Command::new("") + .arg(Arg::new("in_file").value_name("IN")) + .arg( + Arg::new("out_file") + .short('o') + .value_name("OUT") + .required(true), + ) + .arg(Arg::new("verbose").short('v').action(ArgAction::SetTrue)) + .get_matches(); + + let in_file_path = matches.get_one::("in_file").unwrap().to_owned(); + let out_file_path = matches.get_one::("out_file").unwrap().to_owned(); + let verbose = *matches.get_one::("verbose").unwrap(); + + Ok(Self { + in_file_path, + out_file_path, + verbose, + }) + } +} diff --git a/crates/sel4-reset/cli/src/main.rs b/crates/sel4-reset/cli/src/main.rs new file mode 100644 index 000000000..58dfe82d7 --- /dev/null +++ b/crates/sel4-reset/cli/src/main.rs @@ -0,0 +1,204 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use std::fs; +use std::mem; + +use anyhow::Result; +use num::{NumCast, Zero}; +use object::elf::{PF_W, PT_LOAD}; +use object::read::elf::{ElfFile, ProgramHeader}; +use object::{Endian, File, Object, ObjectSection, ReadCache, ReadRef}; + +use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue}; + +mod args; + +use args::Args; + +fn main() -> Result<()> { + let args = Args::parse()?; + + if args.verbose { + eprintln!("{:#?}", args); + } + + let in_file = fs::File::open(&args.in_file_path)?; + let in_file_cached = ReadCache::new(in_file); + let in_obj_file = File::parse(&in_file_cached)?; + + match in_obj_file { + File::Elf32(elf) => continue_with_type(&args, &elf), + File::Elf64(elf) => continue_with_type(&args, &elf), + _ => { + panic!() + } + } +} + +fn continue_with_type<'a, T, R>(args: &Args, elf: &ElfFile<'a, T, R>) -> Result<()> +where + R: ReadRef<'a>, + T: FileHeaderExt, +{ + let endian = elf.endian(); + + let persistent_section = elf.section_by_name(".persistent"); + + let mut regions_builder = RegionsBuilder::::new(); + + let mut persistent_section_placed = false; + + for phdr in elf.elf_program_headers().iter() { + if phdr.p_type(endian) == PT_LOAD && phdr.p_flags(endian) & PF_W != 0 { + let vaddr = ::from(phdr.p_vaddr(endian)).unwrap(); + let memsz = ::from(phdr.p_memsz(endian)).unwrap(); + let data = phdr.data(endian, elf.data()).unwrap(); + let skip = persistent_section + .as_ref() + .and_then(|section| { + if section.address() == vaddr { + persistent_section_placed = true; + Some(section.size()) + } else { + None + } + }) + .unwrap_or(0); + regions_builder.add_region_with_skip(skip, vaddr, memsz, data); + } + } + + assert!(!(persistent_section.is_some() && !persistent_section_placed)); + + let out_bytes = regions_builder + .build(endian) + .input::() + .render_with_data_already_parsed(elf) + .unwrap(); + + let out_file_path = &args.out_file_path; + + fs::write(out_file_path, out_bytes)?; + Ok(()) +} + +struct RegionsBuilder { + meta: Vec>, + data: Vec, +} + +impl RegionsBuilder { + fn new() -> Self { + Self { + meta: vec![], + data: vec![], + } + } + + fn add_region(&mut self, vaddr: u64, memsz: u64, data: &[u8]) { + let offset = self.data.len(); + let filesz = data.len(); + self.data.extend_from_slice(data); + self.meta.push(RegionMeta { + vaddr: NumCast::from(vaddr).unwrap(), + offset: NumCast::from(offset).unwrap(), + filesz: NumCast::from(filesz).unwrap(), + memsz: NumCast::from(memsz).unwrap(), + }) + } + + fn add_region_with_skip(&mut self, skip: u64, vaddr: u64, memsz: u64, data: &[u8]) { + if skip < memsz { + self.add_region( + vaddr + skip, + memsz - skip, + &data[data.len().min(skip.try_into().unwrap())..], + ); + } + } + + fn build(&self, endian: impl Endian) -> Regions { + let mut raw = vec![]; + let meta_offset = raw.len(); + let meta_count = self.meta.len(); + for meta in self.meta.iter() { + meta.pack(endian, &mut raw); + } + let data_offset = raw.len(); + let data_size = self.data.len(); + raw.extend_from_slice(&self.data); + Regions { + raw, + meta_offset, + meta_count, + data_offset, + data_size, + } + } +} + +struct RegionMeta { + vaddr: T::Word, + offset: T::Word, + filesz: T::Word, + memsz: T::Word, +} + +impl RegionMeta { + fn pack(&self, endian: impl Endian, buf: &mut Vec) { + buf.extend_from_slice(&T::write_word_bytes(endian, self.vaddr)); + buf.extend_from_slice(&T::write_word_bytes(endian, self.offset)); + buf.extend_from_slice(&T::write_word_bytes(endian, self.filesz)); + buf.extend_from_slice(&T::write_word_bytes(endian, self.memsz)); + } +} + +struct Regions { + raw: Vec, + meta_offset: usize, + meta_count: usize, + data_offset: usize, + data_size: usize, +} + +impl Regions { + fn input(&self) -> Input { + let align_modulus = NumCast::from(4096).unwrap(); + let align_residue = T::Word::zero(); + let memsz = self.raw.len(); + let mut input = Input::::default(); + input.symbolic_injections.push(SymbolicInjection { + align_modulus, + align_residue, + content: &self.raw, + memsz: NumCast::from(memsz).unwrap(), + patches: vec![( + "sel4_reset_regions_start".to_owned(), + SymbolicValue { + addend: T::Sword::zero(), + }, + )], + }); + input.concrete_patches.push(( + "sel4_reset_regions_meta_offset".to_owned(), + NumCast::from(self.meta_offset).unwrap(), + )); + input.concrete_patches.push(( + "sel4_reset_regions_meta_count".to_owned(), + NumCast::from(self.meta_count).unwrap(), + )); + input.concrete_patches.push(( + "sel4_reset_regions_data_offset".to_owned(), + NumCast::from(self.data_offset).unwrap(), + )); + input.concrete_patches.push(( + "sel4_reset_regions_data_size".to_owned(), + NumCast::from(self.data_size).unwrap(), + )); + input + } +} diff --git a/crates/sel4-reset/src/lib.rs b/crates/sel4-reset/src/lib.rs new file mode 100644 index 000000000..463b5b515 --- /dev/null +++ b/crates/sel4-reset/src/lib.rs @@ -0,0 +1,195 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] + +use core::arch::global_asm; +use core::cell::UnsafeCell; +use core::ptr; +use core::slice; + +use cfg_if::cfg_if; + +// // // + +#[repr(C)] +#[derive(Debug)] +struct RegionMeta { + vaddr: usize, + offset: usize, + filesz: usize, + memsz: usize, +} + +struct Regions<'a> { + meta: &'a [RegionMeta], + data: &'a [u8], +} + +impl<'a> Regions<'a> { + unsafe fn reset_memory(&self) { + for meta in self.meta { + let dst = unsafe { slice::from_raw_parts_mut(meta.vaddr as *mut _, meta.memsz) }; + let (dst_data, dst_zero) = dst.split_at_mut(meta.filesz); + let src_data = &self.data[meta.offset..][..meta.filesz]; + dst_data.copy_from_slice(src_data); + ptr::write_bytes(dst_zero.as_mut_ptr(), 0, dst_zero.len()); + } + } +} + +// // // + +#[repr(C)] +#[cfg_attr( + any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "x86_64", + ), + repr(align(16)) +)] +#[cfg_attr(target_arch = "arm", repr(align(4)))] +pub struct Stack(UnsafeCell<[u8; N]>); + +unsafe impl Sync for Stack {} + +impl Stack { + pub const fn new() -> Self { + Self(UnsafeCell::new([0; N])) + } + + pub const fn top(&self) -> StackTop { + StackTop(self.0.get().cast::().wrapping_add(N)) + } +} + +impl Default for Stack { + fn default() -> Self { + Self::new() + } +} + +#[repr(transparent)] +pub struct StackTop(#[allow(dead_code)] *mut u8); + +unsafe impl Sync for StackTop {} + +const STACK_SIZE: usize = 4096; + +#[link_section = ".persistent"] +static STACK: Stack = Stack::new(); + +#[no_mangle] +static __sel4_reset__stack_top: StackTop = STACK.top(); + +// // // + +#[no_mangle] +unsafe extern "C" fn __sel4_reset__reset_memory() { + unsafe { + get_regions().reset_memory(); + } +} + +unsafe fn get_regions() -> Regions<'static> { + Regions { + meta: slice::from_raw_parts( + (sel4_reset_regions_start + sel4_reset_regions_meta_offset) as *const _, + sel4_reset_regions_meta_count, + ), + data: slice::from_raw_parts( + (sel4_reset_regions_start + sel4_reset_regions_data_offset) as *const _, + sel4_reset_regions_data_size, + ), + } +} + +// HACK to force variables into .rodata without causing .rodata to end up in a PF_W segment +macro_rules! rodata { + ($ident:ident) => { + extern "C" { + static $ident: usize; + } + global_asm! { + ".section .rodata", + concat!(".global ", stringify!($ident)), + concat!(stringify!($ident), ": ", asm_word_size!(), " 0"), + concat!(".size ", stringify!($ident), ", .-", stringify!($ident)), + } + }; +} + +cfg_if! { + if #[cfg(target_pointer_width = "64")] { + macro_rules! asm_word_size { + () => { + ".quad" + } + } + } else if #[cfg(target_pointer_width = "32")] { + macro_rules! asm_word_size { + () => { + ".word" + } + } + } else { + compile_error!("unsupported configuration"); + } +} + +rodata!(sel4_reset_regions_start); +rodata!(sel4_reset_regions_meta_offset); +rodata!(sel4_reset_regions_meta_count); +rodata!(sel4_reset_regions_data_offset); +rodata!(sel4_reset_regions_data_size); + +// // // + +pub fn reset() -> ! { + unsafe { + _reset(); + } + unreachable!() +} + +extern "C" { + fn _reset(); +} + +macro_rules! common_asm_prefix { + () => { + r#" + .extern _start + + .global _reset + + .section .text + + _reset: + "# + }; +} + +cfg_if::cfg_if! { + if #[cfg(target_arch = "aarch64")] { + global_asm! { + common_asm_prefix!(), + r#" + ldr x9, =__sel4_reset__stack_top + ldr x9, [x9] + mov sp, x9 + bl __sel4_reset__reset_memory + b _start + + 1: b 1b + "# + } + } else { + compile_error!("unsupported architecture"); + } +} diff --git a/hacking/nix/scope/default.nix b/hacking/nix/scope/default.nix index 74db4bf64..c6974a336 100644 --- a/hacking/nix/scope/default.nix +++ b/hacking/nix/scope/default.nix @@ -107,8 +107,14 @@ superCallPackage ../rust-utils {} self // ia32 = "i686"; }."${seL4Arch}"; - mkSeL4CustomRustTargetTripleName = { microkit ? false, minimal ? false }: - "${rustTargetArchName}-sel4${lib.optionalString microkit "-microkit"}${lib.optionalString minimal "-minimal"}"; + mkSeL4CustomRustTargetTripleName = { microkit ? false, resettable ? false, minimal ? false }: + lib.concatStrings [ + rustTargetArchName + "-sel4" + (lib.optionalString microkit "-microkit") + (lib.optionalString resettable "-resettable") + (lib.optionalString minimal "-minimal") + ]; mkSeL4RustTargetTriple = args: mkCustomRustTargetTriple (mkSeL4CustomRustTargetTripleName args); @@ -197,7 +203,9 @@ superCallPackage ../rust-utils {} self // sel4-capdl-initializer-add-spec = mkTool crates.sel4-capdl-initializer-add-spec; sel4-simple-task-runtime-config-cli = mkTool crates.sel4-simple-task-runtime-config-cli; sel4-kernel-loader-add-payload = mkTool crates.sel4-kernel-loader-add-payload; + sel4-reset-cli = mkTool crates.sel4-reset-cli; + prepareResettable = callPackage ./prepare-resettable.nix {}; embedDebugInfo = callPackage ./embed-debug-info.nix {}; shellForMakefile = callPackage ./shell-for-makefile.nix {}; diff --git a/hacking/nix/scope/prepare-resettable.nix b/hacking/nix/scope/prepare-resettable.nix new file mode 100644 index 000000000..6175466d0 --- /dev/null +++ b/hacking/nix/scope/prepare-resettable.nix @@ -0,0 +1,19 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ lib, runCommand +, sel4-reset-cli +}: + +elf: + +runCommand "elf" { + nativeBuildInputs = [ + sel4-reset-cli + ]; +} '' + sel4-reset-cli ${elf} -o $out +'' diff --git a/hacking/nix/scope/sources.nix b/hacking/nix/scope/sources.nix index 64bfc1e9f..530ade320 100644 --- a/hacking/nix/scope/sources.nix +++ b/hacking/nix/scope/sources.nix @@ -62,7 +62,7 @@ in rec { microkit = fetchGit { url = "https://github.com/coliasgroup/microkit.git"; - rev = "1ccdfcb3b224533c965fd6508de3dd56657f959c"; # branch "rust-nix" + rev = "9d5c0957720ae1093ab1a3cc9e15fc926dbe0431"; # branch "rust-nix" local = localRoot + "/microkit"; }; diff --git a/hacking/nix/scope/world/instances/default.nix b/hacking/nix/scope/world/instances/default.nix index 3e727069f..5baae710e 100644 --- a/hacking/nix/scope/world/instances/default.nix +++ b/hacking/nix/scope/world/instances/default.nix @@ -98,6 +98,7 @@ in rec { microkit.examples.banscii microkit.examples.http-server microkit.tests.passive-server-with-deferred-action + microkit.tests.reset examples.root-task.hello examples.root-task.example-root-task examples.root-task.example-root-task-without-runtime diff --git a/hacking/nix/scope/world/instances/microkit/default.nix b/hacking/nix/scope/world/instances/microkit/default.nix index f0adaf862..2311ff9a7 100644 --- a/hacking/nix/scope/world/instances/microkit/default.nix +++ b/hacking/nix/scope/world/instances/microkit/default.nix @@ -6,10 +6,11 @@ { lib, stdenv , buildPackages, pkgsBuildBuild -, linkFarm, symlinkJoin, writeText, runCommand +, linkFarm, symlinkJoin, writeText, runCommand, runCommandCC , callPackage , microkit , mkTask +, prepareResettable , sources , crates , crateUtils @@ -104,5 +105,52 @@ in { inherit pds; } ); + + reset = maybe isMicrokit ( + let + pd = rec { + orig = mkPD rec { + rootCrate = crates.tests-microkit-reset; + targetTriple = mkSeL4RustTargetTriple { + microkit = true; + resettable = true; + minimal = false; + }; + release = false; + }; + + origELF = "${orig}/bin/test.elf"; + + patched = prepareResettable origELF; + + sup = runCommandCC "test.sup.elf" {} '' + $OBJCOPY --only-keep-debug ${origELF} $out + ''; + }; + in + callPlatform { + system = microkit.mkSystem { + searchPath = [ + (linkFarm "pd" { + "test.elf" = pd.patched; + }) + (linkFarm "pd" { + "test.sup.elf" = pd.sup; + }) + ]; + systemXML = sources.srcRoot + "/crates/private/tests/microkit/reset/x.system"; + }; + extraPlatformArgs = lib.optionalAttrs canSimulate { + canAutomateSimply = true; + }; + extraDebuggingLinks = [ + { name = "test.orig.elf"; path = pd.origELF; } + { name = "test.patched.elf"; path = pd.patched; } + { name = "test.sup.elf"; path = pd.sup; } + ]; + } // { + inherit pd; + } + ); }; } From 8b6d34c1616e5ff443f065399f478ba61ccdb04f Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 3 Jul 2024 07:13:22 +0000 Subject: [PATCH 14/20] crates/sel4-render-elf-with-data: Add p_flags field to SymbolicInjection Signed-off-by: Nick Spinale --- .../cli/src/bin/sel4-embed-debug-info.rs | 3 ++- crates/sel4-capdl-initializer/add-spec/src/render_elf.rs | 5 ++++- crates/sel4-kernel-loader/add-payload/src/render_elf.rs | 3 ++- crates/sel4-render-elf-with-data/src/lib.rs | 9 +++++++++ crates/sel4-render-elf-with-data/src/render.rs | 4 ++-- crates/sel4-reset/cli/src/main.rs | 3 ++- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs b/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs index b3fbddb39..ed974db82 100644 --- a/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs +++ b/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs @@ -12,7 +12,7 @@ use num::{NumCast, One, PrimInt, Zero}; use sel4_render_elf_with_data::{ ConcreteFileHeader32, ConcreteFileHeader64, ElfBitWidth, FileHeaderExt, Input, - SymbolicInjection, SymbolicValue, + SymbolicInjection, SymbolicValue, PF_R, }; fn main() -> Result<(), io::Error> { @@ -72,6 +72,7 @@ fn with_bit_width>( align_residue: T::Word::zero(), content, memsz: content_len, + p_flags: PF_R, patches: vec![( "embedded_debug_info_start".to_owned(), SymbolicValue { diff --git a/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs b/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs index ceca0c75c..5de3b740f 100644 --- a/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs +++ b/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs @@ -6,7 +6,9 @@ use num::{NumCast, One, PrimInt, Zero}; -use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue}; +use sel4_render_elf_with_data::{ + FileHeaderExt, Input, SymbolicInjection, SymbolicValue, PF_R, PF_W, +}; pub(crate) struct RenderElfArgs<'a> { pub(crate) orig_elf: &'a [u8], @@ -28,6 +30,7 @@ impl<'a> RenderElfArgs<'a> { align_residue, content: self.data, memsz, + p_flags: PF_R | PF_W, patches: vec![ ( "sel4_capdl_initializer_serialized_spec_start".to_owned(), diff --git a/crates/sel4-kernel-loader/add-payload/src/render_elf.rs b/crates/sel4-kernel-loader/add-payload/src/render_elf.rs index d3184bed3..d5a3fa3b3 100644 --- a/crates/sel4-kernel-loader/add-payload/src/render_elf.rs +++ b/crates/sel4-kernel-loader/add-payload/src/render_elf.rs @@ -7,7 +7,7 @@ use num::{NumCast, One, PrimInt, Zero}; use object::{read::elf::FileHeader, Endianness}; -use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue}; +use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue, PF_R}; pub fn render_elf(orig_elf: &[u8], serialized_payload: &[u8]) -> Vec where @@ -22,6 +22,7 @@ where align_residue, content: serialized_payload, memsz: NumCast::from(memsz).unwrap(), + p_flags: PF_R, patches: vec![( "loader_payload_start".to_owned(), SymbolicValue { diff --git a/crates/sel4-render-elf-with-data/src/lib.rs b/crates/sel4-render-elf-with-data/src/lib.rs index 9f74336e2..138e6baa2 100644 --- a/crates/sel4-render-elf-with-data/src/lib.rs +++ b/crates/sel4-render-elf-with-data/src/lib.rs @@ -12,6 +12,8 @@ use object::{ Endian, Endianness, File, }; +pub use object::elf::{PF_R, PF_W, PF_X}; + mod render; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -89,6 +91,7 @@ pub struct SymbolicInjection<'a, T: FileHeaderExt> { pub align_residue: T::Word, pub content: &'a [u8], pub memsz: T::Word, + pub p_flags: u32, pub patches: Vec<(Symbol, SymbolicValue)>, } @@ -111,6 +114,7 @@ impl<'a, T: FileHeaderExt> SymbolicInjection<'a, T> { vaddr, content: self.content, memsz: self.memsz, + p_flags: self.p_flags, patches: self .patches .iter() @@ -129,6 +133,7 @@ pub struct Injection<'a, T: FileHeaderExt> { pub vaddr: T::Word, pub content: &'a [u8], pub memsz: T::Word, + pub p_flags: u32, pub patches: Vec<(Symbol, ConcreteValue)>, } @@ -149,6 +154,10 @@ impl<'a, T: FileHeaderExt> Injection<'a, T> { self.content } + fn p_flags(&self) -> u32 { + self.p_flags + } + fn patches(&self) -> impl Iterator)> { self.patches.iter() } diff --git a/crates/sel4-render-elf-with-data/src/render.rs b/crates/sel4-render-elf-with-data/src/render.rs index 3e6e14276..e6856073c 100644 --- a/crates/sel4-render-elf-with-data/src/render.rs +++ b/crates/sel4-render-elf-with-data/src/render.rs @@ -9,7 +9,7 @@ use std::mem; use anyhow::{anyhow, ensure, Result}; use num::{CheckedAdd, NumCast, ToPrimitive}; use object::{ - elf::{PF_R, PF_W, PT_LOAD}, + elf::PT_LOAD, read::elf::{ElfFile, FileHeader, ProgramHeader as _}, read::ReadRef, write::elf::{ProgramHeader, Writer}, @@ -92,7 +92,7 @@ impl<'a, T: FileHeaderExt> Input<'a, T> { let vaddr = injection.vaddr(); writer.write_program_header(&ProgramHeader { p_type: PT_LOAD, - p_flags: PF_R | PF_W, + p_flags: injection.p_flags(), p_offset: (*offset).try_into()?, p_vaddr: vaddr.into(), p_paddr: vaddr.into(), diff --git a/crates/sel4-reset/cli/src/main.rs b/crates/sel4-reset/cli/src/main.rs index 58dfe82d7..f3c4c08ca 100644 --- a/crates/sel4-reset/cli/src/main.rs +++ b/crates/sel4-reset/cli/src/main.rs @@ -9,7 +9,7 @@ use std::mem; use anyhow::Result; use num::{NumCast, Zero}; -use object::elf::{PF_W, PT_LOAD}; +use object::elf::{PF_R, PF_W, PT_LOAD}; use object::read::elf::{ElfFile, ProgramHeader}; use object::{Endian, File, Object, ObjectSection, ReadCache, ReadRef}; @@ -176,6 +176,7 @@ impl Regions { align_residue, content: &self.raw, memsz: NumCast::from(memsz).unwrap(), + p_flags: PF_R, patches: vec![( "sel4_reset_regions_start".to_owned(), SymbolicValue { From b9212629699535e7301d48be1aeb1013ab72efd4 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Mon, 8 Jul 2024 23:21:02 +0000 Subject: [PATCH 15/20] crates/sel4-stack: Introduce Signed-off-by: Nick Spinale --- Cargo.lock | 8 +++ Cargo.toml | 1 + .../examples/root-task/spawn-thread/Cargo.nix | 1 + .../root-task/spawn-thread/Cargo.toml | 1 + .../root-task/spawn-thread/src/main.rs | 22 ++------ crates/sel4-kernel-loader/Cargo.nix | 1 + crates/sel4-kernel-loader/Cargo.toml | 1 + crates/sel4-kernel-loader/src/this_image.rs | 35 ++----------- crates/sel4-reset/Cargo.nix | 3 +- crates/sel4-reset/Cargo.toml | 1 + crates/sel4-reset/src/lib.rs | 39 +------------- crates/sel4-runtime-common/Cargo.nix | 2 +- crates/sel4-runtime-common/Cargo.toml | 1 + crates/sel4-runtime-common/src/start.rs | 39 +------------- crates/sel4-stack/Cargo.nix | 11 ++++ crates/sel4-stack/Cargo.toml | 17 +++++++ crates/sel4-stack/src/lib.rs | 51 +++++++++++++++++++ 17 files changed, 109 insertions(+), 125 deletions(-) create mode 100644 crates/sel4-stack/Cargo.nix create mode 100644 crates/sel4-stack/Cargo.toml create mode 100644 crates/sel4-stack/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ded1c2e91..80456966b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2315,6 +2315,7 @@ dependencies = [ "sel4-pl011-driver", "sel4-platform-info", "sel4-rustfmt-helper", + "sel4-stack", "serde", "smccc", "spin 0.9.8", @@ -2534,6 +2535,7 @@ name = "sel4-reset" version = "0.1.0" dependencies = [ "cfg-if", + "sel4-stack", ] [[package]] @@ -2589,6 +2591,7 @@ dependencies = [ "sel4-elf-header", "sel4-initialize-tls", "sel4-panicking-env", + "sel4-stack", "unwinding", ] @@ -2732,6 +2735,10 @@ dependencies = [ "tock-registers", ] +[[package]] +name = "sel4-stack" +version = "0.1.0" + [[package]] name = "sel4-sync" version = "0.1.0" @@ -2943,6 +2950,7 @@ dependencies = [ "sel4-elf-header", "sel4-initialize-tls", "sel4-root-task", + "sel4-stack", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ba449efd6..ad2161dc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ members = [ "crates/sel4-shared-ring-buffer/block-io/types", "crates/sel4-shared-ring-buffer/bookkeeping", "crates/sel4-shared-ring-buffer/smoltcp", + "crates/sel4-stack", "crates/sel4-sync", "crates/sel4-test-harness", "crates/sel4/bitfield-ops", diff --git a/crates/examples/root-task/spawn-thread/Cargo.nix b/crates/examples/root-task/spawn-thread/Cargo.nix index 7f6fc9406..394991b1a 100644 --- a/crates/examples/root-task/spawn-thread/Cargo.nix +++ b/crates/examples/root-task/spawn-thread/Cargo.nix @@ -14,6 +14,7 @@ mk { sel4 sel4-root-task sel4-elf-header + sel4-stack sel4-initialize-tls ; }; diff --git a/crates/examples/root-task/spawn-thread/Cargo.toml b/crates/examples/root-task/spawn-thread/Cargo.toml index 95100b49a..c252b2263 100644 --- a/crates/examples/root-task/spawn-thread/Cargo.toml +++ b/crates/examples/root-task/spawn-thread/Cargo.toml @@ -22,3 +22,4 @@ sel4 = { path = "../../../sel4" } sel4-elf-header = { path = "../../../sel4-elf-header" } sel4-initialize-tls = { path = "../../../sel4-initialize-tls" } sel4-root-task = { path = "../../../sel4-root-task" } +sel4-stack = { path = "../../../sel4-stack" } diff --git a/crates/examples/root-task/spawn-thread/src/main.rs b/crates/examples/root-task/spawn-thread/src/main.rs index 19bb21049..b157de24e 100644 --- a/crates/examples/root-task/spawn-thread/src/main.rs +++ b/crates/examples/root-task/spawn-thread/src/main.rs @@ -24,6 +24,7 @@ use sel4_initialize_tls::{TlsImage, TlsReservationLayout, UncheckedTlsImage}; use sel4_root_task::{ abort, panicking::catch_unwind, root_task, set_global_allocator_mutex_notification, Never, }; +use sel4_stack::Stack; static SECONDARY_THREAD_STACK: Stack<4096> = Stack::new(); @@ -133,7 +134,9 @@ fn find_largest_kernel_untyped(bootinfo: &sel4::BootInfo) -> sel4::cap::Untyped fn create_user_context(f: SecondaryThreadFn) -> sel4::UserContext { let mut ctx = sel4::UserContext::default(); - *ctx.sp_mut() = SECONDARY_THREAD_STACK.top().try_into().unwrap(); + *ctx.sp_mut() = (SECONDARY_THREAD_STACK.top().ptr() as usize) + .try_into() + .unwrap(); *ctx.pc_mut() = (secondary_thread_entrypoint as usize).try_into().unwrap(); *ctx.c_param_mut(0) = f.into_arg(); @@ -253,23 +256,6 @@ fn get_tls_image() -> TlsImage { // // // -#[repr(C, align(16))] -struct Stack(UnsafeCell<[u8; N]>); - -unsafe impl Sync for Stack {} - -impl Stack { - const fn new() -> Self { - Self(UnsafeCell::new([0; N])) - } - - fn top(&self) -> usize { - (self.0.get() as usize) + N - } -} - -// // // - #[repr(C, align(4096))] struct IpcBufferFrame(UnsafeCell<[u8; GRANULE_SIZE]>); diff --git a/crates/sel4-kernel-loader/Cargo.nix b/crates/sel4-kernel-loader/Cargo.nix index be5cbb167..be78360c7 100644 --- a/crates/sel4-kernel-loader/Cargo.nix +++ b/crates/sel4-kernel-loader/Cargo.nix @@ -20,6 +20,7 @@ mk { sel4-config sel4-kernel-loader-embed-page-tables-runtime sel4-immutable-cell + sel4-stack ; sel4-kernel-loader-payload-types = localCrates.sel4-kernel-loader-payload-types // { features = [ "serde" ]; }; }; diff --git a/crates/sel4-kernel-loader/Cargo.toml b/crates/sel4-kernel-loader/Cargo.toml index 91bcc31d1..2203f9496 100644 --- a/crates/sel4-kernel-loader/Cargo.toml +++ b/crates/sel4-kernel-loader/Cargo.toml @@ -28,6 +28,7 @@ sel4-kernel-loader-embed-page-tables-runtime = { path = "embed-page-tables/runti sel4-kernel-loader-payload-types = { path = "payload-types", features = ["serde"] } sel4-logging = { path = "../sel4-logging" } sel4-platform-info = { path = "../sel4-platform-info" } +sel4-stack = { path = "../sel4-stack" } spin = { version = "0.9.4", features = ["lock_api"] } [build-dependencies] diff --git a/crates/sel4-kernel-loader/src/this_image.rs b/crates/sel4-kernel-loader/src/this_image.rs index 32a27b00d..f3ed5036b 100644 --- a/crates/sel4-kernel-loader/src/this_image.rs +++ b/crates/sel4-kernel-loader/src/this_image.rs @@ -52,29 +52,8 @@ pub(crate) mod page_tables { } pub(crate) mod stacks { - use core::cell::UnsafeCell; - use sel4_config::sel4_cfg_usize; - - #[repr(C, align(16))] - struct Stack(UnsafeCell<[u8; N]>); - - unsafe impl Sync for Stack {} - - impl Stack { - pub const fn new() -> Self { - Self(UnsafeCell::new([0; N])) - } - - pub const fn top(&self) -> StackTop { - StackTop(self.0.get().cast::().wrapping_add(N)) - } - } - - #[repr(transparent)] - pub struct StackTop(#[allow(dead_code)] *mut u8); - - unsafe impl Sync for StackTop {} + use sel4_stack::{Stack, StackTop}; const PRIMARY_STACK_SIZE: usize = 4096 * 8; // TODO this is excessive @@ -86,17 +65,13 @@ pub(crate) mod stacks { const NUM_SECONDARY_CORES: usize = sel4_cfg_usize!(MAX_NUM_NODES) - 1; const SECONDARY_STACK_SIZE: usize = 4096 * 2; - const SECONDARY_STACKS_SIZE: usize = SECONDARY_STACK_SIZE * NUM_SECONDARY_CORES; - static SECONDARY_STACKS: Stack = Stack::new(); + static SECONDARY_STACKS: [Stack; NUM_SECONDARY_CORES] = + [const { Stack::new() }; NUM_SECONDARY_CORES]; #[allow(clippy::zst_offset)] // for case where NUM_SECONDARY_CORES == 0 pub(crate) fn get_secondary_stack_bottom(core_id: usize) -> usize { - unsafe { - SECONDARY_STACKS - .0 - .get() - .offset((core_id * SECONDARY_STACK_SIZE).try_into().unwrap()) as usize - } + assert!(core_id > 0 && core_id < sel4_cfg_usize!(MAX_NUM_NODES)); + SECONDARY_STACKS[core_id - 1].top().ptr() as usize } } diff --git a/crates/sel4-reset/Cargo.nix b/crates/sel4-reset/Cargo.nix index b72744993..6c91b430f 100644 --- a/crates/sel4-reset/Cargo.nix +++ b/crates/sel4-reset/Cargo.nix @@ -4,11 +4,12 @@ # SPDX-License-Identifier: BSD-2-Clause # -{ mk, versions }: +{ mk, versions, localCrates }: mk { package.name = "sel4-reset"; dependencies = { inherit (versions) cfg-if; + inherit (localCrates) sel4-stack; }; } diff --git a/crates/sel4-reset/Cargo.toml b/crates/sel4-reset/Cargo.toml index 33da63163..4e3edbc85 100644 --- a/crates/sel4-reset/Cargo.toml +++ b/crates/sel4-reset/Cargo.toml @@ -18,3 +18,4 @@ license = "BSD-2-Clause" [dependencies] cfg-if = "1.0.0" +sel4-stack = { path = "../sel4-stack" } diff --git a/crates/sel4-reset/src/lib.rs b/crates/sel4-reset/src/lib.rs index 463b5b515..376aed3ce 100644 --- a/crates/sel4-reset/src/lib.rs +++ b/crates/sel4-reset/src/lib.rs @@ -7,12 +7,13 @@ #![no_std] use core::arch::global_asm; -use core::cell::UnsafeCell; use core::ptr; use core::slice; use cfg_if::cfg_if; +use sel4_stack::{Stack, StackTop}; + // // // #[repr(C)] @@ -43,42 +44,6 @@ impl<'a> Regions<'a> { // // // -#[repr(C)] -#[cfg_attr( - any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "x86_64", - ), - repr(align(16)) -)] -#[cfg_attr(target_arch = "arm", repr(align(4)))] -pub struct Stack(UnsafeCell<[u8; N]>); - -unsafe impl Sync for Stack {} - -impl Stack { - pub const fn new() -> Self { - Self(UnsafeCell::new([0; N])) - } - - pub const fn top(&self) -> StackTop { - StackTop(self.0.get().cast::().wrapping_add(N)) - } -} - -impl Default for Stack { - fn default() -> Self { - Self::new() - } -} - -#[repr(transparent)] -pub struct StackTop(#[allow(dead_code)] *mut u8); - -unsafe impl Sync for StackTop {} - const STACK_SIZE: usize = 4096; #[link_section = ".persistent"] diff --git a/crates/sel4-runtime-common/Cargo.nix b/crates/sel4-runtime-common/Cargo.nix index c9636d70a..d24744d96 100644 --- a/crates/sel4-runtime-common/Cargo.nix +++ b/crates/sel4-runtime-common/Cargo.nix @@ -10,7 +10,7 @@ mk { package.name = "sel4-runtime-common"; dependencies = { inherit (versions) cfg-if; - inherit (localCrates) sel4-panicking-env sel4-elf-header; + inherit (localCrates) sel4-panicking-env sel4-elf-header sel4-stack; sel4 = localCrates.sel4 // { default-features = false; optional = true; }; sel4-initialize-tls = localCrates.sel4-initialize-tls // { features = [ "on-stack" ]; optional = true; }; }; diff --git a/crates/sel4-runtime-common/Cargo.toml b/crates/sel4-runtime-common/Cargo.toml index a94de4448..fc8a81b16 100644 --- a/crates/sel4-runtime-common/Cargo.toml +++ b/crates/sel4-runtime-common/Cargo.toml @@ -26,6 +26,7 @@ sel4 = { path = "../sel4", default-features = false, optional = true } sel4-elf-header = { path = "../sel4-elf-header" } sel4-initialize-tls = { path = "../sel4-initialize-tls", features = ["on-stack"], optional = true } sel4-panicking-env = { path = "../sel4-panicking/env" } +sel4-stack = { path = "../sel4-stack" } [target."cfg(not(target_arch = \"arm\"))".dependencies.unwinding] version = "0.1.6" diff --git a/crates/sel4-runtime-common/src/start.rs b/crates/sel4-runtime-common/src/start.rs index 0b4a65565..c582342eb 100644 --- a/crates/sel4-runtime-common/src/start.rs +++ b/crates/sel4-runtime-common/src/start.rs @@ -8,43 +8,6 @@ // - guard pages for stack? use core::arch::global_asm; -use core::cell::UnsafeCell; - -#[repr(C)] -#[cfg_attr( - any( - target_arch = "aarch64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "x86_64", - ), - repr(align(16)) -)] -#[cfg_attr(target_arch = "arm", repr(align(4)))] -pub struct Stack(UnsafeCell<[u8; N]>); - -unsafe impl Sync for Stack {} - -impl Stack { - pub const fn new() -> Self { - Self(UnsafeCell::new([0; N])) - } - - pub const fn top(&self) -> StackTop { - StackTop(self.0.get().cast::().wrapping_add(N)) - } -} - -impl Default for Stack { - fn default() -> Self { - Self::new() - } -} - -#[repr(transparent)] -pub struct StackTop(#[allow(dead_code)] *mut u8); - -unsafe impl Sync for StackTop {} #[macro_export] macro_rules! declare_stack { @@ -158,5 +121,5 @@ cfg_if::cfg_if! { } pub mod _private { - pub use super::{Stack, StackTop}; + pub use sel4_stack::{Stack, StackTop}; } diff --git a/crates/sel4-stack/Cargo.nix b/crates/sel4-stack/Cargo.nix new file mode 100644 index 000000000..6c7cbbec8 --- /dev/null +++ b/crates/sel4-stack/Cargo.nix @@ -0,0 +1,11 @@ +# +# Copyright 2024, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk }: + +mk { + package.name = "sel4-stack"; +} diff --git a/crates/sel4-stack/Cargo.toml b/crates/sel4-stack/Cargo.toml new file mode 100644 index 000000000..1a546b880 --- /dev/null +++ b/crates/sel4-stack/Cargo.toml @@ -0,0 +1,17 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-stack" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" diff --git a/crates/sel4-stack/src/lib.rs b/crates/sel4-stack/src/lib.rs new file mode 100644 index 000000000..b1fa36bc8 --- /dev/null +++ b/crates/sel4-stack/src/lib.rs @@ -0,0 +1,51 @@ +// +// Copyright 2023, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +#![no_std] + +use core::cell::UnsafeCell; + +#[repr(C)] +#[cfg_attr( + any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "x86_64", + ), + repr(align(16)) +)] +#[cfg_attr(target_arch = "arm", repr(align(4)))] +pub struct Stack(UnsafeCell<[u8; N]>); + +unsafe impl Sync for Stack {} + +impl Stack { + pub const fn new() -> Self { + Self(UnsafeCell::new([0; N])) + } + + pub const fn top(&self) -> StackTop { + StackTop(self.0.get().cast::().wrapping_add(N)) + } +} + +impl Default for Stack { + fn default() -> Self { + Self::new() + } +} + +#[repr(transparent)] +pub struct StackTop(#[allow(dead_code)] *mut u8); + +impl StackTop { + pub fn ptr(&self) -> *mut u8 { + self.0 + } +} + +unsafe impl Sync for StackTop {} From 19cd172aac6dd6e5a87df60effacb4582856c62e Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Tue, 9 Jul 2024 06:43:29 +0000 Subject: [PATCH 16/20] crates/sel4-stack: Improve language Signed-off-by: Nick Spinale --- .../src/main.rs | 26 +++++++++---------- .../root-task/spawn-thread/src/main.rs | 2 +- crates/sel4-kernel-loader/asm/aarch32/head.S | 2 +- crates/sel4-kernel-loader/asm/aarch64/head.S | 2 +- crates/sel4-kernel-loader/asm/riscv/head.S | 6 ++--- crates/sel4-kernel-loader/src/this_image.rs | 6 ++--- crates/sel4-reset/src/lib.rs | 6 ++--- crates/sel4-runtime-common/src/start.rs | 16 ++++++------ crates/sel4-stack/src/lib.rs | 10 +++---- 9 files changed, 38 insertions(+), 38 deletions(-) diff --git a/crates/examples/root-task/example-root-task-without-runtime/src/main.rs b/crates/examples/root-task/example-root-task-without-runtime/src/main.rs index 36cc18f75..6f635370a 100644 --- a/crates/examples/root-task/example-root-task-without-runtime/src/main.rs +++ b/crates/examples/root-task/example-root-task-without-runtime/src/main.rs @@ -95,22 +95,22 @@ mod stack { Self(UnsafeCell::new([0; N])) } - pub const fn top(&self) -> StackTop { - StackTop(self.0.get().cast::().wrapping_add(N)) + pub const fn bottom(&self) -> StackBottom { + StackBottom(self.0.get().cast::().wrapping_add(N)) } } #[repr(transparent)] - pub struct StackTop(#[allow(dead_code)] *mut u8); + pub struct StackBottom(#[allow(dead_code)] *mut u8); - unsafe impl Sync for StackTop {} + unsafe impl Sync for StackBottom {} const STACK_SIZE: usize = 0x4000; static STACK: Stack = Stack::new(); #[no_mangle] - static __stack_top: StackTop = STACK.top(); + static __stack_bottom: StackBottom = STACK.bottom(); } cfg_if::cfg_if! { @@ -118,13 +118,13 @@ cfg_if::cfg_if! { global_asm! { r#" .extern __rust_entry - .extern __stack_top + .extern __stack_bottom .section .text .global _start _start: - ldr x9, =__stack_top + ldr x9, =__stack_bottom ldr x9, [x9] mov sp, x9 b __rust_entry @@ -136,13 +136,13 @@ cfg_if::cfg_if! { global_asm! { r#" .extern __rust_entry - .extern __stack_top + .extern __stack_bottom .section .text .global _start _start: - ldr r8, =__stack_top + ldr r8, =__stack_bottom ldr r8, [r8] mov sp, r8 b __rust_entry @@ -155,7 +155,7 @@ cfg_if::cfg_if! { () => { r#" .extern __rust_entry - .extern __stack_top + .extern __stack_bottom .section .text @@ -169,7 +169,7 @@ cfg_if::cfg_if! { addi gp, gp, %pcrel_lo(1b) .option pop - la sp, __stack_top + la sp, __stack_bottom lx sp, (sp) jal __rust_entry @@ -201,13 +201,13 @@ cfg_if::cfg_if! { global_asm! { r#" .extern __rust_entry - .extern __stack_top + .extern __stack_bottom .section .text .global _start _start: - mov rsp, __stack_top + mov rsp, __stack_bottom mov rbp, rsp sub rsp, 0x8 // Stack must be 16-byte aligned before call push rbp diff --git a/crates/examples/root-task/spawn-thread/src/main.rs b/crates/examples/root-task/spawn-thread/src/main.rs index b157de24e..67fb6c5cf 100644 --- a/crates/examples/root-task/spawn-thread/src/main.rs +++ b/crates/examples/root-task/spawn-thread/src/main.rs @@ -134,7 +134,7 @@ fn find_largest_kernel_untyped(bootinfo: &sel4::BootInfo) -> sel4::cap::Untyped fn create_user_context(f: SecondaryThreadFn) -> sel4::UserContext { let mut ctx = sel4::UserContext::default(); - *ctx.sp_mut() = (SECONDARY_THREAD_STACK.top().ptr() as usize) + *ctx.sp_mut() = (SECONDARY_THREAD_STACK.bottom().ptr() as usize) .try_into() .unwrap(); *ctx.pc_mut() = (secondary_thread_entrypoint as usize).try_into().unwrap(); diff --git a/crates/sel4-kernel-loader/asm/aarch32/head.S b/crates/sel4-kernel-loader/asm/aarch32/head.S index 26adcbc39..127b52901 100644 --- a/crates/sel4-kernel-loader/asm/aarch32/head.S +++ b/crates/sel4-kernel-loader/asm/aarch32/head.S @@ -51,7 +51,7 @@ clearzi: clearzi_exit: - ldr r9, =__primary_stack_top + ldr r9, =__primary_stack_bottom ldr r9, [r9] mov sp, r9 bl leave_hyp diff --git a/crates/sel4-kernel-loader/asm/aarch64/head.S b/crates/sel4-kernel-loader/asm/aarch64/head.S index 5cf466ed7..6fe8f6d1c 100644 --- a/crates/sel4-kernel-loader/asm/aarch64/head.S +++ b/crates/sel4-kernel-loader/asm/aarch64/head.S @@ -36,7 +36,7 @@ clear_bss_loop: cmp x0, x1 b.lt clear_bss_loop - ldr x9, =__primary_stack_top + ldr x9, =__primary_stack_bottom ldr x9, [x9] mov sp, x9 bl init_core_state diff --git a/crates/sel4-kernel-loader/asm/riscv/head.S b/crates/sel4-kernel-loader/asm/riscv/head.S index 8ec9a82e6..34e644fec 100644 --- a/crates/sel4-kernel-loader/asm/riscv/head.S +++ b/crates/sel4-kernel-loader/asm/riscv/head.S @@ -8,7 +8,7 @@ #include .extern __global_pointer$ -.extern __primary_stack_top +.extern __primary_stack_bottom .extern hsm_exists .extern next_logical_core_id .extern start_core_by_logical_id @@ -66,7 +66,7 @@ _start: mv s2, a1 /* preserve a1 (dtb) in s2 */ /* Attach the stack to sp before calling any C functions */ - la sp, __primary_stack_top + la sp, __primary_stack_bottom lx sp, (sp) /* Check if the Heart State Management (HSM) extension exists, so it can be @@ -123,7 +123,7 @@ _start1: /* a0 must hold current hard ID passed by bootloader */ /* This HART may be a different HART to the one that started at _start * If we've switched HARTs then the other HART will get a different stack * region in secondary_harts. */ - la sp, __primary_stack_top + la sp, __primary_stack_bottom lx sp, (sp) /* The C code expects the registers to be set up as: * a0 = hart id diff --git a/crates/sel4-kernel-loader/src/this_image.rs b/crates/sel4-kernel-loader/src/this_image.rs index f3ed5036b..8c115e066 100644 --- a/crates/sel4-kernel-loader/src/this_image.rs +++ b/crates/sel4-kernel-loader/src/this_image.rs @@ -53,14 +53,14 @@ pub(crate) mod page_tables { pub(crate) mod stacks { use sel4_config::sel4_cfg_usize; - use sel4_stack::{Stack, StackTop}; + use sel4_stack::{Stack, StackBottom}; const PRIMARY_STACK_SIZE: usize = 4096 * 8; // TODO this is excessive static PRIMARY_STACK: Stack = Stack::new(); #[no_mangle] - static __primary_stack_top: StackTop = PRIMARY_STACK.top(); + static __primary_stack_bottom: StackBottom = PRIMARY_STACK.bottom(); const NUM_SECONDARY_CORES: usize = sel4_cfg_usize!(MAX_NUM_NODES) - 1; @@ -72,6 +72,6 @@ pub(crate) mod stacks { #[allow(clippy::zst_offset)] // for case where NUM_SECONDARY_CORES == 0 pub(crate) fn get_secondary_stack_bottom(core_id: usize) -> usize { assert!(core_id > 0 && core_id < sel4_cfg_usize!(MAX_NUM_NODES)); - SECONDARY_STACKS[core_id - 1].top().ptr() as usize + SECONDARY_STACKS[core_id - 1].bottom().ptr() as usize } } diff --git a/crates/sel4-reset/src/lib.rs b/crates/sel4-reset/src/lib.rs index 376aed3ce..6ec2ee0f0 100644 --- a/crates/sel4-reset/src/lib.rs +++ b/crates/sel4-reset/src/lib.rs @@ -12,7 +12,7 @@ use core::slice; use cfg_if::cfg_if; -use sel4_stack::{Stack, StackTop}; +use sel4_stack::{Stack, StackBottom}; // // // @@ -50,7 +50,7 @@ const STACK_SIZE: usize = 4096; static STACK: Stack = Stack::new(); #[no_mangle] -static __sel4_reset__stack_top: StackTop = STACK.top(); +static __sel4_reset__stack_bottom: StackBottom = STACK.bottom(); // // // @@ -145,7 +145,7 @@ cfg_if::cfg_if! { global_asm! { common_asm_prefix!(), r#" - ldr x9, =__sel4_reset__stack_top + ldr x9, =__sel4_reset__stack_bottom ldr x9, [x9] mov sp, x9 bl __sel4_reset__reset_memory diff --git a/crates/sel4-runtime-common/src/start.rs b/crates/sel4-runtime-common/src/start.rs index c582342eb..c1068517d 100644 --- a/crates/sel4-runtime-common/src/start.rs +++ b/crates/sel4-runtime-common/src/start.rs @@ -13,10 +13,10 @@ use core::arch::global_asm; macro_rules! declare_stack { ($size:expr) => { #[no_mangle] - static __sel4_runtime_common__stack_top: $crate::_private::start::StackTop = { + static __sel4_runtime_common__stack_bottom: $crate::_private::start::StackBottom = { static STACK: $crate::_private::start::Stack<{ $size }> = $crate::_private::start::Stack::new(); - STACK.top() + STACK.bottom() }; }; } @@ -25,7 +25,7 @@ macro_rules! common_asm_prefix { () => { r#" .extern sel4_runtime_rust_entry - .extern __sel4_runtime_common__stack_top + .extern __sel4_runtime_common__stack_bottom .global _start @@ -41,7 +41,7 @@ cfg_if::cfg_if! { global_asm! { common_asm_prefix!(), r#" - ldr x9, =__sel4_runtime_common__stack_top + ldr x9, =__sel4_runtime_common__stack_bottom ldr x9, [x9] mov sp, x9 b sel4_runtime_rust_entry @@ -53,7 +53,7 @@ cfg_if::cfg_if! { global_asm! { common_asm_prefix!(), r#" - ldr r8, =__sel4_runtime_common__stack_top + ldr r8, =__sel4_runtime_common__stack_bottom ldr r8, [r8] mov sp, r8 b sel4_runtime_rust_entry @@ -72,7 +72,7 @@ cfg_if::cfg_if! { addi gp, gp, %pcrel_lo(1b) .option pop - la sp, __sel4_runtime_common__stack_top + la sp, __sel4_runtime_common__stack_bottom lx sp, (sp) jal sel4_runtime_rust_entry @@ -106,7 +106,7 @@ cfg_if::cfg_if! { global_asm! { common_asm_prefix!(), r#" - mov rsp, __sel4_runtime_common__stack_top + mov rsp, __sel4_runtime_common__stack_bottom mov rbp, rsp sub rsp, 0x8 // Stack must be 16-byte aligned before call push rbp @@ -121,5 +121,5 @@ cfg_if::cfg_if! { } pub mod _private { - pub use sel4_stack::{Stack, StackTop}; + pub use sel4_stack::{Stack, StackBottom}; } diff --git a/crates/sel4-stack/src/lib.rs b/crates/sel4-stack/src/lib.rs index b1fa36bc8..af18cd0a4 100644 --- a/crates/sel4-stack/src/lib.rs +++ b/crates/sel4-stack/src/lib.rs @@ -28,8 +28,8 @@ impl Stack { Self(UnsafeCell::new([0; N])) } - pub const fn top(&self) -> StackTop { - StackTop(self.0.get().cast::().wrapping_add(N)) + pub const fn bottom(&self) -> StackBottom { + StackBottom(self.0.get().cast::().wrapping_add(N)) } } @@ -40,12 +40,12 @@ impl Default for Stack { } #[repr(transparent)] -pub struct StackTop(#[allow(dead_code)] *mut u8); +pub struct StackBottom(#[allow(dead_code)] *mut u8); -impl StackTop { +impl StackBottom { pub fn ptr(&self) -> *mut u8 { self.0 } } -unsafe impl Sync for StackTop {} +unsafe impl Sync for StackBottom {} From cfa1dea9efddc5afcbe2b85ee53d72cb3af548a1 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Tue, 9 Jul 2024 06:46:33 +0000 Subject: [PATCH 17/20] crates/sel4-kernel-loader: Refactor Signed-off-by: Nick Spinale --- crates/sel4-kernel-loader/src/main.rs | 2 +- crates/sel4-kernel-loader/src/this_image.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/sel4-kernel-loader/src/main.rs b/crates/sel4-kernel-loader/src/main.rs index 87e384b58..5f27f77e3 100644 --- a/crates/sel4-kernel-loader/src/main.rs +++ b/crates/sel4-kernel-loader/src/main.rs @@ -71,7 +71,7 @@ fn main(per_core: ::PerCore) -> ! { } for core_id in 1..MAX_NUM_NODES { - let sp = this_image::stacks::get_secondary_stack_bottom(core_id); + let sp = this_image::stacks::get_secondary_stack_bottom(core_id).ptr() as usize; { let mut init_info = SECONDARY_CORE_INIT_INFO.write(); *init_info = Some(SecondaryCoreInitInfo { diff --git a/crates/sel4-kernel-loader/src/this_image.rs b/crates/sel4-kernel-loader/src/this_image.rs index 8c115e066..83657eaf3 100644 --- a/crates/sel4-kernel-loader/src/this_image.rs +++ b/crates/sel4-kernel-loader/src/this_image.rs @@ -70,8 +70,8 @@ pub(crate) mod stacks { [const { Stack::new() }; NUM_SECONDARY_CORES]; #[allow(clippy::zst_offset)] // for case where NUM_SECONDARY_CORES == 0 - pub(crate) fn get_secondary_stack_bottom(core_id: usize) -> usize { + pub(crate) fn get_secondary_stack_bottom(core_id: usize) -> StackBottom { assert!(core_id > 0 && core_id < sel4_cfg_usize!(MAX_NUM_NODES)); - SECONDARY_STACKS[core_id - 1].bottom().ptr() as usize + SECONDARY_STACKS[core_id - 1].bottom() } } From b34d1bfac97e6bf7d1992feb3fa3533b2910e9b6 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Tue, 9 Jul 2024 07:21:58 +0000 Subject: [PATCH 18/20] crates/sel4-synthetic-elf: Introduce Signed-off-by: Nick Spinale --- Cargo.lock | 18 +- Cargo.toml | 1 + .../embedded-debug-info/cli/Cargo.nix | 2 +- .../embedded-debug-info/cli/Cargo.toml | 2 +- .../cli/src/bin/sel4-embed-debug-info.rs | 61 +++--- .../sel4-capdl-initializer/add-spec/Cargo.nix | 2 +- .../add-spec/Cargo.toml | 2 +- .../add-spec/src/main.rs | 15 +- .../add-spec/src/render_elf.rs | 112 ++++++---- .../sel4-kernel-loader/add-payload/Cargo.nix | 2 +- .../sel4-kernel-loader/add-payload/Cargo.toml | 2 +- .../add-payload/src/main.rs | 12 +- .../add-payload/src/render_elf.rs | 60 +++--- crates/sel4-reset/cli/Cargo.nix | 3 +- crates/sel4-reset/cli/Cargo.toml | 3 +- crates/sel4-reset/cli/src/main.rs | 141 ++++++------ crates/sel4-synthetic-elf/Cargo.nix | 15 ++ crates/sel4-synthetic-elf/Cargo.toml | 22 ++ crates/sel4-synthetic-elf/src/lib.rs | 118 ++++++++++ crates/sel4-synthetic-elf/src/patches.rs | 175 +++++++++++++++ crates/sel4-synthetic-elf/src/segments.rs | 203 ++++++++++++++++++ .../manifest-scope.nix | 1 + 22 files changed, 758 insertions(+), 214 deletions(-) create mode 100644 crates/sel4-synthetic-elf/Cargo.nix create mode 100644 crates/sel4-synthetic-elf/Cargo.toml create mode 100644 crates/sel4-synthetic-elf/src/lib.rs create mode 100644 crates/sel4-synthetic-elf/src/patches.rs create mode 100644 crates/sel4-synthetic-elf/src/segments.rs diff --git a/Cargo.lock b/Cargo.lock index 80456966b..c7ac08f24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2004,7 +2004,7 @@ version = "0.1.0" dependencies = [ "clap", "num", - "sel4-render-elf-with-data", + "sel4-synthetic-elf", ] [[package]] @@ -2093,7 +2093,7 @@ dependencies = [ "object", "postcard", "sel4-capdl-initializer-types", - "sel4-render-elf-with-data", + "sel4-synthetic-elf", "serde_json", ] @@ -2335,7 +2335,7 @@ dependencies = [ "sel4-config-generic-types", "sel4-kernel-loader-config-types", "sel4-kernel-loader-payload-types", - "sel4-render-elf-with-data", + "sel4-synthetic-elf", "serde", "serde_json", "serde_yaml", @@ -2546,8 +2546,7 @@ dependencies = [ "clap", "fallible-iterator 0.2.0", "num", - "object", - "sel4-render-elf-with-data", + "sel4-synthetic-elf", ] [[package]] @@ -2748,6 +2747,15 @@ dependencies = [ "sel4-immediate-sync-once-cell", ] +[[package]] +name = "sel4-synthetic-elf" +version = "0.1.0" +dependencies = [ + "num", + "object", + "thiserror", +] + [[package]] name = "sel4-sys" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index ad2161dc4..97ddabb50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,6 +137,7 @@ members = [ "crates/sel4-shared-ring-buffer/smoltcp", "crates/sel4-stack", "crates/sel4-sync", + "crates/sel4-synthetic-elf", "crates/sel4-test-harness", "crates/sel4/bitfield-ops", "crates/sel4/bitfield-parser", diff --git a/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.nix b/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.nix index d874d6425..bea5cb793 100644 --- a/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.nix +++ b/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.nix @@ -10,6 +10,6 @@ mk { package.name = "sel4-backtrace-embedded-debug-info-cli"; dependencies = { inherit (versions) num clap; - inherit (localCrates) sel4-render-elf-with-data; + inherit (localCrates) sel4-synthetic-elf; }; } diff --git a/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.toml b/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.toml index 5d81c96cc..368bd4e8d 100644 --- a/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.toml +++ b/crates/sel4-backtrace/embedded-debug-info/cli/Cargo.toml @@ -19,4 +19,4 @@ license = "BSD-2-Clause" [dependencies] clap = "4.4.6" num = "0.4.1" -sel4-render-elf-with-data = { path = "../../../sel4-render-elf-with-data" } +sel4-synthetic-elf = { path = "../../../sel4-synthetic-elf" } diff --git a/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs b/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs index ed974db82..f501747eb 100644 --- a/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs +++ b/crates/sel4-backtrace/embedded-debug-info/cli/src/bin/sel4-embed-debug-info.rs @@ -8,12 +8,9 @@ use std::fs; use std::io; use clap::{Arg, Command}; -use num::{NumCast, One, PrimInt, Zero}; +use num::NumCast; -use sel4_render_elf_with_data::{ - ConcreteFileHeader32, ConcreteFileHeader64, ElfBitWidth, FileHeaderExt, Input, - SymbolicInjection, SymbolicValue, PF_R, -}; +use sel4_synthetic_elf::{object, Builder, PatchValue, Segment}; fn main() -> Result<(), io::Error> { let matches = Command::new("") @@ -50,38 +47,38 @@ fn main() -> Result<(), io::Error> { .to_owned(); let out_elf_path = matches.get_one::("out_elf").unwrap().to_owned(); - let image_elf = fs::read(image_elf_path)?; - let debug_info_elf = fs::read(debug_info_elf_path)?; + let image_elf_buf = fs::read(image_elf_path)?; + let debug_info_elf_buf = fs::read(debug_info_elf_path)?; - let out_elf = match ElfBitWidth::detect(&image_elf).unwrap() { - ElfBitWidth::Elf32 => with_bit_width::(&image_elf, &debug_info_elf), - ElfBitWidth::Elf64 => with_bit_width::(&image_elf, &debug_info_elf), + let out_elf_buf = match object::File::parse(&*image_elf_buf).unwrap() { + object::File::Elf32(image_elf) => with_bit_width(&image_elf, &debug_info_elf_buf), + object::File::Elf64(image_elf) => with_bit_width(&image_elf, &debug_info_elf_buf), + _ => { + panic!() + } }; - fs::write(out_elf_path, out_elf) + fs::write(out_elf_path, out_elf_buf) } -fn with_bit_width>( - image_elf: &[u8], +fn with_bit_width>( + image_elf: &object::read::elf::ElfFile, content: &[u8], ) -> Vec { - let content_len = NumCast::from(content.len()).unwrap(); - let mut input = Input::::default(); - input.symbolic_injections.push(SymbolicInjection { - align_modulus: T::Word::one(), - align_residue: T::Word::zero(), - content, - memsz: content_len, - p_flags: PF_R, - patches: vec![( - "embedded_debug_info_start".to_owned(), - SymbolicValue { - addend: T::Sword::zero(), - }, - )], - }); - input - .concrete_patches - .push(("embedded_debug_info_size".to_owned(), content_len)); - input.render_with_data(image_elf).unwrap() + let mut builder = Builder::new(&image_elf).unwrap(); + + builder.discard_p_align(true); + + let vaddr = builder.footprint().unwrap().end.next_multiple_of(4096); + + builder.add_segment(Segment::simple(vaddr, content.into())); + + builder + .patch_word_with_cast("embedded_debug_info_start", vaddr) + .unwrap(); + builder + .patch_word_with_cast("embedded_debug_info_size", content.len()) + .unwrap(); + + builder.build().unwrap() } diff --git a/crates/sel4-capdl-initializer/add-spec/Cargo.nix b/crates/sel4-capdl-initializer/add-spec/Cargo.nix index c32aaaccc..e8143390a 100644 --- a/crates/sel4-capdl-initializer/add-spec/Cargo.nix +++ b/crates/sel4-capdl-initializer/add-spec/Cargo.nix @@ -19,7 +19,7 @@ mk { object = { version = versions.object; features = [ "all" ]; }; postcard = postcardWith [ "alloc" ]; inherit (localCrates) - sel4-render-elf-with-data + sel4-synthetic-elf ; sel4-capdl-initializer-types = localCrates.sel4-capdl-initializer-types // { features = [ "std" "serde" "deflate" ]; }; }; diff --git a/crates/sel4-capdl-initializer/add-spec/Cargo.toml b/crates/sel4-capdl-initializer/add-spec/Cargo.toml index 8d2af034c..dfea20da8 100644 --- a/crates/sel4-capdl-initializer/add-spec/Cargo.toml +++ b/crates/sel4-capdl-initializer/add-spec/Cargo.toml @@ -24,5 +24,5 @@ num = "0.4.1" object = { version = "0.36.1", features = ["all"] } postcard = { version = "1.0.2", default-features = false, features = ["alloc"] } sel4-capdl-initializer-types = { path = "../types", features = ["std", "serde", "deflate"] } -sel4-render-elf-with-data = { path = "../../sel4-render-elf-with-data" } +sel4-synthetic-elf = { path = "../../sel4-synthetic-elf" } serde_json = "1.0.87" diff --git a/crates/sel4-capdl-initializer/add-spec/src/main.rs b/crates/sel4-capdl-initializer/add-spec/src/main.rs index 8fb4a6989..946bc985f 100644 --- a/crates/sel4-capdl-initializer/add-spec/src/main.rs +++ b/crates/sel4-capdl-initializer/add-spec/src/main.rs @@ -9,7 +9,6 @@ use std::fs; use anyhow::Result; use sel4_capdl_initializer_types::{Footprint, InputSpec}; -use sel4_render_elf_with_data::{ConcreteFileHeader32, ConcreteFileHeader64, ElfBitWidth}; mod args; mod render_elf; @@ -27,7 +26,7 @@ fn main() -> Result<()> { eprintln!("{:#?}", args); } - let initializer_elf = fs::read(&args.initializer_elf_path)?; + let initializer_elf_buf = fs::read(&args.initializer_elf_path)?; let spec_json = fs::read_to_string(&args.spec_json_path)?; let fill_dir_path = &args.fill_dir_path; let out_file_path = &args.out_file_path; @@ -56,17 +55,19 @@ fn main() -> Result<()> { } let render_elf_args = render_elf::RenderElfArgs { - orig_elf: &initializer_elf, data: &serialized_spec, granule_size_bits: GRANULE_SIZE_BITS, heap_size, }; - let rendered_initializer_elf = match ElfBitWidth::detect(&initializer_elf).unwrap() { - ElfBitWidth::Elf32 => render_elf_args.call_with::(), - ElfBitWidth::Elf64 => render_elf_args.call_with::(), + let rendered_initializer_elf_buf = match object::File::parse(&*initializer_elf_buf).unwrap() { + object::File::Elf32(initializer_elf) => render_elf_args.call_with(&initializer_elf), + object::File::Elf64(initializer_elf) => render_elf_args.call_with(&initializer_elf), + _ => { + panic!() + } }; - fs::write(out_file_path, rendered_initializer_elf)?; + fs::write(out_file_path, rendered_initializer_elf_buf)?; Ok(()) } diff --git a/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs b/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs index 5de3b740f..ce3796299 100644 --- a/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs +++ b/crates/sel4-capdl-initializer/add-spec/src/render_elf.rs @@ -4,61 +4,79 @@ // SPDX-License-Identifier: BSD-2-Clause // -use num::{NumCast, One, PrimInt, Zero}; +use num::NumCast; +use object::read::elf::FileHeader; -use sel4_render_elf_with_data::{ - FileHeaderExt, Input, SymbolicInjection, SymbolicValue, PF_R, PF_W, -}; +use sel4_synthetic_elf::{Builder, PatchValue, Segment, PF_W}; pub(crate) struct RenderElfArgs<'a> { - pub(crate) orig_elf: &'a [u8], pub(crate) data: &'a [u8], pub(crate) granule_size_bits: usize, pub(crate) heap_size: usize, } impl<'a> RenderElfArgs<'a> { - pub(crate) fn call_with>(&self) -> Vec { - let data_len: T::Word = NumCast::from(self.data.len()).unwrap(); - let heap_size: T::Word = NumCast::from(self.heap_size).unwrap(); - let align_modulus = T::Word::one() << self.granule_size_bits; - let align_residue = (align_modulus - data_len % align_modulus) % align_modulus; - let memsz = data_len + heap_size; - let mut input = Input::::default(); - input.symbolic_injections.push(SymbolicInjection { - align_modulus, - align_residue, - content: self.data, - memsz, - p_flags: PF_R | PF_W, - patches: vec![ - ( - "sel4_capdl_initializer_serialized_spec_start".to_owned(), - SymbolicValue { - addend: T::Sword::zero(), - }, - ), - ( - "sel4_capdl_initializer_heap_start".to_owned(), - SymbolicValue { - addend: NumCast::from(data_len).unwrap(), - }, - ), - ], - }); - input - .image_start_patches - .push("sel4_capdl_initializer_image_start".to_owned()); - input - .image_end_patches - .push("sel4_capdl_initializer_image_end".to_owned()); - input.concrete_patches.push(( - "sel4_capdl_initializer_serialized_spec_size".to_owned(), - data_len, - )); - input - .concrete_patches - .push(("sel4_capdl_initializer_heap_size".to_owned(), heap_size)); - input.render_with_data(self.orig_elf).unwrap() + pub(crate) fn call_with>( + &self, + orig_elf: &object::read::elf::ElfFile, + ) -> Vec { + let mut builder = Builder::new(&orig_elf).unwrap(); + + builder.discard_p_align(true); + + let granule_size_bytes = 1 << self.granule_size_bits; + + { + let align_residue = (granule_size_bytes + - u64::try_from(self.data.len()).unwrap() % granule_size_bytes) + % granule_size_bytes; + + let vaddr = builder.next_vaddr().next_multiple_of(granule_size_bytes) + align_residue; + + builder.add_segment(Segment::simple(vaddr, self.data.into())); + + builder + .patch_word_with_cast("sel4_capdl_initializer_serialized_spec_start", vaddr) + .unwrap(); + builder + .patch_word_with_cast( + "sel4_capdl_initializer_serialized_spec_size", + self.data.len(), + ) + .unwrap(); + } + + { + let vaddr = builder.next_vaddr().next_multiple_of(granule_size_bytes); + + builder.add_segment({ + let mut segment = Segment::simple(vaddr, vec![].into()); + segment.p_flags |= PF_W; + segment.p_memsz = u64::try_from(self.heap_size).unwrap(); + segment + }); + + builder + .patch_word_with_cast("sel4_capdl_initializer_heap_start", vaddr) + .unwrap(); + builder + .patch_word_with_cast("sel4_capdl_initializer_heap_size", self.heap_size) + .unwrap(); + } + + builder + .patch_word_with_cast( + "sel4_capdl_initializer_image_start", + builder.footprint().unwrap().start, + ) + .unwrap(); + builder + .patch_word_with_cast( + "sel4_capdl_initializer_image_end", + builder.footprint().unwrap().end, + ) + .unwrap(); + + builder.build().unwrap() } } diff --git a/crates/sel4-kernel-loader/add-payload/Cargo.nix b/crates/sel4-kernel-loader/add-payload/Cargo.nix index ba2cb2b66..0b32fd51c 100644 --- a/crates/sel4-kernel-loader/add-payload/Cargo.nix +++ b/crates/sel4-kernel-loader/add-payload/Cargo.nix @@ -23,7 +23,7 @@ mk { serde = serdeWith [ "alloc" "derive" ]; inherit (localCrates) sel4-kernel-loader-config-types - sel4-render-elf-with-data + sel4-synthetic-elf ; sel4-kernel-loader-payload-types = localCrates.sel4-kernel-loader-payload-types // { features = [ "serde" ]; }; sel4-config-generic-types = localCrates.sel4-config-generic-types // { features = [ "serde" ]; }; diff --git a/crates/sel4-kernel-loader/add-payload/Cargo.toml b/crates/sel4-kernel-loader/add-payload/Cargo.toml index 9a670845d..4e2f7aa6b 100644 --- a/crates/sel4-kernel-loader/add-payload/Cargo.toml +++ b/crates/sel4-kernel-loader/add-payload/Cargo.toml @@ -27,7 +27,7 @@ postcard = { version = "1.0.2", default-features = false, features = ["alloc"] } sel4-config-generic-types = { path = "../../sel4/config/generic/types", features = ["serde"] } sel4-kernel-loader-config-types = { path = "../config-types" } sel4-kernel-loader-payload-types = { path = "../payload-types", features = ["serde"] } -sel4-render-elf-with-data = { path = "../../sel4-render-elf-with-data" } +sel4-synthetic-elf = { path = "../../sel4-synthetic-elf" } serde = { version = "1.0.147", default-features = false, features = ["alloc", "derive"] } serde_json = "1.0.87" serde_yaml = "0.9.14" diff --git a/crates/sel4-kernel-loader/add-payload/src/main.rs b/crates/sel4-kernel-loader/add-payload/src/main.rs index 3cdea1c9c..b32b24fe8 100644 --- a/crates/sel4-kernel-loader/add-payload/src/main.rs +++ b/crates/sel4-kernel-loader/add-payload/src/main.rs @@ -16,7 +16,7 @@ use object::{ use serde::Serialize; use sel4_config_generic_types::Configuration; -use sel4_render_elf_with_data::FileHeaderExt; +use sel4_synthetic_elf::PatchValue; mod args; mod render_elf; @@ -53,12 +53,10 @@ fn main() -> Result<()> { fn continue_with_word_size(args: &Args) -> Result<()> where - T: FileHeaderExt - + FileHeader< - Word: PrimInt + WrappingSub + Integer + Serialize, - Sword: PrimInt, - Endian = Endianness, - >, + T: FileHeader< + Word: PrimInt + WrappingSub + Integer + Serialize + PatchValue, + Endian = Endianness, + >, { let loader_bytes = fs::read(&args.loader_path)?; diff --git a/crates/sel4-kernel-loader/add-payload/src/render_elf.rs b/crates/sel4-kernel-loader/add-payload/src/render_elf.rs index d5a3fa3b3..222af59dc 100644 --- a/crates/sel4-kernel-loader/add-payload/src/render_elf.rs +++ b/crates/sel4-kernel-loader/add-payload/src/render_elf.rs @@ -4,39 +4,37 @@ // SPDX-License-Identifier: BSD-2-Clause // -use num::{NumCast, One, PrimInt, Zero}; -use object::{read::elf::FileHeader, Endianness}; +use num::NumCast; +use object::read::elf::FileHeader; -use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue, PF_R}; +use sel4_synthetic_elf::{Builder, PatchValue, Segment}; -pub fn render_elf(orig_elf: &[u8], serialized_payload: &[u8]) -> Vec +pub fn render_elf(orig_elf_buffer: &[u8], serialized_payload: &[u8]) -> Vec where - T: FileHeaderExt + FileHeader, + T: FileHeader, { - let align_modulus = T::Word::one(); - let align_residue = T::Word::one(); - let memsz = serialized_payload.len(); - let mut input = Input::::default(); - input.symbolic_injections.push(SymbolicInjection { - align_modulus, - align_residue, - content: serialized_payload, - memsz: NumCast::from(memsz).unwrap(), - p_flags: PF_R, - patches: vec![( - "loader_payload_start".to_owned(), - SymbolicValue { - addend: T::Sword::zero(), - }, - )], - }); - input - .image_start_patches - .push("loader_image_start".to_owned()); - input.image_end_patches.push("loader_image_end".to_owned()); - input.concrete_patches.push(( - "loader_payload_size".to_owned(), - NumCast::from(serialized_payload.len()).unwrap(), - )); - input.render_with_data(orig_elf).unwrap() + let orig_elf_file = &object::read::elf::ElfFile::::parse(orig_elf_buffer).unwrap(); + + let mut builder = Builder::new(&orig_elf_file).unwrap(); + + builder.discard_p_align(true); + + let vaddr = builder.next_vaddr().next_multiple_of(4096); + + builder.add_segment(Segment::simple(vaddr, serialized_payload.into())); + + builder + .patch_word_with_cast("loader_payload_start", vaddr) + .unwrap(); + builder + .patch_word_with_cast("loader_payload_size", serialized_payload.len()) + .unwrap(); + builder + .patch_word_with_cast("loader_image_start", builder.footprint().unwrap().start) + .unwrap(); + builder + .patch_word_with_cast("loader_image_end", builder.footprint().unwrap().end) + .unwrap(); + + builder.build().unwrap() } diff --git a/crates/sel4-reset/cli/Cargo.nix b/crates/sel4-reset/cli/Cargo.nix index c3665b09d..1bf6dedf0 100644 --- a/crates/sel4-reset/cli/Cargo.nix +++ b/crates/sel4-reset/cli/Cargo.nix @@ -15,9 +15,8 @@ mk { num clap ; - object = { version = versions.object; features = [ "all" ]; }; inherit (localCrates) - sel4-render-elf-with-data + sel4-synthetic-elf ; }; } diff --git a/crates/sel4-reset/cli/Cargo.toml b/crates/sel4-reset/cli/Cargo.toml index 040aafa06..91a9bfcbb 100644 --- a/crates/sel4-reset/cli/Cargo.toml +++ b/crates/sel4-reset/cli/Cargo.toml @@ -21,5 +21,4 @@ anyhow = "1.0.66" clap = "4.4.6" fallible-iterator = "0.2.0" num = "0.4.1" -object = { version = "0.36.1", features = ["all"] } -sel4-render-elf-with-data = { path = "../../sel4-render-elf-with-data" } +sel4-synthetic-elf = { path = "../../sel4-synthetic-elf" } diff --git a/crates/sel4-reset/cli/src/main.rs b/crates/sel4-reset/cli/src/main.rs index f3c4c08ca..ac0afd2b0 100644 --- a/crates/sel4-reset/cli/src/main.rs +++ b/crates/sel4-reset/cli/src/main.rs @@ -4,16 +4,16 @@ // SPDX-License-Identifier: BSD-2-Clause // +use std::borrow::Cow; use std::fs; -use std::mem; use anyhow::Result; -use num::{NumCast, Zero}; -use object::elf::{PF_R, PF_W, PT_LOAD}; -use object::read::elf::{ElfFile, ProgramHeader}; +use num::NumCast; +use object::elf::{PF_W, PT_LOAD}; +use object::read::elf::{ElfFile, FileHeader, ProgramHeader}; use object::{Endian, File, Object, ObjectSection, ReadCache, ReadRef}; -use sel4_render_elf_with_data::{FileHeaderExt, Input, SymbolicInjection, SymbolicValue}; +use sel4_synthetic_elf::{object, Builder, PatchValue, Segment}; mod args; @@ -39,46 +39,76 @@ fn main() -> Result<()> { } } -fn continue_with_type<'a, T, R>(args: &Args, elf: &ElfFile<'a, T, R>) -> Result<()> +fn continue_with_type<'a, T, R>(args: &Args, elf: &'a ElfFile<'a, T, R>) -> Result<()> where R: ReadRef<'a>, - T: FileHeaderExt, + T: FileHeader, { let endian = elf.endian(); let persistent_section = elf.section_by_name(".persistent"); + let mut builder = Builder::empty(&elf); + let mut regions_builder = RegionsBuilder::::new(); let mut persistent_section_placed = false; - for phdr in elf.elf_program_headers().iter() { - if phdr.p_type(endian) == PT_LOAD && phdr.p_flags(endian) & PF_W != 0 { - let vaddr = ::from(phdr.p_vaddr(endian)).unwrap(); - let memsz = ::from(phdr.p_memsz(endian)).unwrap(); - let data = phdr.data(endian, elf.data()).unwrap(); - let skip = persistent_section - .as_ref() - .and_then(|section| { - if section.address() == vaddr { - persistent_section_placed = true; - Some(section.size()) - } else { - None - } - }) - .unwrap_or(0); - regions_builder.add_region_with_skip(skip, vaddr, memsz, data); + for phdr in elf.elf_program_headers() { + if phdr.p_type(endian) == PT_LOAD { + let mut segment = Segment::from_phdr(phdr, endian, elf.data())?; + if phdr.p_flags(endian) & PF_W != 0 { + let vaddr = phdr.p_vaddr(endian).into(); + let memsz = phdr.p_memsz(endian).into(); + let data = phdr.data(endian, elf.data()).unwrap(); + let skip = persistent_section + .as_ref() + .and_then(|section| { + if section.address() == vaddr { + persistent_section_placed = true; + Some(section.size()) + } else { + None + } + }) + .unwrap_or(0); + regions_builder.add_region_with_skip(skip, vaddr, memsz, data); + segment.data = match &segment.data { + Cow::Borrowed(slice) => slice[..usize::try_from(skip).unwrap()].into(), + _ => panic!(), + } + } + builder.add_segment(segment); } } assert!(!(persistent_section.is_some() && !persistent_section_placed)); - let out_bytes = regions_builder - .build(endian) - .input::() - .render_with_data_already_parsed(elf) + let regions = regions_builder.build(endian); + + let vaddr = builder.next_vaddr().next_multiple_of(4096); + + builder.add_segment(Segment::simple(vaddr, regions.raw.into())); + + builder + .patch_word_with_cast("sel4_reset_regions_start", vaddr) + .unwrap(); + builder + .patch_word_with_cast("sel4_reset_regions_meta_offset", regions.meta_offset) + .unwrap(); + builder + .patch_word_with_cast("sel4_reset_regions_meta_count", regions.meta_count) + .unwrap(); + builder + .patch_word_with_cast("sel4_reset_regions_data_offset", regions.data_offset) .unwrap(); + builder + .patch_word_with_cast("sel4_reset_regions_data_size", regions.data_size) + .unwrap(); + + builder.discard_p_align(true); + + let out_bytes = builder.build().unwrap(); let out_file_path = &args.out_file_path; @@ -86,12 +116,12 @@ where Ok(()) } -struct RegionsBuilder { +struct RegionsBuilder { meta: Vec>, data: Vec, } -impl RegionsBuilder { +impl> RegionsBuilder { fn new() -> Self { Self { meta: vec![], @@ -141,19 +171,19 @@ impl RegionsBuilder { } } -struct RegionMeta { +struct RegionMeta { vaddr: T::Word, offset: T::Word, filesz: T::Word, memsz: T::Word, } -impl RegionMeta { +impl> RegionMeta { fn pack(&self, endian: impl Endian, buf: &mut Vec) { - buf.extend_from_slice(&T::write_word_bytes(endian, self.vaddr)); - buf.extend_from_slice(&T::write_word_bytes(endian, self.offset)); - buf.extend_from_slice(&T::write_word_bytes(endian, self.filesz)); - buf.extend_from_slice(&T::write_word_bytes(endian, self.memsz)); + buf.extend_from_slice(&self.vaddr.to_bytes(endian)); + buf.extend_from_slice(&self.offset.to_bytes(endian)); + buf.extend_from_slice(&self.filesz.to_bytes(endian)); + buf.extend_from_slice(&self.memsz.to_bytes(endian)); } } @@ -164,42 +194,3 @@ struct Regions { data_offset: usize, data_size: usize, } - -impl Regions { - fn input(&self) -> Input { - let align_modulus = NumCast::from(4096).unwrap(); - let align_residue = T::Word::zero(); - let memsz = self.raw.len(); - let mut input = Input::::default(); - input.symbolic_injections.push(SymbolicInjection { - align_modulus, - align_residue, - content: &self.raw, - memsz: NumCast::from(memsz).unwrap(), - p_flags: PF_R, - patches: vec![( - "sel4_reset_regions_start".to_owned(), - SymbolicValue { - addend: T::Sword::zero(), - }, - )], - }); - input.concrete_patches.push(( - "sel4_reset_regions_meta_offset".to_owned(), - NumCast::from(self.meta_offset).unwrap(), - )); - input.concrete_patches.push(( - "sel4_reset_regions_meta_count".to_owned(), - NumCast::from(self.meta_count).unwrap(), - )); - input.concrete_patches.push(( - "sel4_reset_regions_data_offset".to_owned(), - NumCast::from(self.data_offset).unwrap(), - )); - input.concrete_patches.push(( - "sel4_reset_regions_data_size".to_owned(), - NumCast::from(self.data_size).unwrap(), - )); - input - } -} diff --git a/crates/sel4-synthetic-elf/Cargo.nix b/crates/sel4-synthetic-elf/Cargo.nix new file mode 100644 index 000000000..9906ea1be --- /dev/null +++ b/crates/sel4-synthetic-elf/Cargo.nix @@ -0,0 +1,15 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# + +{ mk, versions }: + +mk { + package.name = "sel4-synthetic-elf"; + dependencies = { + inherit (versions) thiserror num; + object = { version = versions.object; features = [ "all" ]; }; + }; +} diff --git a/crates/sel4-synthetic-elf/Cargo.toml b/crates/sel4-synthetic-elf/Cargo.toml new file mode 100644 index 000000000..7af344024 --- /dev/null +++ b/crates/sel4-synthetic-elf/Cargo.toml @@ -0,0 +1,22 @@ +# +# Copyright 2023, Colias Group, LLC +# +# SPDX-License-Identifier: BSD-2-Clause +# +# +# This file is generated from './Cargo.nix'. You can edit this file directly +# if you are not using this project's Cargo manifest management tools. +# See 'hacking/cargo-manifest-management/README.md' for more information. +# + +[package] +name = "sel4-synthetic-elf" +version = "0.1.0" +authors = ["Nick Spinale "] +edition = "2021" +license = "BSD-2-Clause" + +[dependencies] +num = "0.4.1" +object = { version = "0.36.1", features = ["all"] } +thiserror = "1.0" diff --git a/crates/sel4-synthetic-elf/src/lib.rs b/crates/sel4-synthetic-elf/src/lib.rs new file mode 100644 index 000000000..e7026cfea --- /dev/null +++ b/crates/sel4-synthetic-elf/src/lib.rs @@ -0,0 +1,118 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use std::any; +use std::error::Error; +use std::fmt; +use std::ops::Range; + +use num::{NumCast, ToPrimitive}; +use object::read::ReadRef; + +pub use object; +pub use object::elf::{PF_R, PF_W, PF_X}; + +mod patches; +mod segments; + +pub use patches::{PatchValue, Patches}; +pub use segments::{Segment, Segments}; + +pub struct Builder<'a, 'data, T: object::read::elf::FileHeader, R: ReadRef<'data>> { + base_elf_file: &'a object::read::elf::ElfFile<'data, T, R>, + segments: Segments<'data>, + patches: Patches, + discard_p_align: bool, +} + +impl<'a: 'data, 'data, T: object::read::elf::FileHeader, R: ReadRef<'data>> + Builder<'a, 'data, T, R> +{ + pub fn empty(base_elf_file: &'a object::read::elf::ElfFile<'data, T, R>) -> Self { + let segments = Segments::new(); + let patches = Patches::new(); + Self { + base_elf_file, + segments, + patches, + discard_p_align: false, + } + } + + pub fn new( + base_elf_file: &'a object::read::elf::ElfFile<'data, T, R>, + ) -> Result> { + let mut this = Self::empty(base_elf_file); + this.segments.add_segments_from_phdrs(&this.base_elf_file)?; + Ok(this) + } + + pub fn discard_p_align(&mut self, doit: bool) { + self.discard_p_align = doit; + } + + pub fn add_segment(&mut self, segment: Segment<'a>) { + self.segments.add_segment(segment) + } + + pub fn footprint(&self) -> Option> { + self.segments.footprint() + } + + pub fn next_vaddr(&self) -> u64 { + self.footprint().map(|footprint| footprint.end).unwrap_or(0) + } + + pub fn patch_bytes(&mut self, name: &str, value: Vec) -> Result> { + Ok(self + .patches + .add_bytes_via_symbol(&self.base_elf_file, name, value)?) + } + + pub fn patch(&mut self, name: &str, value: impl PatchValue) -> Result> { + Ok(self.patches.add_via_symbol( + &self.base_elf_file, + name, + value, + self.base_elf_file.endian(), + )?) + } + + pub fn patch_word(&mut self, name: &str, value: T::Word) -> Result> + where + T::Word: PatchValue, + { + self.patch(name, value) + } + + pub fn patch_word_with_cast( + &mut self, + name: &str, + value: impl ToPrimitive + fmt::Debug + Copy, + ) -> Result> + where + T::Word: PatchValue + NumCast, + { + self.patch( + name, + ::from(value).unwrap_or_else(|| { + panic!( + "value {:#x?} out of bounds for word type {}", + value, + any::type_name::() + ) + }), + ) + } + + pub fn build(&self) -> Result, Box> { + let mut buf = self + .segments + .build_using_ehdr(&self.base_elf_file, self.discard_p_align)?; + self.patches.apply(&mut buf).unwrap(); + Ok(buf) + } +} diff --git a/crates/sel4-synthetic-elf/src/patches.rs b/crates/sel4-synthetic-elf/src/patches.rs new file mode 100644 index 000000000..ca8a99ef1 --- /dev/null +++ b/crates/sel4-synthetic-elf/src/patches.rs @@ -0,0 +1,175 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use std::fmt; + +use object::read::elf::{ElfFile, FileHeader}; +use object::read::ReadRef; +use object::{Endian, File, Object, ObjectSegment, ObjectSymbol}; +use thiserror::Error; + +pub struct Patches { + patches: Vec<(u64, Vec)>, +} + +impl Patches { + pub fn new() -> Self { + Self { patches: vec![] } + } + + pub fn add_bytes(&mut self, vaddr: u64, value: Vec) { + self.patches.push((vaddr, value)) + } + + pub fn add(&mut self, vaddr: u64, value: impl PatchValue, endian: impl Endian) { + self.add_bytes(vaddr, value.to_bytes(endian)) + } + + pub fn add_bytes_via_symbol<'data, T: FileHeader, R: ReadRef<'data>>( + &mut self, + elf_file_for_symbols: &ElfFile<'data, T, R>, + name: &str, + value: Vec, + ) -> Result { + for symbol in elf_file_for_symbols.symbols() { + if symbol.name()? == name { + let vaddr = symbol.address(); + let size = symbol.size(); + if usize::try_from(size).unwrap() != value.len() { + return Err(PatchesAddFromSymbolError::SymbolSizeMismatch( + name.to_owned(), + )); + } + self.add_bytes(vaddr, value); + return Ok(vaddr); + } + } + Err(PatchesAddFromSymbolError::SymbolMissing(name.to_owned())) + } + + pub fn add_via_symbol<'data, T: FileHeader, R: ReadRef<'data>>( + &mut self, + elf_file_for_symbols: &ElfFile<'data, T, R>, + name: &str, + value: impl PatchValue, + endian: impl Endian, + ) -> Result { + self.add_bytes_via_symbol(elf_file_for_symbols, name, value.to_bytes(endian)) + } + + pub fn apply(&self, elf_file_data: &mut [u8]) -> Result<(), PatchesApplyError> { + let offsets_into_file = match File::parse(&*elf_file_data)? { + File::Elf32(elf_file) => self.offsets_into_file(&elf_file), + File::Elf64(elf_file) => self.offsets_into_file(&elf_file), + _ => { + panic!() + } + }?; + + for (offset_into_file, value) in offsets_into_file + .iter() + .zip(self.patches.iter().map(|(_vaddr, value)| value)) + { + elf_file_data[usize::try_from(*offset_into_file).unwrap()..][..value.len()] + .copy_from_slice(&value); + } + + Ok(()) + } + + fn offsets_into_file<'data, T: FileHeader, R: ReadRef<'data>>( + &self, + elf_file: &ElfFile<'data, T, R>, + ) -> Result, PatchesApplyError> { + self.patches + .iter() + .map(|(vaddr, value)| { + elf_file + .segments() + .find_map(|segment| { + let start = segment.address(); + let end = start + segment.size(); + if (start..end).contains(&vaddr) { + let offset_in_segment = vaddr - start; + let (file_start, file_size) = segment.file_range(); + if offset_in_segment + u64::try_from(value.len()).unwrap() <= file_size + { + return Some(file_start + offset_in_segment); + } + } + None + }) + .ok_or_else(|| { + PatchesApplyError::AddrRangeNotMappedWithData(*vaddr, value.len()) + }) + }) + .collect::, PatchesApplyError>>() + } +} + +pub trait PatchValue { + fn to_bytes(&self, endian: impl Endian) -> Vec; +} + +impl PatchValue for u32 { + fn to_bytes(&self, endian: impl Endian) -> Vec { + endian.write_u32_bytes(*self).to_vec() + } +} + +impl PatchValue for u64 { + fn to_bytes(&self, endian: impl Endian) -> Vec { + endian.write_u64_bytes(*self).to_vec() + } +} + +#[derive(Error, Debug)] +pub enum PatchesAddFromSymbolError { + ReadError(object::read::Error), + SymbolMissing(String), + SymbolSizeMismatch(String), +} + +impl From for PatchesAddFromSymbolError { + fn from(err: object::read::Error) -> Self { + Self::ReadError(err) + } +} + +impl fmt::Display for PatchesAddFromSymbolError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ReadError(err) => write!(f, "read error: {}", err), + Self::SymbolMissing(name) => write!(f, "symbol missing: {:?}", name), + Self::SymbolSizeMismatch(name) => write!(f, "symbol size mismatch: {:?}", name), + } + } +} + +#[derive(Error, Debug)] +pub enum PatchesApplyError { + ReadError(object::read::Error), + AddrRangeNotMappedWithData(u64, usize), +} + +impl From for PatchesApplyError { + fn from(err: object::read::Error) -> Self { + Self::ReadError(err) + } +} + +impl fmt::Display for PatchesApplyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ReadError(err) => write!(f, "read error: {}", err), + Self::AddrRangeNotMappedWithData(start, size) => write!( + f, + "address range not mapped with file data: {:?}({:?})", + start, size + ), + } + } +} diff --git a/crates/sel4-synthetic-elf/src/segments.rs b/crates/sel4-synthetic-elf/src/segments.rs new file mode 100644 index 000000000..8e46d1400 --- /dev/null +++ b/crates/sel4-synthetic-elf/src/segments.rs @@ -0,0 +1,203 @@ +// +// Copyright 2024, Colias Group, LLC +// +// SPDX-License-Identifier: BSD-2-Clause +// + +use std::borrow::Cow; +use std::fmt; +use std::ops::Range; + +use object::elf::{PF_R, PT_LOAD}; +use object::read::elf::{ElfFile, FileHeader, ProgramHeader}; +use object::read::ReadRef; +use object::{Endian, Endianness, Object}; +use thiserror::Error; + +pub struct Segments<'a> { + segments: Vec>, +} + +impl<'a> Segments<'a> { + pub fn new() -> Self { + Self { segments: vec![] } + } + + pub fn add_segment(&mut self, segment: Segment<'a>) { + self.segments.push(segment); + } + + pub fn add_segments_from_phdrs>( + &mut self, + elf_file: &ElfFile<'a, T, R>, + ) -> Result<(), SegmentsError> { + let endian = elf_file.endian(); + for phdr in elf_file.elf_program_headers() { + if phdr.p_type(endian) == PT_LOAD { + self.add_segment(Segment::from_phdr(phdr, endian, elf_file.data())?); + } + } + Ok(()) + } + + pub fn footprint(&self) -> Option> { + let start = self.segments.iter().map(|segment| segment.p_vaddr).min()?; + let end = self + .segments + .iter() + .map(|segment| segment.p_vaddr + segment.p_memsz) + .max()?; + Some(start..end) + } + + pub fn build( + &self, + endianness: Endianness, + is_64: bool, + ehdr: &object::write::elf::FileHeader, + discard_p_align: bool, + ) -> Result, SegmentsError> { + let mut writer_buf = vec![]; + let mut writer = object::write::elf::Writer::new(endianness, is_64, &mut writer_buf); + + writer.reserve_file_header(); + writer.reserve_program_headers(self.segments.len().try_into().unwrap()); + + let mut offsets = vec![]; + for segment in self.segments.iter() { + let min_offset: u64 = writer.reserved_len().try_into().unwrap(); + let residue = segment.p_vaddr % segment.p_align; + let mut offset = min_offset.next_multiple_of(segment.p_align) + residue; + if offset >= min_offset + segment.p_align { + offset -= segment.p_align; + } + writer.reserve_until(offset.try_into().unwrap()); + writer.reserve(segment.data.len(), 1); + offsets.push(offset) + } + + writer.write_file_header(ehdr)?; + writer.write_align_program_headers(); + + for (phdr, offset) in self.segments.iter().zip(offsets.iter()) { + writer.write_program_header(&object::write::elf::ProgramHeader { + p_type: PT_LOAD, + p_flags: phdr.p_flags, + p_offset: *offset, + p_vaddr: phdr.p_vaddr, + p_paddr: phdr.p_paddr, + p_filesz: phdr.data.len().try_into().unwrap(), + p_memsz: phdr.p_memsz, + p_align: if discard_p_align { 1 } else { phdr.p_align }, + }); + } + + for (phdr, offset) in self.segments.iter().zip(offsets.iter()) { + writer.pad_until((*offset).try_into().unwrap()); + writer.write(&phdr.data); + } + + Ok(writer_buf) + } + + pub fn build_using_ehdr<'data, T: FileHeader, R: ReadRef<'data>>( + &self, + elf_file: &ElfFile<'data, T, R>, + discard_p_align: bool, + ) -> Result, SegmentsError> { + let endian = elf_file.endian(); + + let endianness = if endian.is_little_endian() { + Endianness::Little + } else { + Endianness::Big + }; + + let ehdr = elf_file.elf_header(); + + let ehdr_for_write = object::write::elf::FileHeader { + os_abi: ehdr.e_ident().os_abi, + abi_version: ehdr.e_ident().abi_version, + e_type: ehdr.e_type(endian), + e_machine: ehdr.e_machine(endian), + e_entry: ehdr.e_entry(endian).into(), + e_flags: ehdr.e_flags(endian), + }; + + self.build( + endianness, + elf_file.is_64(), + &ehdr_for_write, + discard_p_align, + ) + } +} + +pub struct Segment<'a> { + pub p_flags: u32, + pub p_vaddr: u64, + pub p_paddr: u64, + pub p_memsz: u64, + pub p_align: u64, + pub data: Cow<'a, [u8]>, +} + +impl<'a> Segment<'a> { + pub fn from_phdr>( + phdr: &T, + endian: T::Endian, + data: R, + ) -> Result { + Ok(Self { + p_flags: phdr.p_flags(endian), + p_vaddr: phdr.p_vaddr(endian).into(), + p_paddr: phdr.p_paddr(endian).into(), + p_memsz: phdr.p_memsz(endian).into(), + p_align: phdr.p_align(endian).into(), + data: Cow::Borrowed( + phdr.data(endian, data) + .map_err(|_| SegmentsError::FileDataError)?, + ), + }) + } + + pub fn simple(vaddr: u64, data: Cow<'a, [u8]>) -> Self { + Self { + p_flags: PF_R, + p_vaddr: vaddr, + p_paddr: vaddr, + p_memsz: data.len().try_into().unwrap(), + p_align: 1, + data, + } + } +} + +#[derive(Error, Debug)] +pub enum SegmentsError { + ReadError(object::read::Error), + WriteError(object::write::Error), + FileDataError, +} + +impl From for SegmentsError { + fn from(err: object::read::Error) -> Self { + Self::ReadError(err) + } +} + +impl From for SegmentsError { + fn from(err: object::write::Error) -> Self { + Self::WriteError(err) + } +} + +impl fmt::Display for SegmentsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ReadError(err) => write!(f, "read error: {}", err), + Self::WriteError(err) => write!(f, "write error: {}", err), + Self::FileDataError => write!(f, "file data error"), + } + } +} diff --git a/hacking/cargo-manifest-management/manifest-scope.nix b/hacking/cargo-manifest-management/manifest-scope.nix index 17a6d9038..a4f8175ca 100644 --- a/hacking/cargo-manifest-management/manifest-scope.nix +++ b/hacking/cargo-manifest-management/manifest-scope.nix @@ -122,6 +122,7 @@ in rec { smoltcp = "0.10.0"; syn = "1.0.107"; synstructure = "0.12.6"; + thiserror = "1.0"; tock-registers = "0.8.1"; unwinding = "0.1.6"; virtio-drivers = "0.7.2"; From d50ad4e8c4d3c965a3a8487825825323a8e362bb Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 10 Jul 2024 05:13:17 +0000 Subject: [PATCH 19/20] crates/sel4-render-elf-with-data: Remove Signed-off-by: Nick Spinale --- Cargo.lock | 10 - Cargo.toml | 1 - crates/sel4-render-elf-with-data/Cargo.nix | 15 -- crates/sel4-render-elf-with-data/Cargo.toml | 23 -- crates/sel4-render-elf-with-data/src/lib.rs | 168 -------------- .../sel4-render-elf-with-data/src/render.rs | 214 ------------------ 6 files changed, 431 deletions(-) delete mode 100644 crates/sel4-render-elf-with-data/Cargo.nix delete mode 100644 crates/sel4-render-elf-with-data/Cargo.toml delete mode 100644 crates/sel4-render-elf-with-data/src/lib.rs delete mode 100644 crates/sel4-render-elf-with-data/src/render.rs diff --git a/Cargo.lock b/Cargo.lock index c7ac08f24..e8134d2f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2520,16 +2520,6 @@ dependencies = [ name = "sel4-platform-info-types" version = "0.1.0" -[[package]] -name = "sel4-render-elf-with-data" -version = "0.1.0" -dependencies = [ - "anyhow", - "fallible-iterator 0.2.0", - "num", - "object", -] - [[package]] name = "sel4-reset" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 97ddabb50..729ca3173 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -122,7 +122,6 @@ members = [ "crates/sel4-panicking/env", "crates/sel4-platform-info", "crates/sel4-platform-info/types", - "crates/sel4-render-elf-with-data", "crates/sel4-reset", "crates/sel4-reset/cli", "crates/sel4-root-task", diff --git a/crates/sel4-render-elf-with-data/Cargo.nix b/crates/sel4-render-elf-with-data/Cargo.nix deleted file mode 100644 index 2a64bec4b..000000000 --- a/crates/sel4-render-elf-with-data/Cargo.nix +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright 2023, Colias Group, LLC -# -# SPDX-License-Identifier: BSD-2-Clause -# - -{ mk, versions }: - -mk { - package.name = "sel4-render-elf-with-data"; - dependencies = { - object = { version = versions.object; features = [ "all" ]; }; - inherit (versions) anyhow fallible-iterator num; - }; -} diff --git a/crates/sel4-render-elf-with-data/Cargo.toml b/crates/sel4-render-elf-with-data/Cargo.toml deleted file mode 100644 index 45bc85914..000000000 --- a/crates/sel4-render-elf-with-data/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright 2023, Colias Group, LLC -# -# SPDX-License-Identifier: BSD-2-Clause -# -# -# This file is generated from './Cargo.nix'. You can edit this file directly -# if you are not using this project's Cargo manifest management tools. -# See 'hacking/cargo-manifest-management/README.md' for more information. -# - -[package] -name = "sel4-render-elf-with-data" -version = "0.1.0" -authors = ["Nick Spinale "] -edition = "2021" -license = "BSD-2-Clause" - -[dependencies] -anyhow = "1.0.66" -fallible-iterator = "0.2.0" -num = "0.4.1" -object = { version = "0.36.1", features = ["all"] } diff --git a/crates/sel4-render-elf-with-data/src/lib.rs b/crates/sel4-render-elf-with-data/src/lib.rs deleted file mode 100644 index 138e6baa2..000000000 --- a/crates/sel4-render-elf-with-data/src/lib.rs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright 2023, Colias Group, LLC -// -// SPDX-License-Identifier: BSD-2-Clause -// - -use anyhow::{bail, Result}; -use num::{NumCast, PrimInt}; -use object::{ - elf::{FileHeader32, FileHeader64}, - read::elf::FileHeader, - Endian, Endianness, File, -}; - -pub use object::elf::{PF_R, PF_W, PF_X}; - -mod render; - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ElfBitWidth { - Elf32, - Elf64, -} - -impl ElfBitWidth { - pub fn detect(file_content: &[u8]) -> Result { - Ok(match File::parse(file_content)? { - File::Elf32(_) => Self::Elf32, - File::Elf64(_) => Self::Elf64, - _ => bail!("not ELF"), - }) - } -} - -pub type ConcreteFileHeader32 = FileHeader32; -pub type ConcreteFileHeader64 = FileHeader64; - -pub trait FileHeaderExt: FileHeader { - fn checked_add_signed(x: Self::Word, y: Self::Sword) -> Option; - fn write_word_bytes(endian: impl Endian, n: Self::Word) -> Vec; -} - -impl FileHeaderExt for ConcreteFileHeader32 { - fn checked_add_signed(x: Self::Word, y: Self::Sword) -> Option { - x.checked_add_signed(y) - } - - fn write_word_bytes(endian: impl Endian, n: Self::Word) -> Vec { - endian.write_u32_bytes(n).to_vec() - } -} - -impl FileHeaderExt for ConcreteFileHeader64 { - fn checked_add_signed(x: Self::Word, y: Self::Sword) -> Option { - x.checked_add_signed(y) - } - - fn write_word_bytes(endian: impl Endian, n: Self::Word) -> Vec { - endian.write_u64_bytes(n).to_vec() - } -} - -// NOTE -// The phdrs in output of render_with_data have p_align=1 regardless of the input. -// That is because the current consumers of the output do not use p_align. - -pub struct Input<'a, T: FileHeaderExt> { - pub symbolic_injections: Vec>, - pub image_start_patches: Vec, - pub image_end_patches: Vec, - pub concrete_patches: Vec<(Symbol, ConcreteValue)>, -} - -impl<'a, T: FileHeaderExt> Default for Input<'a, T> { - fn default() -> Self { - Self { - symbolic_injections: Default::default(), - image_start_patches: Default::default(), - image_end_patches: Default::default(), - concrete_patches: Default::default(), - } - } -} - -type Symbol = String; - -type ConcreteValue = ::Word; - -pub struct SymbolicInjection<'a, T: FileHeaderExt> { - pub align_modulus: T::Word, - pub align_residue: T::Word, - pub content: &'a [u8], - pub memsz: T::Word, - pub p_flags: u32, - pub patches: Vec<(Symbol, SymbolicValue)>, -} - -#[derive(Debug)] -pub struct SymbolicValue { - pub addend: T::Sword, -} - -impl<'a, T: FileHeaderExt> SymbolicInjection<'a, T> { - fn filesz(&self) -> T::Word { - NumCast::from(self.content.len()).unwrap() - } - - fn align_from(&self, addr: T::Word) -> T::Word { - align_from::(addr, self.align_modulus, self.align_residue) - } - - fn locate(&self, vaddr: T::Word) -> Result> { - Ok(Injection { - vaddr, - content: self.content, - memsz: self.memsz, - p_flags: self.p_flags, - patches: self - .patches - .iter() - .map(|(name, symbolic_value)| { - ( - name.clone(), - T::checked_add_signed(vaddr, symbolic_value.addend).unwrap(), - ) - }) - .collect::)>>(), - }) - } -} - -pub struct Injection<'a, T: FileHeaderExt> { - pub vaddr: T::Word, - pub content: &'a [u8], - pub memsz: T::Word, - pub p_flags: u32, - pub patches: Vec<(Symbol, ConcreteValue)>, -} - -impl<'a, T: FileHeaderExt> Injection<'a, T> { - fn vaddr(&self) -> T::Word { - self.vaddr - } - - fn filesz(&self) -> T::Word { - NumCast::from(self.content.len()).unwrap() - } - - fn memsz(&self) -> T::Word { - self.memsz - } - - fn content(&self) -> &'a [u8] { - self.content - } - - fn p_flags(&self) -> u32 { - self.p_flags - } - - fn patches(&self) -> impl Iterator)> { - self.patches.iter() - } -} - -fn align_from(addr: T::Word, modulus: T::Word, residue: T::Word) -> T::Word { - addr + (modulus + residue - addr % modulus) % modulus -} diff --git a/crates/sel4-render-elf-with-data/src/render.rs b/crates/sel4-render-elf-with-data/src/render.rs deleted file mode 100644 index e6856073c..000000000 --- a/crates/sel4-render-elf-with-data/src/render.rs +++ /dev/null @@ -1,214 +0,0 @@ -// -// Copyright 2023, Colias Group, LLC -// -// SPDX-License-Identifier: BSD-2-Clause -// - -use std::mem; - -use anyhow::{anyhow, ensure, Result}; -use num::{CheckedAdd, NumCast, ToPrimitive}; -use object::{ - elf::PT_LOAD, - read::elf::{ElfFile, FileHeader, ProgramHeader as _}, - read::ReadRef, - write::elf::{ProgramHeader, Writer}, - Object, ObjectSegment, ObjectSymbol, -}; - -use crate::{FileHeaderExt, Injection, Input}; - -impl<'a, T: FileHeaderExt> Input<'a, T> { - pub fn render_with_data(&self, orig: &[u8]) -> Result> { - self.render_with_data_already_parsed(&ElfFile::parse(orig)?) - } - - pub fn render_with_data_already_parsed<'b, R: ReadRef<'b>>( - &self, - orig_obj: &ElfFile<'b, T, R>, - ) -> Result> { - let orig_endian = orig_obj.endian(); - let orig_image_end = next_vaddr(orig_obj)?; - - let mut out_buf = vec![]; - let mut writer = Writer::new(orig_endian, orig_obj.is_64(), &mut out_buf); - - writer.reserve_file_header(); - writer.reserve_program_headers( - (loadable_segments(orig_obj).count() + self.symbolic_injections.len()).try_into()?, - ); - - let revised_offsets = loadable_segments(orig_obj) - .map(|phdr| { - let filesz = phdr.p_filesz(orig_endian).to_usize().unwrap(); - let offset = writer.reserve(filesz, 1); - Ok(offset) - }) - .collect::>>()?; - - let new_segments = { - let mut next_vaddr = orig_image_end; - self.symbolic_injections - .iter() - .map(|symbolic_injection| { - let filesz = symbolic_injection.filesz(); - let memsz = symbolic_injection.memsz; - let offset = writer.reserve(filesz.to_usize().unwrap(), 1); - let vaddr = symbolic_injection.align_from(next_vaddr); - next_vaddr = vaddr.checked_add(&memsz).unwrap(); - Ok((symbolic_injection.locate(vaddr)?, offset)) - }) - .collect::, usize)>>>()? - }; - - writer.write_file_header({ - let hdr = orig_obj.elf_header(); - &object::write::elf::FileHeader { - os_abi: hdr.e_ident().os_abi, - abi_version: hdr.e_ident().abi_version, - e_type: hdr.e_type(orig_endian), - e_machine: hdr.e_machine(orig_endian), - e_entry: hdr.e_entry(orig_endian).into(), - e_flags: hdr.e_flags(orig_endian), - } - })?; - - writer.write_align_program_headers(); - - for (phdr, revised_offset) in loadable_segments(orig_obj).zip(&revised_offsets) { - writer.write_program_header(&ProgramHeader { - p_type: phdr.p_type(orig_endian), - p_flags: phdr.p_flags(orig_endian), - p_offset: (*revised_offset).try_into()?, - p_vaddr: phdr.p_vaddr(orig_endian).into(), - p_paddr: phdr.p_paddr(orig_endian).into(), - p_filesz: phdr.p_filesz(orig_endian).into(), - p_memsz: phdr.p_memsz(orig_endian).into(), - p_align: 1, - }); - } - - for (injection, offset) in &new_segments { - let vaddr = injection.vaddr(); - writer.write_program_header(&ProgramHeader { - p_type: PT_LOAD, - p_flags: injection.p_flags(), - p_offset: (*offset).try_into()?, - p_vaddr: vaddr.into(), - p_paddr: vaddr.into(), - p_filesz: injection.filesz().into(), - p_memsz: injection.memsz().into(), - p_align: 1, - }); - } - - for (phdr, revised_offset) in loadable_segments(orig_obj).zip(&revised_offsets) { - writer.pad_until(*revised_offset); - writer.write(phdr.data(orig_endian, orig_obj.data()).ok().unwrap()); - } - - for (injection, offset) in &new_segments { - writer.pad_until(*offset); - writer.write(injection.content()); - } - - let mut recorded: Vec<(String, T::Word)> = vec![]; - { - let image_start = first_vaddr(orig_obj)?; - let image_end = new_segments - .iter() - .map(|(injection, _offset)| injection.vaddr() + injection.memsz()) - .max() - .unwrap_or(orig_image_end); - for name in &self.image_start_patches { - recorded.push((name.clone(), image_start)) - } - for name in &self.image_end_patches { - recorded.push((name.clone(), image_end)) - } - } - for (injection, _offset) in &new_segments { - for (name, value) in injection.patches() { - recorded.push((name.clone(), *value)) - } - } - for (name, value) in &self.concrete_patches { - recorded.push((name.clone(), *value)) - } - - let out_obj: &ElfFile = &ElfFile::parse(out_buf.as_slice())?; - let mut patches = vec![]; - for (name, value) in &recorded { - let patch_offset = - vaddr_to_offset(out_obj, get_symbol_vaddr(orig_obj, name)?)?.try_into()?; - let value_bytes = T::write_word_bytes(out_obj.endian(), *value); - patches.push((patch_offset, value_bytes)) - } - for (patch_offset, value_bytes) in patches { - out_buf[patch_offset..patch_offset + value_bytes.len()].copy_from_slice(&value_bytes); - } - - Ok(out_buf) - } -} - -fn loadable_segments<'a, 'b, T: FileHeaderExt, R: ReadRef<'b>>( - obj: &'a ElfFile<'b, T, R>, -) -> impl Iterator::ProgramHeader> + 'a { - obj.elf_program_headers() - .iter() - .filter(|phdr| phdr.p_type(obj.endian()) == PT_LOAD) -} - -fn get_symbol_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>( - obj: &ElfFile<'a, T, R>, - name: &str, -) -> Result { - for symbol in obj.symbols() { - if symbol.name()? == name { - ensure!(usize::try_from(symbol.size()).unwrap() == mem::size_of::()); - return Ok(NumCast::from(symbol.address()).unwrap()); - } - } - Err(anyhow!("symbol '{}' not present", name)) -} - -fn vaddr_to_offset<'a, T: FileHeaderExt, R: ReadRef<'a>>( - obj: &ElfFile<'a, T, R>, - vaddr: T::Word, -) -> Result -where -{ - for segment in obj.segments() { - let start = segment.address(); - let end = start + segment.size(); - if (start..end).contains(&vaddr.into()) { - let offset_in_segment = vaddr.into() - start; - let (file_start, file_size) = segment.file_range(); - ensure!(offset_in_segment < file_size); - return Ok(file_start + offset_in_segment); - } - } - Err(anyhow!( - "vaddr '0x{:x}' not mapped", - >::into(vaddr) - )) -} - -fn first_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>(obj: &ElfFile<'a, T, R>) -> Result -where -{ - loadable_segments(obj) - .map(|phdr| phdr.p_vaddr(obj.endian())) - .min() - .ok_or(anyhow!("no segments")) -} - -fn next_vaddr<'a, T: FileHeaderExt, R: ReadRef<'a>>(obj: &ElfFile<'a, T, R>) -> Result -where -{ - loadable_segments(obj) - .map(|phdr| phdr.p_vaddr(obj.endian()) + phdr.p_memsz(obj.endian())) - .max() - .ok_or(anyhow!("no segments")) -} From ed24c1d69ab308168b326029139a8acbc9921d64 Mon Sep 17 00:00:00 2001 From: Nick Spinale Date: Wed, 10 Jul 2024 09:04:56 +0000 Subject: [PATCH 20/20] nix: Test CapDL loader with added spec Signed-off-by: Nick Spinale --- hacking/nix/scope/world/instances/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hacking/nix/scope/world/instances/default.nix b/hacking/nix/scope/world/instances/default.nix index 5baae710e..0cb74f060 100644 --- a/hacking/nix/scope/world/instances/default.nix +++ b/hacking/nix/scope/world/instances/default.nix @@ -298,7 +298,7 @@ in rec { release = true; # test optimizations }; rootTask = mkCapDLInitializer { - small = true; + small = false; spec = mkSimpleCompositionCapDLSpec { script = sources.srcRoot + "/crates/private/tests/capdl/threads/cdl.py"; config = {