monistode_binutils/object_file/sections/
header.rs

1use crate::serializable::{Serializable, SerializationError};
2
3#[derive(Debug, Clone)]
4pub enum SectionType {
5    Text,
6    SymbolTable,
7    RelocationTable,
8}
9
10impl TryFrom<u8> for SectionType {
11    type Error = SerializationError;
12
13    fn try_from(value: u8) -> Result<Self, Self::Error> {
14        match value {
15            0 => Ok(SectionType::Text),
16            255 => Ok(SectionType::SymbolTable),
17            254 => Ok(SectionType::RelocationTable),
18            v => Err(SerializationError::InvalidSectionType(v)),
19        }
20    }
21}
22
23impl From<SectionType> for u8 {
24    fn from(value: SectionType) -> Self {
25        match value {
26            SectionType::Text => 0,
27            SectionType::SymbolTable => 255,
28            SectionType::RelocationTable => 254,
29        }
30    }
31}
32
33#[derive(Debug, Clone)]
34pub struct TextSectionHeader {
35    pub bit_length: usize,
36}
37
38#[derive(Debug, Clone)]
39pub struct SymbolTableHeader {
40    pub entry_count: u32,
41    pub names_length: u32,
42}
43
44#[derive(Debug, Clone)]
45pub struct RelocationTableHeader {
46    pub entry_count: u32,
47    pub names_length: u32,
48}
49
50#[derive(Debug, Clone)]
51pub enum SectionHeader {
52    Text(TextSectionHeader),
53    SymbolTable(SymbolTableHeader),
54    RelocationTable(RelocationTableHeader),
55}
56
57impl Serializable for SectionHeader {
58    fn serialize(&self) -> Vec<u8> {
59        let mut data = Vec::with_capacity(16);
60        match self {
61            SectionHeader::Text(header) => {
62                data.push(SectionType::Text.into());
63                data.extend([0; 7]); // Padding to 8 bytes
64                data.extend(header.bit_length.to_le_bytes());
65            }
66            SectionHeader::SymbolTable(header) => {
67                data.push(SectionType::SymbolTable.into());
68                data.extend([0; 3]); // Padding to 4 bytes
69                data.extend(header.entry_count.to_le_bytes());
70                data.extend(header.names_length.to_le_bytes());
71                data.extend([0; 4]); // Padding to 16 bytes
72            }
73            SectionHeader::RelocationTable(header) => {
74                data.push(SectionType::RelocationTable.into());
75                data.extend([0; 3]); // Padding to 4 bytes
76                data.extend(header.entry_count.to_le_bytes());
77                data.extend(header.names_length.to_le_bytes());
78                data.extend([0; 4]); // Padding to 16 bytes
79            }
80        }
81        data
82    }
83
84    fn deserialize(data: &[u8]) -> Result<(usize, Self), SerializationError> {
85        if data.len() < 16 {
86            return Err(SerializationError::DataTooShort);
87        }
88
89        match data[0] {
90            0 => {
91                let bit_length = u64::from_le_bytes([
92                    data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
93                ]) as usize;
94                Ok((16, SectionHeader::Text(TextSectionHeader { bit_length })))
95            }
96            255 | 254 => {
97                let entry_count = u32::from_le_bytes([data[4], data[5], data[6], data[7]]);
98                let names_length = u32::from_le_bytes([data[8], data[9], data[10], data[11]]);
99                let header = if data[0] == 255 {
100                    SectionHeader::SymbolTable(SymbolTableHeader {
101                        entry_count,
102                        names_length,
103                    })
104                } else {
105                    SectionHeader::RelocationTable(RelocationTableHeader {
106                        entry_count,
107                        names_length,
108                    })
109                };
110                Ok((16, header))
111            }
112            v => Err(SerializationError::InvalidSectionType(v)),
113        }
114    }
115}
116
117impl SectionHeader {
118    pub fn section_size(&self) -> u64 {
119        match self {
120            SectionHeader::Text(header) => (header.bit_length as u64 + 7) / 8,
121            SectionHeader::SymbolTable(header) => {
122                (header.entry_count as u64 * 12) + header.names_length as u64
123            }
124            SectionHeader::RelocationTable(header) => {
125                (header.entry_count as u64 * 16) + header.names_length as u64
126            }
127        }
128    }
129}