sbpf_disassembler/
program.rs1use std::io::Cursor;
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 cursor::ELFCursor, elf_header::ELFHeader, errors::EZBpfError, program_header::ProgramHeader,
8 section_header::SectionHeader, section_header_entry::SectionHeaderEntry,
9};
10
11#[derive(Debug, Serialize, Deserialize)]
12pub struct Program {
13 pub elf_header: ELFHeader,
14 pub program_headers: Vec<ProgramHeader>,
15 pub section_headers: Vec<SectionHeader>,
16 pub section_header_entries: Vec<SectionHeaderEntry>,
17}
18
19impl Program {
20 pub fn from_bytes(b: &[u8]) -> Result<Self, EZBpfError> {
21 let mut c = Cursor::new(b);
22 let elf_header = c.read_elf_header()?;
23
24 c.set_position(elf_header.e_phoff);
25 let program_headers = (0..elf_header.e_phnum)
26 .map(|_| c.read_program_header())
27 .collect::<Result<Vec<_>, _>>()?;
28 c.set_position(elf_header.e_shoff);
29 let section_headers = (0..elf_header.e_shnum)
30 .map(|_| c.read_section_header())
31 .collect::<Result<Vec<_>, _>>()?;
32
33 let shstrndx = §ion_headers[elf_header.e_shstrndx as usize];
34 let shstrndx_value = b
35 [shstrndx.sh_offset as usize..shstrndx.sh_offset as usize + shstrndx.sh_size as usize]
36 .to_vec();
37
38 let mut indices: Vec<u32> = section_headers.iter().map(|h| h.sh_name).collect();
39 indices.push(shstrndx.sh_size as u32);
40 indices.sort_unstable();
41
42 let section_header_entries = section_headers
43 .iter()
44 .map(|s| {
45 let current_offset = s.sh_name as usize;
46 let next_index = indices.binary_search(&s.sh_name).unwrap() + 1;
47 let next_offset =
48 *indices.get(next_index).ok_or(EZBpfError::InvalidString)? as usize;
49
50 let label = String::from_utf8(shstrndx_value[current_offset..next_offset].to_vec())
51 .unwrap_or("default".to_string());
52 let data =
53 b[s.sh_offset as usize..s.sh_offset as usize + s.sh_size as usize].to_vec();
54
55 SectionHeaderEntry::new(label, s.sh_offset as usize, data)
56 })
57 .collect::<Result<Vec<_>, _>>()?;
58
59 Ok(Self {
60 elf_header,
61 program_headers,
62 section_headers,
63 section_header_entries,
64 })
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use hex_literal::hex;
71
72 use crate::program::Program;
73
74 #[test]
75 fn try_deserialize_program() {
76 let program = Program::from_bytes(&hex!("7F454C460201010000000000000000000300F700010000002001000000000000400000000000000028020000000000000000000040003800030040000600050001000000050000002001000000000000200100000000000020010000000000003000000000000000300000000000000000100000000000000100000004000000C001000000000000C001000000000000C0010000000000003C000000000000003C000000000000000010000000000000020000000600000050010000000000005001000000000000500100000000000070000000000000007000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007912A000000000007911182900000000B7000000010000002D21010000000000B70000000000000095000000000000001E0000000000000004000000000000000600000000000000C0010000000000000B0000000000000018000000000000000500000000000000F0010000000000000A000000000000000C00000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000120001002001000000000000300000000000000000656E747279706F696E7400002E74657874002E64796E737472002E64796E73796D002E64796E616D6963002E73687374727461620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000600000000000000200100000000000020010000000000003000000000000000000000000000000008000000000000000000000000000000170000000600000003000000000000005001000000000000500100000000000070000000000000000400000000000000080000000000000010000000000000000F0000000B0000000200000000000000C001000000000000C001000000000000300000000000000004000000010000000800000000000000180000000000000007000000030000000200000000000000F001000000000000F0010000000000000C00000000000000000000000000000001000000000000000000000000000000200000000300000000000000000000000000000000000000FC010000000000002A00000000000000000000000000000001000000000000000000000000000000")).unwrap();
77 println!("{:?}", program.section_header_entries);
78 }
79}