From 2f2954bf73db619917229a04e8354f2b281a0cb0 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 29 Jun 2026 15:28:39 +1000 Subject: [PATCH 1/5] tool/elf: decouple program headers from segments Previously, the ELF code treats program headers = segments. While this worked originally, it broke for cases that requires >= 2 program headers to refer to the same segment. Now, when the ELF is parsed, the code will create a 1-1 mapping of segments to program headers like before. But the allow for additional program headers to be inserted. Signed-off-by: Bill Nguyen --- tool/microkit/src/elf.rs | 59 ++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index 4ef82d9e0..fb48e517d 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -197,6 +197,12 @@ impl ElfSegment { } } +#[derive(Eq, PartialEq, Clone)] +pub struct ProgramHeader { + pub segment_idx: usize, + pub type_: u32, +} + #[derive(Eq, PartialEq, Clone)] pub struct ElfFile { pub path: PathBuf, @@ -204,6 +210,7 @@ pub struct ElfFile { pub entry: u64, pub machine: u16, pub segments: Vec, + pub program_headers: Vec, symbols: HashMap, } @@ -214,7 +221,8 @@ impl ElfFile { word_size, entry, machine, - segments: [].into(), + segments: vec![], + program_headers: vec![], symbols: HashMap::new(), } } @@ -233,12 +241,24 @@ impl ElfFile { Some(path_for_symbols) => ElfFileReader::from_path(path_for_symbols)?.symbols()?, None => reader.symbols()?, }; + // Initially create a one to one mapping of segments -> program headers. + // So that we can create two program headers of different types that point to the same segment. + let program_headers = segments + .iter() + .enumerate() + .map(|(i, _)| ProgramHeader { + segment_idx: i, + type_: PHENT_TYPE_LOADABLE, + }) + .collect(); + Ok(ElfFile { path: path.to_owned(), word_size: reader.word_size, entry: reader.hdr.entry, machine: reader.hdr.machine, segments, + program_headers, symbols, }) } @@ -522,6 +542,11 @@ impl ElfFile { attrs: r | w | x, }; self.segments.push(elf_segment); + + self.program_headers.push(ProgramHeader { + segment_idx: self.segments.len() - 1, + type_: PHENT_TYPE_LOADABLE, + }); } pub fn loadable_segments(&self) -> Vec<&ElfSegment> { @@ -532,7 +557,7 @@ impl ElfFile { pub fn reserialise(&self, out: &std::path::Path) -> Result { let ehsize = size_of::(); - let phnum = self.loadable_segments().len(); + let phnum = self.program_headers.len(); let phentsize = size_of::(); // First entry is reserved, last entry is dummy strtab @@ -587,21 +612,27 @@ impl ElfFile { let mut data_off_watermark = (ehsize as u64) + (phnum as u64) * (phentsize as u64) + (shnum as u64) * (shentsize as u64); - let mut data_offs = [].to_vec(); - // First write out the program headers table + // First thing to do is work out where to place all the data segments + let mut seg_idx_to_data_off: HashMap = Default::default(); for (i, seg) in self.loadable_segments().iter().enumerate() { + seg_idx_to_data_off.insert(i, data_off_watermark); + data_off_watermark += seg.file_size(); + } + + // Then write out the program headers table + for (i, program_header) in self.program_headers.iter().enumerate() { + let linked_segment = &self.segments[program_header.segment_idx]; let ph_serialised = ElfProgramHeader64 { - type_: PHENT_TYPE_LOADABLE, // loadable - flags: seg.attrs, - offset: data_off_watermark, - vaddr: seg.virt_addr, - paddr: seg.phys_addr, - filesz: seg.file_size(), - memsz: seg.mem_size(), + type_: program_header.type_, + flags: linked_segment.attrs, + offset: seg_idx_to_data_off[&program_header.segment_idx], + vaddr: linked_segment.virt_addr, + paddr: linked_segment.phys_addr, + filesz: linked_segment.file_size(), + memsz: linked_segment.mem_size(), align: 0, }; - data_offs.push(data_off_watermark); elf_file .write_all(unsafe { struct_to_bytes(&ph_serialised) }) @@ -612,8 +643,6 @@ impl ElfFile { out.display() ) }); - - data_off_watermark += seg.file_size(); } // Then the section headers table, which describe the same thing as the program headers. @@ -634,7 +663,7 @@ impl ElfFile { type_: SHT_PROGBITS, flags: seg.section_flags(), addr: seg.phys_addr, - offset: data_offs[i], + offset: seg_idx_to_data_off[&i], size: seg.file_size(), link: 0, info: 0, From 60260e946d28b3809cff65a19f69cb0eab090f7b Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 19 Jun 2026 13:43:33 +1000 Subject: [PATCH 2/5] tool/elf: refactored program headers table mgmt Added `pub fn phdrs_table(&self) -> Vec<(ElfProgramHeader64, usize)>` to ELF code. Signed-off-by: Bill Nguyen --- tool/microkit/src/elf.rs | 47 ++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index fb48e517d..e6e73a7d2 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -62,7 +62,7 @@ struct ElfSectionHeader64 { } #[repr(C, packed)] -struct ElfProgramHeader64 { +pub struct ElfProgramHeader64 { type_: u32, flags: u32, offset: u64, @@ -553,6 +553,29 @@ impl ElfFile { self.segments.iter().filter(|s| s.loadable).collect() } + /// Returns a vec of program headers in ELF format without the file data offset filled and its linked segment. + pub fn phdrs_table_serialised(&self) -> Vec<(ElfProgramHeader64, usize)> { + let mut table = vec![]; + for program_header in self.program_headers.iter() { + let linked_segment = &self.segments[program_header.segment_idx]; + + let phdr = ElfProgramHeader64 { + type_: program_header.type_, + flags: linked_segment.attrs, + offset: 0, + vaddr: linked_segment.virt_addr, + paddr: linked_segment.phys_addr, + filesz: linked_segment.file_size(), + memsz: linked_segment.mem_size(), + align: 0, + }; + + table.push((phdr, program_header.segment_idx)); + } + + table + } + /// Re-create a minimal ELF file with all the program and section headers. pub fn reserialise(&self, out: &std::path::Path) -> Result { let ehsize = size_of::(); @@ -621,25 +644,17 @@ impl ElfFile { } // Then write out the program headers table - for (i, program_header) in self.program_headers.iter().enumerate() { - let linked_segment = &self.segments[program_header.segment_idx]; - let ph_serialised = ElfProgramHeader64 { - type_: program_header.type_, - flags: linked_segment.attrs, - offset: seg_idx_to_data_off[&program_header.segment_idx], - vaddr: linked_segment.virt_addr, - paddr: linked_segment.phys_addr, - filesz: linked_segment.file_size(), - memsz: linked_segment.mem_size(), - align: 0, - }; + for (phdr, seg_idx) in self.phdrs_table_serialised().iter_mut() { + phdr.offset = seg_idx_to_data_off[seg_idx]; + let phdr_type = phdr.type_; elf_file - .write_all(unsafe { struct_to_bytes(&ph_serialised) }) + .write_all(unsafe { struct_to_bytes(phdr) }) .unwrap_or_else(|_| { panic!( - "Failed to write ELF program header #{} for '{}'", - i, + "Failed to write ELF program header type {:x} linked to segment index {} for '{}'", + phdr_type, + seg_idx, out.display() ) }); From 39c4af3e849b65fd58a6799febe43a755c2b6761 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Fri, 19 Jun 2026 13:46:57 +1000 Subject: [PATCH 3/5] tool/elf: + segment with multiple program headers Modified `pub fn add_segment()` to allow for an additional program header in the ELF to describe the segment with a user defined type identifier. Signed-off-by: Bill Nguyen --- tool/microkit/src/capdl/initialiser.rs | 2 ++ tool/microkit/src/elf.rs | 13 ++++++++++++- tool/microkit/src/loader.rs | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tool/microkit/src/capdl/initialiser.rs b/tool/microkit/src/capdl/initialiser.rs index 250203b55..78c3284a2 100644 --- a/tool/microkit/src/capdl/initialiser.rs +++ b/tool/microkit/src/capdl/initialiser.rs @@ -67,6 +67,7 @@ impl CapDLInitialiser { false, spec_vaddr, ElfSegmentData::RealData(spec_payload.into()), + None, ); let embedded_frame_data_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); @@ -76,6 +77,7 @@ impl CapDLInitialiser { false, embedded_frame_data_vaddr, ElfSegmentData::RealData(embedded_frame_data), + None, ); // These symbol names must match rust-sel4/crates/sel4-capdl-initializer/src/main.rs diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index e6e73a7d2..c3e23d192 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -522,6 +522,9 @@ impl ElfFile { round_down(self.highest_vaddr() + page_size as u64, page_size as u64) } + /// Add a segment, its data and a corresponding program header with loadable type to the ELF. + /// The caller can pass a Some value to `meta_phdr_type_maybe` to create an additional + /// program header with a specific type identifier. pub fn add_segment( &mut self, read: bool, @@ -529,6 +532,7 @@ impl ElfFile { execute: bool, vaddr: u64, data: ElfSegmentData, + meta_phdr_type_maybe: Option, ) { let r = if read { PF_R } else { 0 }; let w = if write { PF_W } else { 0 }; @@ -547,6 +551,13 @@ impl ElfFile { segment_idx: self.segments.len() - 1, type_: PHENT_TYPE_LOADABLE, }); + + if let Some(meta_phdr_type) = meta_phdr_type_maybe { + self.program_headers.push(ProgramHeader { + segment_idx: self.segments.len() - 1, + type_: meta_phdr_type, + }); + } } pub fn loadable_segments(&self) -> Vec<&ElfSegment> { @@ -660,7 +671,7 @@ impl ElfFile { }); } - // Then the section headers table, which describe the same thing as the program headers. + // Next step is the section headers table, which describe mostly the same thing as the program headers. // This is needed for U-Boot's `bootelf` command to work properly without adding the `-p` flag // when booting the loader image on ARM and RISC-V platforms. // First entry is reserved! diff --git a/tool/microkit/src/loader.rs b/tool/microkit/src/loader.rs index 5e4ec89b9..53a2597e2 100644 --- a/tool/microkit/src/loader.rs +++ b/tool/microkit/src/loader.rs @@ -572,6 +572,7 @@ impl<'a> Loader<'a> { true, self.entry, ElfSegmentData::RealData(self.to_bytes()), + None, ); loader_elf From 67e4362b97735b7faf9e60cd7cda541be52f5c09 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 29 Jun 2026 15:24:31 +1000 Subject: [PATCH 4/5] Switch rust-sel4 to mainline commit Which also required changes to how the spec is packed into the intialiser. Signed-off-by: Bill Nguyen --- Cargo.lock | 93 +++++++++++++++++--------- Cargo.toml | 8 +-- tool/microkit/src/capdl/allocation.rs | 10 ++- tool/microkit/src/capdl/initialiser.rs | 93 ++++++++++++++++++-------- tool/microkit/src/elf.rs | 25 +++---- 5 files changed, 152 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a0442d20..89b1b0de7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,7 +494,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sel4" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "cfg-if", "sel4-config", @@ -504,7 +504,7 @@ dependencies = [ [[package]] name = "sel4-alloca" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "cfg-if", ] @@ -512,7 +512,7 @@ dependencies = [ [[package]] name = "sel4-bitfield-ops" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "rustversion", ] @@ -520,12 +520,12 @@ dependencies = [ [[package]] name = "sel4-build-env" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-capdl-initializer" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "log", "rkyv", @@ -534,13 +534,16 @@ dependencies = [ "sel4-immediate-sync-once-cell", "sel4-immutable-cell", "sel4-logging", + "sel4-no-allocator", + "sel4-phdrs", + "sel4-phdrs-patched", "sel4-root-task", ] [[package]] name = "sel4-capdl-initializer-types" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "miniz_oxide", "rkyv", @@ -552,7 +555,7 @@ dependencies = [ [[package]] name = "sel4-capdl-initializer-types-derive" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "proc-macro2", "quote", @@ -562,7 +565,7 @@ dependencies = [ [[package]] name = "sel4-config" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "prettyplease", "proc-macro2", @@ -576,7 +579,7 @@ dependencies = [ [[package]] name = "sel4-config-data" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "sel4-build-env", "sel4-config-types", @@ -586,7 +589,7 @@ dependencies = [ [[package]] name = "sel4-config-macros" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "fallible-iterator", "proc-macro2", @@ -599,7 +602,7 @@ dependencies = [ [[package]] name = "sel4-config-types" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "serde", ] @@ -607,36 +610,31 @@ dependencies = [ [[package]] name = "sel4-ctors-dtors" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-dlmalloc" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "dlmalloc", "lock_api", ] -[[package]] -name = "sel4-elf-header" -version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" - [[package]] name = "sel4-immediate-sync-once-cell" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-immutable-cell" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-initialize-tls" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "cfg-if", "sel4-alloca", @@ -645,16 +643,21 @@ dependencies = [ [[package]] name = "sel4-logging" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "lock_api", "log", ] +[[package]] +name = "sel4-no-allocator" +version = "0.1.0" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" + [[package]] name = "sel4-panicking" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "cfg-if", "sel4-immediate-sync-once-cell", @@ -665,12 +668,39 @@ dependencies = [ [[package]] name = "sel4-panicking-env" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" + +[[package]] +name = "sel4-phdrs" +version = "0.1.0" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" +dependencies = [ + "sel4-phdrs-constants", +] + +[[package]] +name = "sel4-phdrs-constants" +version = "0.1.0" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" + +[[package]] +name = "sel4-phdrs-patched" +version = "0.1.0" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" +dependencies = [ + "sel4-phdrs", + "sel4-rodata-static", +] + +[[package]] +name = "sel4-rodata-static" +version = "0.1.0" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-root-task" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "sel4", "sel4-dlmalloc", @@ -685,7 +715,7 @@ dependencies = [ [[package]] name = "sel4-root-task-macros" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "proc-macro2", "quote", @@ -695,14 +725,15 @@ dependencies = [ [[package]] name = "sel4-runtime-common" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "cfg-if", "sel4", "sel4-ctors-dtors", - "sel4-elf-header", + "sel4-immutable-cell", "sel4-initialize-tls", "sel4-panicking-env", + "sel4-phdrs", "sel4-stack", "unwinding", ] @@ -710,12 +741,12 @@ dependencies = [ [[package]] name = "sel4-stack" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" [[package]] name = "sel4-sync" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "lock_api", "sel4", @@ -725,7 +756,7 @@ dependencies = [ [[package]] name = "sel4-sys" version = "0.1.0" -source = "git+https://github.com/au-ts/rust-sel4?rev=33cb132571121a8d846ad3be9066617087ee5c32#33cb132571121a8d846ad3be9066617087ee5c32" +source = "git+https://github.com/seL4/rust-sel4?rev=413940c8058da32098c464f6cd09e550b230505c#413940c8058da32098c464f6cd09e550b230505c" dependencies = [ "bindgen", "glob", diff --git a/Cargo.toml b/Cargo.toml index e3c561ebb..1c02e1bd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,12 @@ members = [ ] [workspace.dependencies.sel4-capdl-initializer] -git = "https://github.com/au-ts/rust-sel4" -rev = "33cb132571121a8d846ad3be9066617087ee5c32" +git = "https://github.com/seL4/rust-sel4" +rev = "413940c8058da32098c464f6cd09e550b230505c" [workspace.dependencies.sel4-capdl-initializer-types] -git = "https://github.com/au-ts/rust-sel4" -rev = "33cb132571121a8d846ad3be9066617087ee5c32" +git = "https://github.com/seL4/rust-sel4" +rev = "413940c8058da32098c464f6cd09e550b230505c" [profile.release.package.microkit-tool] strip = true diff --git a/tool/microkit/src/capdl/allocation.rs b/tool/microkit/src/capdl/allocation.rs index 31fe79456..7d0dcaa67 100644 --- a/tool/microkit/src/capdl/allocation.rs +++ b/tool/microkit/src/capdl/allocation.rs @@ -145,9 +145,13 @@ pub fn simulate_capdl_object_alloc_algorithm( let target_is_obj_with_paddr = target < ut.end(); while cur_paddr < target { - let max_size_bits = usize::try_from(cur_paddr.trailing_zeros()) - .unwrap() - .min((target - cur_paddr).trailing_zeros().try_into().unwrap()); + let max_size_bits = { + let alignment_bits = (cur_paddr - ut.base()) + .checked_ilog2() + .unwrap_or(kernel_config.word_size.try_into().unwrap()); + let distance_bits = (target - cur_paddr).checked_ilog2().expect("never 0"); + alignment_bits.min(distance_bits).try_into().unwrap() + }; let mut created = false; // If this UT is in main memory, allocate all the objects that does not specify a paddr first. diff --git a/tool/microkit/src/capdl/initialiser.rs b/tool/microkit/src/capdl/initialiser.rs index 78c3284a2..45cca4930 100644 --- a/tool/microkit/src/capdl/initialiser.rs +++ b/tool/microkit/src/capdl/initialiser.rs @@ -8,14 +8,19 @@ use std::ops::Range; use rkyv::util::AlignedVec; -use crate::elf::ElfSegmentData; -use crate::util::round_up; +use crate::elf::{ElfProgramHeader64, ElfSegmentData, PF_R, PHENT_TYPE_LOADABLE, PHENT_TYPE_PHDR}; +use crate::util::{round_up, struct_to_bytes}; use crate::{elf::ElfFile, sel4::PageSize}; use crate::{serialise_ut, UntypedObject}; // Page size used for allocating the spec and embedded frames segments. pub const INITIALISER_GRANULE_SIZE: PageSize = PageSize::Small; +// Magic numbers for the initialiser to identify the data type. +// See rust-sel4 crates/sel4-phdrs/constants/src/lib.rs +const PT_SEL4_CAPDL_SPEC: u32 = 0x64c3_4003; +const PT_SEL4_CAPDL_FRAME_DATA: u32 = 0x64c3_4004; + pub struct CapDLInitialiserSpecMetadata { pub spec_size: u64, } @@ -59,6 +64,7 @@ impl CapDLInitialiser { self.spec_metadata = None; } + // Follow implementation in rust-sel4: crates/sel4-capdl-initializer/add-spec/src/lib.rs let spec_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); let spec_size = spec_payload.len() as u64; self.elf.add_segment( @@ -67,7 +73,7 @@ impl CapDLInitialiser { false, spec_vaddr, ElfSegmentData::RealData(spec_payload.into()), - None, + Some(PT_SEL4_CAPDL_SPEC), ); let embedded_frame_data_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); @@ -77,40 +83,73 @@ impl CapDLInitialiser { false, embedded_frame_data_vaddr, ElfSegmentData::RealData(embedded_frame_data), - None, + Some(PT_SEL4_CAPDL_FRAME_DATA), ); - // These symbol names must match rust-sel4/crates/sel4-capdl-initializer/src/main.rs - self.elf - .write_symbol( - "sel4_capdl_initializer_embedded_frames_data_start", - &embedded_frame_data_vaddr.to_le_bytes(), - ) - .unwrap(); + // Now make the program headers table and inject it into the ELF as the initialiser look at + // it to figure out its virtual address bound, spec location in memory etc. + // It would have been nicer if we can perform this step in ElfFile::reserialise() but + // that function is only relevant for x86. + let phdrs_table_vaddr = self.elf.next_vaddr(INITIALISER_GRANULE_SIZE); + let phdrs_table = self.elf.phdrs_table_serialised(); + // Accounts for a PHENT_TYPE_PHDR meta phdr + PHENT_TYPE_LOADABLE phdr when we eventually inject + // the table as a segment. + let expected_phnum = phdrs_table.len() + 2; + let expected_phdrs_table_size_bytes = size_of::() * expected_phnum; + + let mut phdrs_table_bytes = vec![]; + phdrs_table.iter().for_each(|phdr| { + phdrs_table_bytes.extend(unsafe { struct_to_bytes(&phdr.0) }); + }); + + // Simulate what happens in ElfFile::add_segment() to derive the final program headers table. + // We do this due to a chicken and egg problem, the real program headers table won't be finalised + // until we add it as a segment. But we can't add it as a segment until we finalise it. + phdrs_table_bytes.extend(unsafe { + struct_to_bytes(&ElfProgramHeader64 { + type_: PHENT_TYPE_PHDR, + flags: PF_R, + offset: 0, + vaddr: phdrs_table_vaddr, + paddr: phdrs_table_vaddr, + filesz: expected_phdrs_table_size_bytes as u64, + memsz: expected_phdrs_table_size_bytes as u64, + align: 0, + }) + }); + phdrs_table_bytes.extend(unsafe { + struct_to_bytes(&ElfProgramHeader64 { + type_: PHENT_TYPE_LOADABLE, + flags: PF_R, + offset: 0, + vaddr: phdrs_table_vaddr, + paddr: phdrs_table_vaddr, + filesz: expected_phdrs_table_size_bytes as u64, + memsz: expected_phdrs_table_size_bytes as u64, + align: 0, + }) + }); - self.elf - .write_symbol( - "sel4_capdl_initializer_serialized_spec_data_start", - &spec_vaddr.to_le_bytes(), - ) - .unwrap(); - self.elf - .write_symbol( - "sel4_capdl_initializer_serialized_spec_data_size", - &spec_size.to_le_bytes(), - ) - .unwrap(); + self.elf.add_segment( + true, + false, + false, + phdrs_table_vaddr, + ElfSegmentData::RealData(phdrs_table_bytes), + Some(PHENT_TYPE_PHDR), + ); self.elf .write_symbol( - "sel4_capdl_initializer_image_start", - &self.elf.lowest_vaddr().to_le_bytes(), + "sel4_phdrs_patched__vaddr", + &phdrs_table_vaddr.to_le_bytes(), ) .unwrap(); + self.elf .write_symbol( - "sel4_capdl_initializer_image_end", - &self.elf.highest_vaddr().to_le_bytes(), + "sel4_phdrs_patched__phnum", + &(expected_phnum as u16).to_le_bytes(), ) .unwrap(); diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index c3e23d192..84028aadc 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -63,14 +63,14 @@ struct ElfSectionHeader64 { #[repr(C, packed)] pub struct ElfProgramHeader64 { - type_: u32, - flags: u32, - offset: u64, - vaddr: u64, - paddr: u64, - filesz: u64, - memsz: u64, - align: u64, + pub type_: u32, + pub flags: u32, + pub offset: u64, + pub vaddr: u64, + pub paddr: u64, + pub filesz: u64, + pub memsz: u64, + pub align: u64, } #[repr(C, packed)] @@ -100,12 +100,13 @@ struct ElfHeader64 { const ELF_MAGIC: &[u8; 4] = b"\x7FELF"; -const PHENT_TYPE_LOADABLE: u32 = 1; +pub const PHENT_TYPE_LOADABLE: u32 = 1; +pub const PHENT_TYPE_PHDR: u32 = 6; /// ELF program-header flags (`p_flags`) -const PF_X: u32 = 0x1; -const PF_W: u32 = 0x2; -const PF_R: u32 = 0x4; +pub const PF_X: u32 = 0x1; +pub const PF_W: u32 = 0x2; +pub const PF_R: u32 = 0x4; /// ELF section-header type (`sh_type`) const SHT_PROGBITS: u32 = 0x1; From eeaf7c06f9fc23aa930b482200a97c898a00b151 Mon Sep 17 00:00:00 2001 From: Bill Nguyen Date: Mon, 29 Jun 2026 15:31:39 +1000 Subject: [PATCH 5/5] tool/elf: `type_` -> `r#type` Updated all instances of struct member name `type_` to `r#type`. Signed-off-by: Bill Nguyen --- tool/microkit/src/capdl/initialiser.rs | 4 ++-- tool/microkit/src/elf.rs | 32 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tool/microkit/src/capdl/initialiser.rs b/tool/microkit/src/capdl/initialiser.rs index 45cca4930..d944b823e 100644 --- a/tool/microkit/src/capdl/initialiser.rs +++ b/tool/microkit/src/capdl/initialiser.rs @@ -107,7 +107,7 @@ impl CapDLInitialiser { // until we add it as a segment. But we can't add it as a segment until we finalise it. phdrs_table_bytes.extend(unsafe { struct_to_bytes(&ElfProgramHeader64 { - type_: PHENT_TYPE_PHDR, + r#type: PHENT_TYPE_PHDR, flags: PF_R, offset: 0, vaddr: phdrs_table_vaddr, @@ -119,7 +119,7 @@ impl CapDLInitialiser { }); phdrs_table_bytes.extend(unsafe { struct_to_bytes(&ElfProgramHeader64 { - type_: PHENT_TYPE_LOADABLE, + r#type: PHENT_TYPE_LOADABLE, flags: PF_R, offset: 0, vaddr: phdrs_table_vaddr, diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index 84028aadc..11caa8db6 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -21,7 +21,7 @@ struct ElfHeader32 { ident_osabi: u8, ident_abiversion: u8, _padding: [u8; 7], - type_: u16, + r#type: u16, machine: u16, version: u32, entry: u32, @@ -50,7 +50,7 @@ struct ElfSymbol64 { #[repr(C, packed)] struct ElfSectionHeader64 { name: u32, - type_: u32, + r#type: u32, flags: u64, addr: u64, offset: u64, @@ -63,7 +63,7 @@ struct ElfSectionHeader64 { #[repr(C, packed)] pub struct ElfProgramHeader64 { - pub type_: u32, + pub r#type: u32, pub flags: u32, pub offset: u64, pub vaddr: u64, @@ -83,7 +83,7 @@ struct ElfHeader64 { ident_osabi: u8, ident_abiversion: u8, _padding: [u8; 7], - type_: u16, + r#type: u16, machine: u16, version: u32, entry: u64, @@ -201,7 +201,7 @@ impl ElfSegment { #[derive(Eq, PartialEq, Clone)] pub struct ProgramHeader { pub segment_idx: usize, - pub type_: u32, + pub r#type: u32, } #[derive(Eq, PartialEq, Clone)] @@ -249,7 +249,7 @@ impl ElfFile { .enumerate() .map(|(i, _)| ProgramHeader { segment_idx: i, - type_: PHENT_TYPE_LOADABLE, + r#type: PHENT_TYPE_LOADABLE, }) .collect(); @@ -348,7 +348,7 @@ impl ElfFileReader { let segment_start = phent.offset as usize; let segment_end = phent.offset as usize + phent.filesz as usize; - if phent.type_ != PHENT_TYPE_LOADABLE { + if phent.r#type != PHENT_TYPE_LOADABLE { continue; } @@ -363,7 +363,7 @@ impl ElfFileReader { data: segment_data, phys_addr: phent.paddr, virt_addr: phent.vaddr, - loadable: phent.type_ == PHENT_TYPE_LOADABLE, + loadable: phent.r#type == PHENT_TYPE_LOADABLE, attrs: flags, }; @@ -385,7 +385,7 @@ impl ElfFileReader { let shent_bytes = &self.bytes[shent_start as usize..shent_end as usize]; let shent = unsafe { bytes_to_struct::(shent_bytes) }; - if shent.type_ == 2 { + if shent.r#type == 2 { symtab_shent = Some(shent) } shents.push(shent); @@ -550,13 +550,13 @@ impl ElfFile { self.program_headers.push(ProgramHeader { segment_idx: self.segments.len() - 1, - type_: PHENT_TYPE_LOADABLE, + r#type: PHENT_TYPE_LOADABLE, }); if let Some(meta_phdr_type) = meta_phdr_type_maybe { self.program_headers.push(ProgramHeader { segment_idx: self.segments.len() - 1, - type_: meta_phdr_type, + r#type: meta_phdr_type, }); } } @@ -572,7 +572,7 @@ impl ElfFile { let linked_segment = &self.segments[program_header.segment_idx]; let phdr = ElfProgramHeader64 { - type_: program_header.type_, + r#type: program_header.r#type, flags: linked_segment.attrs, offset: 0, vaddr: linked_segment.virt_addr, @@ -620,7 +620,7 @@ impl ElfFile { ident_osabi: 0, ident_abiversion: 0, _padding: [0; 7], - type_: 2, // executable file + r#type: 2, // executable file machine: self.machine, version: 1, entry: self.entry, @@ -659,7 +659,7 @@ impl ElfFile { for (phdr, seg_idx) in self.phdrs_table_serialised().iter_mut() { phdr.offset = seg_idx_to_data_off[seg_idx]; - let phdr_type = phdr.type_; + let phdr_type = phdr.r#type; elf_file .write_all(unsafe { struct_to_bytes(phdr) }) .unwrap_or_else(|_| { @@ -687,7 +687,7 @@ impl ElfFile { for (i, seg) in self.loadable_segments().iter().enumerate() { let sh_serialised = ElfSectionHeader64 { name: 0, - type_: SHT_PROGBITS, + r#type: SHT_PROGBITS, flags: seg.section_flags(), addr: seg.phys_addr, offset: seg_idx_to_data_off[&i], @@ -710,7 +710,7 @@ impl ElfFile { } let strtab_seg = ElfSectionHeader64 { name: 0, - type_: SHT_STRTAB, + r#type: SHT_STRTAB, flags: 0, addr: 0, offset: data_off_watermark,