sbpf_disassembler/
section_header_entry.rs

1use std::{fmt::Debug, io::Cursor};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{cursor::ELFCursor, errors::EZBpfError, instructions::Ix};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct SectionHeaderEntry {
9    pub label: String,
10    pub offset: usize,
11    pub data: Vec<u8>,
12    #[serde(skip_serializing_if = "Vec::is_empty")]
13    pub ixs: Vec<Ix>,
14    #[serde(skip_serializing_if = "String::is_empty")]
15    pub utf8: String,
16}
17
18impl SectionHeaderEntry {
19    pub fn new(label: String, offset: usize, data: Vec<u8>) -> Result<Self, EZBpfError> {
20        let mut h = SectionHeaderEntry {
21            label,
22            offset,
23            data,
24            ixs: vec![],
25            utf8: String::new(),
26        };
27
28        if &h.label == ".text\0" {
29            h.ixs = h.to_ixs()?;
30        }
31
32        if let Ok(utf8) = String::from_utf8(h.data.clone()) {
33            h.utf8 = utf8;
34        }
35        Ok(h)
36    }
37
38    pub fn offset(&self) -> usize {
39        self.offset
40    }
41
42    pub fn to_ixs(&self) -> Result<Vec<Ix>, EZBpfError> {
43        if self.data.len() % 8 != 0 {
44            return Err(EZBpfError::InvalidDataLength);
45        }
46        let mut ixs: Vec<Ix> = vec![];
47        if self.data.len() >= 8 {
48            let mut c = Cursor::new(self.data.as_slice());
49            while let Ok(ix) = c.read_ix() {
50                ixs.push(ix);
51            }
52        }
53        Ok(ixs)
54    }
55
56    pub fn to_bytes(&self) -> Vec<u8> {
57        self.data.clone()
58    }
59}
60
61#[cfg(test)]
62mod test {
63    use crate::{instructions::Ix, opcodes::OpCode, section_header_entry::SectionHeaderEntry};
64
65    #[test]
66    fn serialize_e2e() {
67        let data = vec![
68            0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69            0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70        ];
71
72        let h = SectionHeaderEntry::new(".text\0".to_string(), 128, data.clone()).unwrap();
73
74        let ixs = vec![
75            Ix {
76                op: OpCode::Lddw,
77                dst: 1,
78                src: 0,
79                off: 0,
80                imm: 0,
81            },
82            Ix {
83                op: OpCode::Exit,
84                dst: 0,
85                src: 0,
86                off: 0,
87                imm: 0,
88            },
89        ];
90        assert_eq!(ixs, h.to_ixs().unwrap());
91
92        assert_eq!(
93            data,
94            h.to_ixs()
95                .expect("Invalid IX")
96                .into_iter()
97                .flat_map(|i| i.to_bytes())
98                .collect::<Vec<u8>>()
99        )
100    }
101}