From 8239079130c174e029a02df4b335b709bdfa93e0 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Sat, 1 Apr 2023 00:14:09 +0200 Subject: [PATCH] Add section flag support, loader now ready to run binary files --- src/kernel/thread_manager.rs | 4 +-- src/simulator/loader.rs | 53 ++++++++++++++++++++++++++++++++---- src/simulator/machine.rs | 4 +-- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index e88cf59..acecc5b 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -206,8 +206,8 @@ mod test { #[ignore = "Pas encore terminé, contient des bugs"] fn test_thread_context() { let mut machine = Machine::init_machine(); - loader::load("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error"); - let start_pc = 0x1000; + let loader = loader::Loader::new("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error"); + let start_pc = loader.elf_header.entrypoint; let system = &mut System::default(); let thread1 = Thread::new("th1"); diff --git a/src/simulator/loader.rs b/src/simulator/loader.rs index cf77546..9bbe132 100644 --- a/src/simulator/loader.rs +++ b/src/simulator/loader.rs @@ -187,11 +187,22 @@ impl TryFrom<&Vec> for ElfHeader { } } + +pub enum FlagValue { + ShfWrite = 0x1, + ShfAlloc = 0x2, + ShfExecinstr = 0x4, + ShfMerge = 0x10, + ShfStrings = 0x20, + ShfInfoLink = 0x40, + ShfLinkOrder = 0x80, + // There is others but are unrelevant (I think) +} #[derive(Debug)] pub struct SectionHeader { pub name_offset: u32, pub header_type: u32, - pub attribute: u64, + pub flags: u64, pub virt_addr: u64, pub image_offset: u64, pub section_size: u64, @@ -203,6 +214,11 @@ pub struct SectionHeader { impl SectionHeader { + /// return true if flag of this section contains / have `key`, false otherwise + pub fn does_flag_contains_key(&self, key: FlagValue) -> bool { + self.flags & key as u64 != 0 + } + fn get_name_offset(instructions: &Vec, address: usize) -> Option { get_address_point(instructions, address, true).map(|v| { v as u32 }) // set true to return a u32 @@ -212,7 +228,7 @@ impl SectionHeader { get_address_point(instructions, address + 0x4, true).map(|v| { v as u32 }) } - fn get_attribute(instructions: &Vec, address: usize, is_32bits: bool) -> Option { + fn get_flags(instructions: &Vec, address: usize, is_32bits: bool) -> Option { get_address_point(instructions, address + 0x8, is_32bits) } @@ -256,7 +272,7 @@ impl TryFrom<(&Vec, u64, bool)> for SectionHeader { let name_offset = Self::get_name_offset(instructions, address).ok_or(())?; let header_type = Self::get_header_type(instructions, address).ok_or(())?; - let attribute = Self::get_attribute(instructions, address, is_32bits).ok_or(())?; + let attribute = Self::get_flags(instructions, address, is_32bits).ok_or(())?; let virt_addr = Self::get_virtual_address(instructions, address, is_32bits).ok_or(())?; let image_offset = Self::get_image_offset(instructions, address, is_32bits).ok_or(())?; let section_size = Self::get_section_size(instructions, address, is_32bits).ok_or(())?; @@ -266,7 +282,7 @@ impl TryFrom<(&Vec, u64, bool)> for SectionHeader { let entry_size = Self::get_entry_size(instructions, address, is_32bits).ok_or(())?; Ok(Self { name_offset, header_type, - attribute, + flags: attribute, virt_addr, image_offset, section_size, @@ -292,7 +308,31 @@ pub enum LoaderError { impl Loader { - pub fn load(path: &str, machine: &mut Machine, start_index: usize) -> Result { + pub fn new(path: &str, machine: &mut Machine, start_index: usize) -> Result { + let loader = Self::load_and_parse(path)?; + loader.load_into_machine(machine, start_index)?; + Ok(loader) + } + + fn load_into_machine(&self, machine: &mut Machine, start_index: usize) -> Result{ + for i in 0..self.sections.len() { + let section = &self.sections[i]; + if section.does_flag_contains_key(FlagValue::ShfAlloc) { + // Can allocate to machine memory + for j in (0..section.section_size as usize).step_by(4) { + let mut buf: [u8; 4] = [0; 4]; + for k in 0..4 { + buf[k] = self.bytes.get(section.image_offset as usize + j + k).copied().ok_or(LoaderError::ParsingError)?; + } + machine.write_memory(4, start_index + section.virt_addr as usize + j, u32::from_le_bytes(buf) as u64); + } + } + } + let last = self.sections.last().ok_or(LoaderError::ParsingError)?; + Ok(start_index as u64 + last.virt_addr + last.section_size) + } + + fn load_and_parse(path: &str) -> Result { let file = fs::File::open(path); match file { Ok(mut file) => { @@ -388,7 +428,8 @@ mod test { #[ignore = "CI gitlab a modifié"] fn test_parse_elf() { let mut machine = Machine::init_machine(); - let loader = Loader::load("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error"); + let loader = Loader::load_and_parse("./test/riscv_instructions/simple_arithmetics/unsigned_addition").expect("IO Error"); + loader.load_into_machine(&mut machine, 0).expect("Parsing error"); assert_eq!(false, loader.elf_header.is_32bits); assert_eq!(false, loader.elf_header.endianess); assert_eq!(true, loader.elf_header.sys_v_abi); diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 1a8775a..1ab9087 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -188,9 +188,9 @@ impl Machine { } println!("________________SP________________"); let sp_index = self.int_reg.get_reg(2); - for i in 0..5 { + /* for i in 0..5 { println!("SP+{:<2} : {:16x}", i*8, self.read_memory(8, (sp_index + i*8) as usize)); - } + } */ println!("##################################"); }