Skip to content

Commit

Permalink
Some corrections to reading ELF files (valida-xyz#158)
Browse files Browse the repository at this point in the history
* issue/135: wip: set initial program counter

* issue/135: wip: correctly load elf file sections

* issue/135: correctly load elf file sections
  • Loading branch information
morganthomas authored Apr 23, 2024
1 parent 1f8d3d9 commit ffce55a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 20 deletions.
14 changes: 12 additions & 2 deletions basic/src/bin/valida.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,18 @@ impl Context {
last_fp_size_: 0,
};

let Program { code, data } = load_executable_file(
let Program {
code,
data,
initial_program_counter,
} = load_executable_file(
fs::read(&args.program)
.expect(format!("Failed to read executable file: {}", &args.program).as_str()),
);

context.machine_.program_mut().set_program_rom(&code);
context.machine_.static_data_mut().load(data);
context.machine_.cpu_mut().pc = initial_program_counter;
context.machine_.cpu_mut().fp = args.stack_height;
context.machine_.cpu_mut().save_register_state();

Expand Down Expand Up @@ -322,12 +327,17 @@ fn main() {
}

let mut machine = BasicMachine::<BabyBear>::default();
let Program { code, data } = load_executable_file(
let Program {
code,
data,
initial_program_counter,
} = 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().pc = initial_program_counter;
machine.cpu_mut().save_register_state();
machine.static_data_mut().load(data);

Expand Down
2 changes: 1 addition & 1 deletion basic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ impl<F: PrimeField32 + TwoAdicField> Machine<F> for BasicMachine<F> {
<WriteInstruction as Instruction<Self, F>>::OPCODE => {
WriteInstruction::execute_with_advice::<Adv>(self, ops, advice)
}
_ => panic!("Unrecognized opcode: {}", opcode),
_ => panic!("Unrecognized opcode: {}, pc = {}", opcode, pc),
};
self.read_word(pc as usize);

Expand Down
46 changes: 29 additions & 17 deletions elf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use elf::abi;
use elf::endian::AnyEndian;
use elf::section::SectionHeader;
use elf::ElfBytes;
use valida_machine::{ProgramROM, Word};
use valida_machine::{ProgramROM, Word, INSTRUCTION_ELEMENTS};

pub struct Program {
pub code: ProgramROM<i32>,
pub data: BTreeMap<u32, Word<u8>>,
pub initial_program_counter: u32,
}

pub fn load_executable_file(file: Vec<u8>) -> Program {
Expand All @@ -23,6 +24,7 @@ pub fn load_executable_file(file: Vec<u8>) -> Program {
Program {
code: ProgramROM::from_machine_code(file.as_slice()),
data: BTreeMap::new(),
initial_program_counter: 0,
}
}
}
Expand All @@ -35,29 +37,34 @@ pub fn load_elf_object_file(file: Vec<u8>) -> Program {
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_rodata: bool = section_header.sh_type == abi::SHT_PROGBITS
&& (section_header.sh_flags == abi::SHF_ALLOC.into()
|| section_header.sh_flags == 0x32); // TODO: what is 0x32?
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(&section_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));
}
if is_data || is_rodata || is_text {
let section_data = file.section_data(&section_header).unwrap();
match section_data {
(section_data, None) => {
if is_data || is_rodata {
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);
_ => panic!("unsupported: compressed ELF section data"),
}
} else if is_bss {
bss_sections.push(section_header);
}
}
let initial_program_counter = text_sections
.iter()
.map(|(section_header, _)| section_header.sh_addr / ((INSTRUCTION_ELEMENTS * 4) as u64))
.reduce(|a, b| a.min(b))
.unwrap();
let code_size = text_sections
.iter()
.map(|(section_header, _)| section_header.sh_addr + section_header.sh_size)
Expand All @@ -70,7 +77,11 @@ pub fn load_elf_object_file(file: Vec<u8>) -> Program {
}
let mut data: BTreeMap<u32, Word<u8>> = BTreeMap::new();
for (section_header, section_data) in data_sections {
for i in 0..(section_header.sh_size / 4) as usize {
let mut section_data = Vec::from(section_data);
while section_data.len() % 4 != 0 {
section_data.push(0);
}
for i in 0..(section_data.len() / 4) as usize {
data.insert(
<u64 as TryInto<u32>>::try_into(section_header.sh_addr).unwrap()
+ <usize as TryInto<u32>>::try_into(i * 4).unwrap(),
Expand All @@ -85,6 +96,7 @@ pub fn load_elf_object_file(file: Vec<u8>) -> Program {
}
Program {
code: ProgramROM::from_machine_code(code.as_slice()),
data: data,
data,
initial_program_counter: <u64 as TryInto<u32>>::try_into(initial_program_counter).unwrap(),
}
}

0 comments on commit ffce55a

Please sign in to comment.