Add section flag support, loader now ready to run binary files
This commit is contained in:
parent
0a744f0f94
commit
8239079130
@ -206,8 +206,8 @@ mod test {
|
|||||||
#[ignore = "Pas encore terminé, contient des bugs"]
|
#[ignore = "Pas encore terminé, contient des bugs"]
|
||||||
fn test_thread_context() {
|
fn test_thread_context() {
|
||||||
let mut machine = Machine::init_machine();
|
let mut machine = Machine::init_machine();
|
||||||
loader::load("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error");
|
let loader = loader::Loader::new("./test/riscv_instructions/simple_arithmetics/unsigned_addition", &mut machine, 0).expect("IO Error");
|
||||||
let start_pc = 0x1000;
|
let start_pc = loader.elf_header.entrypoint;
|
||||||
let system = &mut System::default();
|
let system = &mut System::default();
|
||||||
|
|
||||||
let thread1 = Thread::new("th1");
|
let thread1 = Thread::new("th1");
|
||||||
|
@ -187,11 +187,22 @@ impl TryFrom<&Vec<u8>> 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)]
|
#[derive(Debug)]
|
||||||
pub struct SectionHeader {
|
pub struct SectionHeader {
|
||||||
pub name_offset: u32,
|
pub name_offset: u32,
|
||||||
pub header_type: u32,
|
pub header_type: u32,
|
||||||
pub attribute: u64,
|
pub flags: u64,
|
||||||
pub virt_addr: u64,
|
pub virt_addr: u64,
|
||||||
pub image_offset: u64,
|
pub image_offset: u64,
|
||||||
pub section_size: u64,
|
pub section_size: u64,
|
||||||
@ -203,6 +214,11 @@ pub struct SectionHeader {
|
|||||||
|
|
||||||
impl 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<u8>, address: usize) -> Option<u32> {
|
fn get_name_offset(instructions: &Vec<u8>, address: usize) -> Option<u32> {
|
||||||
get_address_point(instructions, address, true).map(|v| { v as u32 })
|
get_address_point(instructions, address, true).map(|v| { v as u32 })
|
||||||
// set true to return a 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 })
|
get_address_point(instructions, address + 0x4, true).map(|v| { v as u32 })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_attribute(instructions: &Vec<u8>, address: usize, is_32bits: bool) -> Option<u64> {
|
fn get_flags(instructions: &Vec<u8>, address: usize, is_32bits: bool) -> Option<u64> {
|
||||||
get_address_point(instructions, address + 0x8, is_32bits)
|
get_address_point(instructions, address + 0x8, is_32bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +272,7 @@ impl TryFrom<(&Vec<u8>, u64, bool)> for SectionHeader {
|
|||||||
|
|
||||||
let name_offset = Self::get_name_offset(instructions, address).ok_or(())?;
|
let name_offset = Self::get_name_offset(instructions, address).ok_or(())?;
|
||||||
let header_type = Self::get_header_type(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 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 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(())?;
|
let section_size = Self::get_section_size(instructions, address, is_32bits).ok_or(())?;
|
||||||
@ -266,7 +282,7 @@ impl TryFrom<(&Vec<u8>, u64, bool)> for SectionHeader {
|
|||||||
let entry_size = Self::get_entry_size(instructions, address, is_32bits).ok_or(())?;
|
let entry_size = Self::get_entry_size(instructions, address, is_32bits).ok_or(())?;
|
||||||
Ok(Self { name_offset,
|
Ok(Self { name_offset,
|
||||||
header_type,
|
header_type,
|
||||||
attribute,
|
flags: attribute,
|
||||||
virt_addr,
|
virt_addr,
|
||||||
image_offset,
|
image_offset,
|
||||||
section_size,
|
section_size,
|
||||||
@ -292,7 +308,31 @@ pub enum LoaderError {
|
|||||||
|
|
||||||
impl Loader {
|
impl Loader {
|
||||||
|
|
||||||
pub fn load(path: &str, machine: &mut Machine, start_index: usize) -> Result<Self, LoaderError> {
|
pub fn new(path: &str, machine: &mut Machine, start_index: usize) -> Result<Self, LoaderError> {
|
||||||
|
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<u64, LoaderError>{
|
||||||
|
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<Self, LoaderError> {
|
||||||
let file = fs::File::open(path);
|
let file = fs::File::open(path);
|
||||||
match file {
|
match file {
|
||||||
Ok(mut file) => {
|
Ok(mut file) => {
|
||||||
@ -388,7 +428,8 @@ mod test {
|
|||||||
#[ignore = "CI gitlab a modifié"]
|
#[ignore = "CI gitlab a modifié"]
|
||||||
fn test_parse_elf() {
|
fn test_parse_elf() {
|
||||||
let mut machine = Machine::init_machine();
|
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.is_32bits);
|
||||||
assert_eq!(false, loader.elf_header.endianess);
|
assert_eq!(false, loader.elf_header.endianess);
|
||||||
assert_eq!(true, loader.elf_header.sys_v_abi);
|
assert_eq!(true, loader.elf_header.sys_v_abi);
|
||||||
|
@ -188,9 +188,9 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
println!("________________SP________________");
|
println!("________________SP________________");
|
||||||
let sp_index = self.int_reg.get_reg(2);
|
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!("SP+{:<2} : {:16x}", i*8, self.read_memory(8, (sp_index + i*8) as usize));
|
||||||
}
|
} */
|
||||||
println!("##################################");
|
println!("##################################");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user