diff --git a/tool/microkit/src/elf.rs b/tool/microkit/src/elf.rs index badb3eec..a3d1961c 100644 --- a/tool/microkit/src/elf.rs +++ b/tool/microkit/src/elf.rs @@ -108,6 +108,7 @@ const PF_R: u32 = 0x4; /// ELF section-header type (`sh_type`) const SHT_PROGBITS: u32 = 0x1; +const SHT_STRTAB: u32 = 0x3; /// ELF section-header flags (`sh_flags`) const SHF_WRITE: u64 = 0x1; @@ -494,14 +495,15 @@ impl ElfFile { self.segments.iter().filter(|s| s.loadable).collect() } - /// Re-create a minimal ELF file with all the segments. + /// 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::(); let phnum = self.loadable_segments().len(); let phentsize = size_of::(); - let shnum = self.loadable_segments().len() + 1; // First entry is reserved + // First entry is reserved, last entry is dummy strtab + let shnum = self.loadable_segments().len() + 2; let shentsize = size_of::(); let mut elf_file = match File::create(out) { @@ -539,7 +541,7 @@ impl ElfFile { phnum: phnum as u16, shentsize: shentsize as u16, shnum: shnum as u16, - shstrndx: 0, + shstrndx: (shnum - 1) as u16, }; elf_file .write_all(unsafe { @@ -617,6 +619,33 @@ impl ElfFile { ) }); } + let strtab_seg = ElfSectionHeader64 { + name: 0, + type_: SHT_STRTAB, + flags: 0, + addr: 0, + offset: data_off_watermark, // points to a null byte that we will write later after all the data + size: 1, + link: 0, + info: 0, + addralign: 0, + entsize: 0, + }; + + // Uncomment this if more data needs to be written. + // data_off_watermark += 1; + // Have to comment out to keep clippy happy, else: + // "warning: value assigned to `data_off_watermark` is never read", or if we try to allow with `#[allow(unused_assignments)]`: + // "error[E0658]: attributes on expressions are experimental" + + elf_file + .write_all(unsafe { struct_to_bytes(&strtab_seg) }) + .unwrap_or_else(|_| { + panic!( + "Failed to write ELF string table section header for '{}'", + out.display() + ) + }); // Finally the data for each segment will follow for (i, seg) in self @@ -634,6 +663,16 @@ impl ElfFile { }); } + // Then the null byte for string table + elf_file + .write_all(vec![0u8; 1].as_slice()) + .unwrap_or_else(|_| { + panic!( + "Failed to write ELF string table byte for '{}'", + out.display() + ) + }); + elf_file.flush().unwrap(); Ok(metadata(out).unwrap().len())