monistode_binutils/object_file/
mod.rs1pub mod header;
2pub mod placed;
3pub mod relocations;
4pub mod sections;
5
6pub use header::ObjectHeader;
7pub use relocations::{Relocation, RelocationTable};
8pub use sections::*;
9
10use crate::{Architecture, Serializable, SerializationError, SymbolTable};
11
12#[derive(Debug, Clone)]
13pub struct ObjectFile {
14 architecture: Architecture,
15 sections: Vec<Section>,
16}
17
18impl Serializable for ObjectFile {
19 fn serialize(&self) -> Vec<u8> {
20 let mut data = Vec::new();
21
22 let mut symbol_table = SymbolTable::new();
24 let mut relocation_table = RelocationTable::new();
25
26 for (section_id, section) in self.sections.iter().enumerate() {
27 for symbol in section.symbols() {
28 symbol_table.add_symbol(section_id as u32, symbol);
29 }
30 for relocation in section.relocations() {
31 relocation_table.add_relocation(section_id as u32, relocation);
32 }
33 }
34
35 let header = ObjectHeader {
37 architecture: self.architecture,
38 section_count: self.sections.len() as u64 + 2, };
40 data.extend(header.serialize());
41
42 let mut section_data = Vec::new();
44 let mut headers = Vec::new();
45
46 for section in &self.sections {
48 let (header, bytes) = section.serialize();
49 headers.push(header);
50 section_data.extend(bytes);
51 }
52
53 let (symbol_header, symbol_data) = symbol_table.serialize_as_section();
55 let (relocation_header, relocation_data) = relocation_table.serialize();
56 headers.push(symbol_header);
57 headers.push(relocation_header);
58 section_data.extend(symbol_data);
59 section_data.extend(relocation_data);
60
61 for header in headers {
63 data.extend(header.serialize());
64 }
65 data.extend(section_data);
66
67 data
68 }
69
70 fn deserialize(data: &[u8]) -> Result<(usize, Self), SerializationError> {
71 if data.len() < 9 {
72 return Err(SerializationError::DataTooShort);
73 }
74
75 let (header_size, header) = ObjectHeader::deserialize(data)?;
77 let mut offset = header_size;
78
79 let mut headers = Vec::new();
81 for _ in 0..header.section_count {
82 if data.len() < offset + 16 {
83 return Err(SerializationError::DataTooShort);
85 }
86 let (size, section_header) = SectionHeader::deserialize(&data[offset..])?;
87 headers.push(section_header);
88 offset += size;
89 }
90
91 let section_count = headers.len();
93 if section_count < 2 {
94 return Err(SerializationError::InvalidData);
95 }
96 if !matches!(headers[section_count - 2], SectionHeader::SymbolTable(_)) {
97 return Err(SerializationError::InvalidData);
98 }
99 if !matches!(
100 headers[section_count - 1],
101 SectionHeader::RelocationTable(_)
102 ) {
103 return Err(SerializationError::InvalidData);
104 }
105
106 if headers[..section_count - 2].iter().any(|h| {
108 matches!(
109 h,
110 SectionHeader::SymbolTable(_) | SectionHeader::RelocationTable(_)
111 )
112 }) {
113 return Err(SerializationError::InvalidData);
114 }
115
116 let mut section_data_offset = offset;
118 for header in &headers[..section_count - 2] {
119 section_data_offset += header.section_size() as usize;
120 }
121
122 let symbol_offset = section_data_offset;
124 let (_, symbol_table) = SymbolTable::deserialize_section(
125 match &headers[section_count - 2] {
126 SectionHeader::SymbolTable(h) => h,
127 _ => unreachable!(),
128 },
129 &data[symbol_offset..],
130 )?;
131
132 let relocation_offset = symbol_offset + headers[section_count - 2].section_size() as usize;
133 let (_, relocation_table) = RelocationTable::deserialize(
134 match &headers[section_count - 1] {
135 SectionHeader::RelocationTable(h) => h,
136 _ => unreachable!(),
137 },
138 &data[relocation_offset..],
139 )?;
140
141 let mut sections = Vec::new();
143 let mut current_offset = offset;
144
145 for (idx, section_header) in headers[..section_count - 2].iter().enumerate() {
146 match section_header {
147 SectionHeader::Text(_) => {
148 let symbols = symbol_table.get_symbols(idx as u32);
149 let relocations = relocation_table.get_relocations(idx as u32);
150 let (size, section) = Section::deserialize(
151 section_header,
152 &data[current_offset..],
153 symbols,
154 relocations,
155 )?;
156 sections.push(section);
157 current_offset += size;
158 }
159 _ => return Err(SerializationError::InvalidData),
160 }
161 }
162
163 Ok((
164 relocation_offset + headers[section_count - 1].section_size() as usize,
165 ObjectFile {
166 architecture: header.architecture,
167 sections,
168 },
169 ))
170 }
171}
172
173impl ObjectFile {
174 pub fn new(architecture: Architecture) -> Self {
175 ObjectFile {
176 architecture,
177 sections: Vec::new(),
178 }
179 }
180
181 pub fn with_sections(architecture: Architecture, sections: Vec<Section>) -> Self {
182 ObjectFile {
183 architecture,
184 sections,
185 }
186 }
187
188 pub fn add_section(&mut self, section: Section) {
189 self.sections.push(section);
190 }
191
192 pub fn sections(self) -> Vec<Section> {
193 self.sections
194 }
195
196 pub fn architecture(&self) -> Architecture {
197 self.architecture
198 }
199
200 pub fn merge(&mut self, other: ObjectFile) {
201 if self.architecture != other.architecture {
202 panic!("Cannot merge object files with different architectures");
203 }
204 self.sections.extend(other.sections);
205 }
206}