sbpf_disassembler/
section_header_entry.rs

1use std::fmt::Debug;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{errors::DisassemblerError, 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, DisassemblerError> {
20        let mut h = SectionHeaderEntry {
21            label,
22            offset,
23            data,
24            ixs: vec![],
25            utf8: String::new(),
26        };
27
28        if h.label.contains(".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>, DisassemblerError> {
43        if self.data.len() % 8 != 0 {
44            return Err(DisassemblerError::InvalidDataLength);
45        }
46        let mut ixs: Vec<Ix> = vec![];
47        let mut pos = 0;
48
49        while pos < self.data.len() {
50            let remaining = &self.data[pos..];
51            if remaining.len() < 8 {
52                break;
53            }
54
55            let ix = Ix::from_bytes(remaining)?;
56            if ix.op == crate::opcodes::OpCode::Lddw {
57                pos += 16;
58            } else {
59                pos += 8;
60            }
61
62            ixs.push(ix);
63        }
64
65        Ok(ixs)
66    }
67
68    pub fn to_bytes(&self) -> Vec<u8> {
69        self.data.clone()
70    }
71}
72
73#[cfg(test)]
74mod test {
75    use crate::{instructions::Ix, opcodes::OpCode, section_header_entry::SectionHeaderEntry};
76
77    #[test]
78    fn serialize_e2e() {
79        let data = vec![
80            0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81            0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82        ];
83
84        let h = SectionHeaderEntry::new(".text\0".to_string(), 128, data.clone()).unwrap();
85
86        let ixs = vec![
87            Ix {
88                op: OpCode::Lddw,
89                dst: 1,
90                src: 0,
91                off: 0,
92                imm: 0,
93            },
94            Ix {
95                op: OpCode::Exit,
96                dst: 0,
97                src: 0,
98                off: 0,
99                imm: 0,
100            },
101        ];
102        assert_eq!(ixs, h.to_ixs().unwrap());
103
104        assert_eq!(
105            data,
106            h.to_ixs()
107                .expect("Invalid IX")
108                .into_iter()
109                .flat_map(|i| i.to_bytes())
110                .collect::<Vec<u8>>()
111        )
112    }
113}