1use {
2 crate::errors::{RuntimeError, RuntimeResult},
3 either::Either,
4 sbpf_common::{inst_param::Number, instruction::Instruction, opcode::Opcode},
5 sbpf_disassembler::{program::Program, rodata::RodataSection},
6 sbpf_vm::memory::Memory,
7};
8
9pub fn load_elf(elf_bytes: &[u8]) -> RuntimeResult<(Vec<Instruction>, Vec<u8>, usize)> {
11 let program = Program::from_bytes(elf_bytes)
12 .map_err(|e| RuntimeError::ElfParseError(format!("{:?}", e)))?;
13 let (mut instructions, rodata_section, entrypoint_idx) = program
14 .to_ixs()
15 .map_err(|e| RuntimeError::ElfParseError(format!("{:?}", e)))?;
16 let entrypoint = entrypoint_idx.unwrap_or(0);
17
18 let mut rodata = rodata_section
19 .as_ref()
20 .map(|s| s.data.clone())
21 .unwrap_or_default();
22
23 if let Some(ref section) = rodata_section {
24 apply_relocations(&mut instructions, &mut rodata, section);
25 }
26
27 Ok((instructions, rodata, entrypoint))
28}
29
30fn apply_relocations(instructions: &mut [Instruction], rodata: &mut [u8], section: &RodataSection) {
32 let elf_base = section.base_address;
33 let elf_end = elf_base + section.data.len() as u64;
34
35 for ix in instructions.iter_mut() {
37 if ix.opcode == Opcode::Lddw
38 && let Some(Either::Right(Number::Int(imm))) = &ix.imm
39 {
40 let addr = *imm as u64;
41 if addr >= elf_base && addr < elf_end {
42 ix.imm = Some(Either::Right(Number::Int(
43 (Memory::RODATA_START + addr - elf_base) as i64,
44 )));
45 }
46 }
47 }
48
49 for &offset in §ion.data_relocations {
51 if offset + 8 <= rodata.len() {
52 let ptr = u64::from_le_bytes(rodata[offset..offset + 8].try_into().unwrap());
53 if ptr >= elf_base && ptr < elf_end {
54 let relocated = Memory::RODATA_START + (ptr - elf_base);
55 rodata[offset..offset + 8].copy_from_slice(&relocated.to_le_bytes());
56 }
57 }
58 }
59
60 for &(offset, ix_idx) in §ion.text_relocations {
62 if offset + 8 <= rodata.len() {
63 rodata[offset..offset + 8].copy_from_slice(&(ix_idx as u64).to_le_bytes());
64 }
65 }
66}