monistode_binutils/object_file/sections/
header.rs1use 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]); data.extend(header.bit_length.to_le_bytes());
65 }
66 SectionHeader::SymbolTable(header) => {
67 data.push(SectionType::SymbolTable.into());
68 data.extend([0; 3]); data.extend(header.entry_count.to_le_bytes());
70 data.extend(header.names_length.to_le_bytes());
71 data.extend([0; 4]); }
73 SectionHeader::RelocationTable(header) => {
74 data.push(SectionType::RelocationTable.into());
75 data.extend([0; 3]); data.extend(header.entry_count.to_le_bytes());
77 data.extend(header.names_length.to_le_bytes());
78 data.extend([0; 4]); }
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}