diff --git a/Cargo.lock b/Cargo.lock index c57a567..a765341 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,6 +279,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + [[package]] name = "generic-array" version = "0.14.7" @@ -1073,6 +1079,7 @@ dependencies = [ "valida-bus", "valida-cpu", "valida-derive", + "valida-elf", "valida-machine", "valida-memory", "valida-opcodes", @@ -1121,6 +1128,14 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "valida-elf" +version = "0.1.0" +dependencies = [ + "elf", + "valida-machine", +] + [[package]] name = "valida-machine" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 39ebb33..3a2fefd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "bus", "cpu", "derive", + "elf", "native_field", "machine", "memory", diff --git a/basic/Cargo.toml b/basic/Cargo.toml index 0739584..121e166 100644 --- a/basic/Cargo.toml +++ b/basic/Cargo.toml @@ -26,6 +26,7 @@ valida-assembler = { path = "../assembler" } valida-bus = { path = "../bus" } valida-cpu = { path = "../cpu" } valida-derive = { path = "../derive" } +valida-elf = { path = "../elf" } valida-machine = { path = "../machine" } valida-memory = { path = "../memory" } valida-opcodes = { path = "../opcodes" } diff --git a/basic/src/bin/valida.rs b/basic/src/bin/valida.rs index 0042fc7..0687f3b 100644 --- a/basic/src/bin/valida.rs +++ b/basic/src/bin/valida.rs @@ -1,4 +1,5 @@ use clap::Parser; +use std::fs; use std::fs::File; use std::io::{stdout, Write}; @@ -11,7 +12,9 @@ use valida_cpu::MachineWithCpuChip; use valida_machine::{Machine, MachineProof, ProgramROM, StdinAdviceProvider}; use valida_memory::MachineWithMemoryChip; +use valida_elf::{load_executable_file, Program}; use valida_program::MachineWithProgramChip; +use valida_static_data::MachineWithStaticDataChip; use p3_challenger::DuplexChallenger; use p3_dft::Radix2DitParallel; @@ -283,16 +286,17 @@ fn main() { } let mut machine = BasicMachine::::default(); - let rom = match ProgramROM::from_file(&args.program) { - Ok(contents) => contents, - Err(e) => panic!("Failure to load file: {}. {}", &args.program, e), - }; - machine.program_mut().set_program_rom(&rom); + let Program { code, data } = load_executable_file( + fs::read(&args.program) + .expect(format!("Failed to read executable file: {}", &args.program).as_str()), + ); + machine.program_mut().set_program_rom(&code); machine.cpu_mut().fp = args.stack_height; machine.cpu_mut().save_register_state(); + machine.static_data_mut().load(data); // Run the program - machine.run(&rom, &mut StdinAdviceProvider); + machine.run(&code, &mut StdinAdviceProvider); type Val = BabyBear; type Challenge = BinomialExtensionField; diff --git a/elf/Cargo.toml b/elf/Cargo.toml new file mode 100644 index 0000000..c31aba3 --- /dev/null +++ b/elf/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "valida-elf" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dependencies] +elf = "0.7.4" +valida-machine = { path = "../machine" } diff --git a/elf/src/lib.rs b/elf/src/lib.rs new file mode 100644 index 0000000..3cd5b4b --- /dev/null +++ b/elf/src/lib.rs @@ -0,0 +1,90 @@ +#![no_std] + +extern crate alloc; + +use alloc::collections::BTreeMap; +use alloc::vec; +use alloc::vec::Vec; +use elf::abi; +use elf::endian::AnyEndian; +use elf::section::SectionHeader; +use elf::ElfBytes; +use valida_machine::{ProgramROM, Word}; + +pub struct Program { + pub code: ProgramROM, + pub data: BTreeMap>, +} + +pub fn load_executable_file(file: Vec) -> Program { + if file[0] == 0x7F && file[1] == 0x45 && file[2] == 0x4C && file[3] == 0x46 { + load_elf_object_file(file) + } else { + Program { + code: ProgramROM::from_machine_code(file.as_slice()), + data: BTreeMap::new(), + } + } +} + +pub fn load_elf_object_file(file: Vec) -> Program { + let file = ElfBytes::::minimal_parse(file.as_slice()).unwrap(); + let mut data_sections: Vec<(SectionHeader, &[u8])> = vec![]; + let mut bss_sections: Vec = vec![]; + let mut text_sections: Vec<(SectionHeader, &[u8])> = vec![]; + for section_header in file.section_headers().unwrap().iter() { + let is_data: bool = section_header.sh_type == abi::SHT_PROGBITS + && section_header.sh_flags == (abi::SHF_ALLOC | abi::SHF_WRITE).into(); + let is_bss: bool = section_header.sh_type == abi::SHT_NOBITS + && section_header.sh_flags == (abi::SHF_ALLOC | abi::SHF_WRITE).into(); + let is_text: bool = section_header.sh_type == abi::SHT_PROGBITS + && section_header.sh_flags == (abi::SHF_ALLOC | abi::SHF_EXECINSTR).into(); + let is_useful: bool = is_data || is_bss || is_text; + if is_useful { + if is_data || is_text { + let section_data = file.section_data(§ion_header).unwrap(); + match section_data { + (section_data, None) => { + if is_data { + data_sections.push((section_header, section_data)); + } else if is_text { + text_sections.push((section_header, section_data)); + } + } + _ => panic!("unsupported: compressed ELF section data"), + } + } else if is_bss { + bss_sections.push(section_header); + } + } + } + let code_size = text_sections + .iter() + .map(|(section_header, _)| section_header.sh_addr + section_header.sh_size) + .fold(0, |a, b| a.max(b)); + let mut code: Vec = vec![0; code_size as usize]; + for (section_header, section_data) in text_sections { + for i in 0..section_header.sh_size as usize { + code[i + section_header.sh_addr as usize] = section_data[i]; + } + } + let mut data: BTreeMap> = BTreeMap::new(); + for (section_header, section_data) in data_sections { + for i in 0..(section_header.sh_size / 4) as usize { + data.insert( + >::try_into(section_header.sh_addr).unwrap() + + >::try_into(i * 4).unwrap(), + Word([ + section_data[i * 4], + section_data[i * 4 + 1], + section_data[i * 4 + 2], + section_data[i * 4 + 3], + ]), + ); + } + } + Program { + code: ProgramROM::from_machine_code(code.as_slice()), + data: data, + } +} diff --git a/static_data/src/lib.rs b/static_data/src/lib.rs index 6b87dad..cbe3615 100644 --- a/static_data/src/lib.rs +++ b/static_data/src/lib.rs @@ -39,6 +39,10 @@ impl StaticDataChip { } } + pub fn load(&mut self, cells: BTreeMap>) { + self.cells = cells; + } + pub fn write(&mut self, address: u32, value: Word) { self.cells.insert(address, value); }